/** * Fetch the model. * * @param ModelIdInterface $modelId The model id. * * @return ModelInterface * * @throws DcGeneralRuntimeException If no model are found. */ protected function fetchModel(ModelIdInterface $modelId) { $dataProvider = $this->getEnvironment()->getDataProvider($modelId->getDataProviderName()); $model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId())); if (!$model || !$model->getId()) { throw new DcGeneralRuntimeException('Could not load model with id ' . $modelId->getSerialized()); } return $model; }
/** * Get the id which identifies the item in the clipboard. * * @return string */ public function getClipboardId() { if ($this->modelId) { return $this->getAction() . $this->modelId->getSerialized() . (($parentId = $this->getParentId()) ? $parentId->getSerialized() : 'null'); } else { return $this->getAction() . $this->getDataProviderName() . (($parentId = $this->getParentId()) ? $parentId->getSerialized() : 'null'); } }
/** * Guard that the data container is not in edit only mode. * * @param ModelIdInterface $modelId The model id. * * @return void * * @throws EditOnlyModeException If data container is in edit only mode. */ protected function guardNotEditOnly(ModelIdInterface $modelId) { if ($this->getEnvironment()->getDataDefinition()->getBasicDefinition()->isEditOnlyMode()) { throw new EditOnlyModeException($modelId->getDataProviderName()); } }
/** * Apply sorting and persist all models. * * @param array $actions The actions collection. * @param ModelIdInterface $after The previous model id. * @param ModelIdInterface $into The hierarchical parent model id. * @param ModelIdInterface $parentModelId The parent model id. * @param array $items Write-back clipboard items. * * @return DefaultCollection|ModelInterface[] * * @throws DcGeneralRuntimeException When the parameters for the pasting destination are invalid. */ private function sortAndPersistModels(array $actions, ModelIdInterface $after = null, ModelIdInterface $into = null, ModelIdInterface $parentModelId = null, array &$items = array()) { $environment = $this->getEnvironment(); $dataDefinition = $environment->getDataDefinition(); $manualSorting = ViewHelpers::getManualSortingProperty($environment); /** @var DefaultCollection|ModelInterface[] $models */ $models = new DefaultCollection(); foreach ($actions as $action) { $models->push($action['model']); $items[] = $action['item']; } // Trigger for each model the pre persist event. foreach ($models as $model) { $event = new PrePasteModelEvent($environment, $model); $environment->getEventDispatcher()->dispatch($event::NAME, $event); } if ($after && $after->getId()) { $dataProvider = $environment->getDataProvider($after->getDataProviderName()); $previous = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($after->getId())); $this->pasteAfter($previous, $models, $manualSorting); } elseif ($into && $into->getId()) { $dataProvider = $environment->getDataProvider($into->getDataProviderName()); $parent = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($into->getId())); $this->pasteInto($parent, $models, $manualSorting); } elseif ($after && $after->getId() == '0' || $into && $into->getId() == '0') { if ($dataDefinition->getBasicDefinition()->getMode() === BasicDefinitionInterface::MODE_HIERARCHICAL) { foreach ($models as $model) { // Paste top means root in hierarchical mode! $this->setRootModel($model); } } $this->pasteTop($models, $manualSorting, $parentModelId); } elseif ($parentModelId) { if ($manualSorting) { $this->pasteTop($models, $manualSorting, $parentModelId); } else { $dataProvider = $environment->getDataProvider(); $dataProvider->saveEach($models); } } else { throw new DcGeneralRuntimeException('Invalid parameters.'); } // Trigger for each model the past persist event. foreach ($models as $model) { $event = new PostPasteModelEvent($environment, $model); $environment->getEventDispatcher()->dispatch($event::NAME, $event); } return $models; }
/** * Retrieve the base data provider config for the current data definition. * * This includes parent filter when in parented list mode and the additional filters from the data definition. * * @param ModelIdInterface $parentId The optional parent to use. * * @return ConfigInterface */ public function getBaseConfig(ModelIdInterface $parentId = null) { $key = $parentId ? $parentId->getSerialized() : null; if (!isset($this->configs[$key])) { $this->configs[$key] = $this->buildBaseConfig($parentId); } return clone $this->configs[$key]; }
/** * Redirect to edit mask. * * @param EnvironmentInterface $environment The environment. * @param ModelIdInterface $copiedModelId The model id. * * @return void */ protected function redirect($environment, $copiedModelId) { // Build a clean url to remove the copy related arguments instad of using the AddToUrlEvent. $url = new BackendUrlBuilder(); $url->setPath('contao/main.php')->setQueryParameter('do', $environment->getInputProvider()->getParameter('do'))->setQueryParameter('table', $copiedModelId->getDataProviderName())->setQueryParameter('act', 'edit')->setQueryParameter('id', $copiedModelId->getSerialized()); $redirectEvent = new RedirectEvent($url->getUrl()); $environment->getEventDispatcher()->dispatch(ContaoEvents::CONTROLLER_REDIRECT, $redirectEvent); }
/** * {@inheritDoc} */ public function hasId(ModelIdInterface $modelId) { return isset($this->itemsByModelId[$modelId->getSerialized()]); }
/** * {@inheritdoc} */ public function getClipboardId() { return $this->getAction() . ($this->modelId ? $this->modelId->getSerialized() : 'null') . (($parentId = $this->getParentId()) ? $parentId->getSerialized() : 'null'); }
/** * {@inheritdoc} */ public function equals(ModelIdInterface $modelId) { // It is exactly the same id if ($this === $modelId) { return true; } return !($this->getDataProviderName() !== $modelId->getDataProviderName() || $this->getId() !== $modelId->getId()); }
/** * {@inheritDoc} */ public function hasId(ModelIdInterface $modelId) { $serializedId = $modelId->getSerialized(); return isset($this->items[$serializedId]); }
/** * Delete all deep models. * * @param ModelIdInterface $modelId The Model Id. * * @return void * * @SuppressWarnings(PHPMD.LongVariableName) */ protected function deepDelete(ModelIdInterface $modelId) { $environment = $this->getEnvironment(); $dataDefinition = $environment->getDataDefinition(); /** @var DefaultModelRelationshipDefinition $relationships */ $relationships = $dataDefinition->getDefinition('model-relationships'); $childConditions = $relationships->getChildConditions($modelId->getDataProviderName()); // delete child element before delete parent element /** @var ParentChildConditionInterface $childCondition */ foreach ($childConditions as $childCondition) { $destinationChildConditions = $relationships->getChildConditions($childCondition->getDestinationName()); if (empty($destinationChildConditions)) { continue; } $dataProvider = $environment->getDataProvider($modelId->getDataProviderName()); $model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId())); $destinationChildDataProvider = $environment->getDataProvider($childCondition->getDestinationName()); $filters = $childCondition->getFilter($model); /** @var DefaultCollection $destinationChildModels */ $destinationChildModels = $destinationChildDataProvider->fetchAll($dataProvider->getEmptyConfig()->setFilter($filters)); if ($destinationChildModels->count() < 1) { continue; } foreach ($destinationChildModels as $destinationChildModel) { $this->deepDelete(ModelId::fromModel($destinationChildModel)); } } foreach ($childConditions as $childCondition) { $dataProvider = $environment->getDataProvider($modelId->getDataProviderName()); $model = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId())); $childDataProvider = $environment->getDataProvider($childCondition->getDestinationName()); $filters = $childCondition->getFilter($model); /** @var DefaultCollection $childModels */ $childModels = $childDataProvider->fetchAll($dataProvider->getEmptyConfig()->setFilter($filters)); if ($childModels->count() < 1) { continue; } foreach ($childModels as $childModel) { // Trigger event before the model will be deleted. $event = new PreDeleteModelEvent($this->getEnvironment(), $childModel); $environment->getEventDispatcher()->dispatch($event::NAME, $event); $childDataProvider->delete($childModel); // Trigger event after the model is deleted. $event = new PostDeleteModelEvent($environment, $childModel); $environment->getEventDispatcher()->dispatch($event::NAME, $event); } } }
/** * Copy each children. * * @param ModelIdInterface $modelId The model id. * @param ModelInterface $copiedModel The copied model. * @param EnvironmentInterface $environment The environment. * * @return void * * @SuppressWarnings(PHPMD.LongVariableName) */ protected function copyEachChilds(ModelIdInterface $modelId, ModelInterface $copiedModel, EnvironmentInterface $environment) { $childDataProviderName = $environment->getInputProvider()->getParameter('ctable'); $dataProvider = $environment->getDataProvider(); $childDataProvider = $environment->getDataProvider($childDataProviderName); $modelRelationship = $environment->getParentDataDefinition()->getModelRelationshipDefinition(); $childCondition = $modelRelationship->getChildCondition($copiedModel->getProviderName(), $childDataProviderName); if (!$childCondition) { return; } $parentModel = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($modelId->getId())); $parentFilters = $childCondition->getFilter($parentModel); $copiedFilters = $childCondition->getFilter($copiedModel); $filter = array(); // Todo can many filter has operation equal foreach ($parentFilters as $index => $parentFilter) { if ($parentFilter['operation'] !== '=') { continue; } $filter = array('parent' => $parentFilter, 'copied' => $copiedFilters[$index]); } $childModels = $childDataProvider->fetchAll($childDataProvider->getEmptyConfig()->setFilter(array($filter['parent']))); if ($childModels->count() < 1) { return; } foreach ($childModels->getModelIds() as $index => $modelId) { $childModel = $childModels->get($index); $copyModelId = ModelId::fromModel($childModel); $copiedChildModel = null; if ($environment->getDataDefinition()->getName() !== $copyModelId->getDataProviderName()) { $copiedChildModel = $this->copyParent($copyModelId, $environment); } if ($environment->getDataDefinition()->getName() === $copyModelId->getDataProviderName() && !$copiedChildModel) { $copiedChildModel = $this->copyHandler($copyModelId, $environment); } $copiedChildModel->setProperty($filter['copied']['property'], $filter['copied']['value']); $childDataProvider->save($copiedChildModel); } }