Current Path : /proc/4653/cwd/wp-content/plugins/ninja-forms/includes/Handlers/ |
Current File : //proc/4653/cwd/wp-content/plugins/ninja-forms/includes/Handlers/SubmissionAggregate.php |
<?php namespace NinjaForms\Includes\Handlers; use NinjaForms\Includes\Contracts\SubmissionDataSource; use NinjaForms\Includes\Entities\SingleSubmission; use NinjaForms\Includes\Entities\SubmissionField; use NinjaForms\Includes\Entities\SubmissionFilter; use NinjaForms\Includes\Handlers\Field; /** * Aggregates submissions from all provided data sources * * Data sources include NF submissions stored as posts; may include pre-existing * Caldera Forms submissions */ class SubmissionAggregate { /** * NF Id of the master form * * There can be multiple forms in the aggregate; the master form defines the * fields and the data within the aggregate. * * @var string */ protected $masterFormId = ''; /** @var SubmissionFilter */ protected $submissionFilter; /** * Collection of submission data sources * * @var SubmissionDataSource[]; */ protected $dataSourceCollection = []; /** * Collection of all SingleSubmissions * * Indexed collection of submissions meeting the filtering parameters * * @var SingleSubmission[] */ protected $aggregatedSubmissions = []; /** * Collection of SubmissionFields defining the form * * @var SubmissionField[] */ protected $submissionFieldCollection = []; /** * Filter submissions to return a collection of SingleSubmission meta data only * * @param string $formId * @return array */ public function filterSubmissions(SubmissionFilter $submissionFilter): array { $this->submissionFilter = $submissionFilter; $formIdCollection = $this->submissionFilter->getNfFormIds(); if (!empty($formIdCollection)) { $masterFormId = $formIdCollection[0]; $this->constructFieldDefinitionCollection($masterFormId); } $aggregated = []; if (!empty($this->dataSourceCollection)) { foreach ($this->dataSourceCollection as $dataSource) { $submissionsFromDataSource = $dataSource->retrieveSubmissionMeta($this->submissionFilter); $aggregated = array_merge($aggregated, $submissionsFromDataSource); } } foreach ($aggregated as $singleSubmission) { $key = $this->constructUniqueAgreggatedSubmissionKey($singleSubmission); $submissionIDs = $this->submissionFilter->getSubmissionsIDs(); //Add singleSubmission to aggregated collection if no submissions IDs were set or if it has correct ID if( in_array( $singleSubmission->submissionRecordId, $submissionIDs ) || empty( $submissionIDs ) ){ $this->aggregatedSubmissions[$key] = $singleSubmission; } } uasort($this->aggregatedSubmissions, function ($a, $b) { return $b->getTimestamp() <=> $a->getTimestamp(); }); return $this->aggregatedSubmissions; } /** * Retrieve a single submission populated with submission/extra values * * Also populates the submissionAggregate such that the aggregate can be * passed for handling elsewhere * * @param SingleSubmission $singleSubmission * @return SingleSubmission */ public function requestSingleSubmission(SingleSubmission $singleSubmission): SingleSubmission { $this->masterFormId = $singleSubmission->getFormId(); $this->constructFieldDefinitionCollection($this->masterFormId); $singleSubmission->setSubmissionFieldCollection($this->submissionFieldCollection); $dataSourceKey = $singleSubmission->getDataSource(); if(isset($this->dataSourceCollection[$dataSourceKey])){ $dataSource=$this->dataSourceCollection[$dataSourceKey]; $singleSubmission = $dataSource->retrieveSingleSubmission($singleSubmission); } $key = $this->constructUniqueAgreggatedSubmissionKey($singleSubmission); $this->aggregatedSubmissions[$key] = $singleSubmission; return $singleSubmission; } /** * Retrieve a submissions by precise list of submissions IDs * * @param SubmissionFilter $submissionFilter * @return SubmissionFilter */ public function requestSubmissionsByIds(SubmissionFilter $submissionFilter): SubmissionFilter { $this->masterFormId = $singleSubmission->getFormId(); $this->constructFieldDefinitionCollection($this->masterFormId); $submissions->setSubmissionFieldCollection($this->submissionFieldCollection); $dataSourceKey = $singleSubmission->getDataSource(); if(isset($this->dataSourceCollection[$dataSourceKey])){ $dataSource=$this->dataSourceCollection[$dataSourceKey]; $singleSubmission = $dataSource->retrieveSingleSubmission($singleSubmission); } $key = $this->constructUniqueAgreggatedSubmissionKey($singleSubmission); $this->aggregatedSubmissions[$key] = $singleSubmission; return $singleSubmission; } /** * Retrieve submissionValues from submission at a given aggregated key * * @param string $key * @return SingleSubmission * @see constructUniqueAgreggatedSubmissionKey() */ public function getSubmissionValuesByAggregatedKey(string $key): SingleSubmission { /** @var SubmissionDataSource $dataSource */ if (isset($this->aggregatedSubmissions[$key])) { $singleSubmission = $this->aggregatedSubmissions[$key]; if (empty($singleSubmission->getSubmissionFieldCollection())) { $singleSubmission->setSubmissionFieldCollection($this->submissionFieldCollection); $dataSource = $this->dataSourceCollection[$singleSubmission->getDataSource()]; $populatedSingleSubmission = $dataSource->retrieveSubmissionValues($singleSubmission); } else { $populatedSingleSubmission = $singleSubmission; } } else { $populatedSingleSubmission = SingleSubmission::fromArray([]); } // create a new object to avoid object-by-reference that updates all submissions in the collection $this->aggregatedSubmissions[$key] = SingleSubmission::fromArray($populatedSingleSubmission->toArray()); return $this->aggregatedSubmissions[$key]; } /** * Delete a single submission * * @param SingleSubmission $singleSubmission * @return SubmissionAggregate */ public function deleteSingleSubmission(SingleSubmission $singleSubmission): SubmissionAggregate { $dataSourceKey = $singleSubmission->getDataSource(); if(isset($this->dataSourceCollection[$dataSourceKey])){ $dataSource = $this->dataSourceCollection[$dataSourceKey]; $dataSource->deleteSubmission($singleSubmission); } return $this; } /** * Restore a single submission * * @param SingleSubmission $singleSubmission * @return SubmissionAggregate */ public function restoreSingleSubmission(SingleSubmission $singleSubmission): SubmissionAggregate { $dataSourceKey = $singleSubmission->getDataSource(); if(isset($this->dataSourceCollection[$dataSourceKey])){ $dataSource = $this->dataSourceCollection[$dataSourceKey]; $dataSource->restoreSubmission($singleSubmission); } return $this; } /** * Update a single submission * * @param SingleSubmission $singleSubmission * @return SubmissionAggregate */ public function updateSingleSubmission(SingleSubmission $singleSubmission): SubmissionAggregate { $dataSourceKey = $singleSubmission->getDataSource(); if(isset($this->dataSourceCollection[$dataSourceKey])){ $dataSource = $this->dataSourceCollection[$dataSourceKey]; $dataSource->updateSubmission($singleSubmission); } return $this; } /** * Construct field definition collection from formId * * @param string $formId * @return void */ protected function constructFieldDefinitionCollection(string $formId): void { $nfFieldsCollection = $this->getFieldsCollection($formId); if (!empty($nfFieldsCollection)) { /** @var Field $nfField */ foreach ($nfFieldsCollection as $id => $nfField) { $slug = $nfField->get_setting('key'); $fieldSettings = $nfField->get_settings(); $fieldOptionDefinition = $nfField->get_setting('options',[]); $fieldsetRepeaterFields = $nfField->get_setting('fields',[]); if(!empty($fieldOptionDefinition)){ foreach($fieldOptionDefinition as $optionDefinition){ $options = $this->extractOptionsFromDefinition($optionDefinition); $optionsCollection[]=$options; } }else{ $optionsCollection = []; } $array = [ 'id' => (string)$id, 'slug' => $slug, 'label' => $nfField->get_setting('label'), 'adminLabel' => $nfField->get_setting('admin_label'), 'type' => $nfField->get_setting('type'), 'options' => $optionsCollection, 'fieldsetRepeaterFields'=>$fieldsetRepeaterFields, 'original' => $fieldSettings ]; $this->submissionFieldCollection[$slug] = SubmissionField::fromArray($array); } } } /** * Extract option array from a given array * * Ensures that required defaults are set if missing in incoming array * * @param array $optionDefinition * @return array */ protected function extractOptionsFromDefinition(array $optionDefinition): array { $defaults = [ 'label' => '', 'value' => '', 'calc' => '', 'selected' => 0, 'order' => 0 ]; $return = array_merge($defaults, \array_intersect_key($optionDefinition, $defaults)); return $return; } /** * Return the Ninja Forms field collection * * @param string $formId * @return array */ protected function getFieldsCollection(string $formId): array { $return = \Ninja_Forms()->form($formId)->get_fields(); return $return; } /** * Construct a unique aggregated submission key for each submission * * Uses the dataSource's id plus the submission record id. Each submission * is is unique within its dataSource, and each dataSource is unique, thus * the combined string is unique * * @param SingleSubmission $singleSubmission * @return string */ protected function constructUniqueAgreggatedSubmissionKey(SingleSubmission $singleSubmission): string { $key = $singleSubmission->getDataSource() . '__' . $singleSubmission->getSubmissionRecordId(); return $key; } /** * Set collection of submission data sources * * @param SubmissionDataSource $dataSource Submission data source * * @return SubmissionAggregate */ public function addDataSource(SubmissionDataSource $dataSource): SubmissionAggregate { $this->dataSourceCollection[$dataSource->getDataSource()] = $dataSource; return $this; } /** * Get collection of SubmissionFields * * @return SubmissionField[] */ public function getFieldDefinitionCollection(): array { return $this->submissionFieldCollection; } /** * Get submission count * * @return integer */ public function getSubmissionCount(): int { return count($this->aggregatedSubmissions); } /** * Get indexed collection of submissions meeting the filtering parameters * * @return SingleSubmission[] */ public function getAggregatedSubmissions(): array { return $this->aggregatedSubmissions; } /** * Get fields and the data within the aggregate. * * @return string */ public function getMasterFormId(): string { return $this->masterFormId; } /** * Set keyed collection of submissions * * This method enables re-setting the aggregated submissions after * performing array methods on it. This is useful to get a subset of the * collection without needing to re-filter and run DB requests * * @param Array $aggregatedSubmissions Keyed collection of * submissions meeting the filtering parameters * * @return self */ public function setAggregatedSubmissions(Array $aggregatedSubmissions) { $this->aggregatedSubmissions = $aggregatedSubmissions; return $this; } }