예제 #1
0
 /**
  * Test that the ModelId class can not be instantiated with invalid values.
  *
  * @param ModelInterface $model     The model to instantiate from.
  *
  * @param string|null    $exception The name of the expected exception class.
  *
  * @dataProvider modelProvider
  *
  * @return void
  */
 public function testInstantiationFromModel($model, $exception = null)
 {
     if (null !== $exception) {
         $this->setExpectedException($exception);
     }
     $modelId = ModelId::fromModel($model);
     $this->assertEquals($model->getId(), $modelId->getId());
     $this->assertEquals($model->getProviderName(), $modelId->getDataProviderName());
 }
 /**
  * Handle the event.
  *
  * @param HandleSubmitEvent $event The event.
  *
  * @return void
  */
 public function handleEvent(HandleSubmitEvent $event)
 {
     $dispatcher = func_get_arg(2);
     $currentUrl = $this->environment->get('uri');
     switch ($event->getButtonName()) {
         case 'save':
             // Could be a create action, always redirect to current page with edit action and id properly set.
             $url = UrlBuilder::fromUrl($currentUrl)->setQueryParameter('act', 'edit')->setQueryParameter('id', ModelId::fromModel($event->getModel())->getSerialized());
             $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($url->getUrl()));
             break;
         case 'saveNcreate':
             // We want to create a new model, set create action and pass the current id as "after" to keep sorting.
             $after = ModelId::fromModel($event->getModel());
             $url = UrlBuilder::fromUrl($currentUrl)->unsetQueryParameter('id')->setQueryParameter('act', 'create')->setQueryParameter('after', $after->getSerialized());
             $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($url->getUrl()));
             break;
         default:
             // Do nothing.
     }
 }
 /**
  * Do deep copy.
  *
  * @param array $deepCopyList The deep copy list.
  *
  * @return void
  */
 protected function doDeepCopy(array $deepCopyList)
 {
     if (empty($deepCopyList)) {
         return;
     }
     $factory = DcGeneralFactory::deriveFromEnvironment($this->getEnvironment());
     $dataDefinition = $this->getEnvironment()->getDataDefinition();
     $modelRelationshipDefinition = $dataDefinition->getModelRelationshipDefinition();
     $childConditions = $modelRelationshipDefinition->getChildConditions($dataDefinition->getName());
     foreach ($deepCopyList as $deepCopy) {
         /** @var ModelInterface $origin */
         $origin = $deepCopy['origin'];
         /** @var ModelInterface $model */
         $model = $deepCopy['model'];
         $parentId = ModelId::fromModel($model);
         foreach ($childConditions as $childCondition) {
             // create new destination environment
             $destinationName = $childCondition->getDestinationName();
             $factory->setContainerName($destinationName);
             $destinationEnvironment = $factory->createEnvironment();
             $destinationDataDefinition = $destinationEnvironment->getDataDefinition();
             $destinationViewDefinition = $destinationDataDefinition->getDefinition(Contao2BackendViewDefinitionInterface::NAME);
             $destinationDataProvider = $destinationEnvironment->getDataProvider();
             $destinationController = $destinationEnvironment->getController();
             /** @var Contao2BackendViewDefinitionInterface $destinationViewDefinition */
             /** @var DefaultController $destinationController */
             $listingConfig = $destinationViewDefinition->getListingConfig();
             $groupAndSortingCollection = $listingConfig->getGroupAndSortingDefinition();
             $groupAndSorting = $groupAndSortingCollection->getDefault();
             // ***** fetch the children
             $filter = $childCondition->getFilter($origin);
             // apply parent-child condition
             $config = $destinationDataProvider->getEmptyConfig();
             $config->setFilter($filter);
             // apply sorting
             $sorting = array();
             foreach ($groupAndSorting as $information) {
                 /** @var GroupAndSortingInformationInterface $information */
                 $sorting[$information->getProperty()] = $information->getSortingMode();
             }
             $config->setSorting($sorting);
             // receive children
             $children = $destinationDataProvider->fetchAll($config);
             // ***** do the deep copy
             $actions = array();
             // build the copy actions
             foreach ($children as $childModel) {
                 $childModelId = ModelId::fromModel($childModel);
                 $actions[] = array('model' => $childModel, 'item' => new Item(ItemInterface::DEEP_COPY, $parentId, $childModelId));
             }
             // do the deep copy
             $childrenModels = $destinationController->doActions($actions, null, null, $parentId);
             // ensure parent-child condition
             foreach ($childrenModels as $childrenModel) {
                 $childCondition->applyTo($model, $childrenModel);
             }
             $destinationDataProvider->saveEach($childrenModels);
         }
     }
 }
예제 #4
0
 /**
  * {@inheritdoc}
  */
 public function process()
 {
     $event = $this->getEvent();
     if ($event->getAction()->getName() !== 'copy') {
         return;
     }
     $environment = $this->getEnvironment();
     $modelId = ModelId::fromSerialized($environment->getInputProvider()->getParameter('source'));
     $this->guardValidEnvironment($modelId);
     // We want a redirect here if not creatable.
     $this->guardIsCreatable($modelId, true);
     if ($this->isEditOnlyResponse()) {
         return;
     }
     // Manual sorting mode. The ClipboardController should pick it up.
     $manualSortingProperty = ViewHelpers::getManualSortingProperty($environment);
     if ($manualSortingProperty && $this->environment->getDataProvider()->fieldExists($manualSortingProperty)) {
         return;
     }
     $copiedModel = $this->copy($modelId);
     $this->redirect($environment, ModelId::fromModel($copiedModel));
 }
예제 #5
0
 /**
  * Calculate the href for a command.
  *
  * @param CommandInterface $command The command.
  *
  * @param ModelInterface   $model   The current model.
  *
  * @return string
  */
 private function calculateHref(CommandInterface $command, $model)
 {
     $modelId = ModelId::fromModel($model)->getSerialized();
     $parameters = $this->calculateParameters($command, $modelId);
     $href = '';
     foreach ($parameters as $key => $value) {
         $href .= sprintf('&%s=%s', $key, $value);
     }
     return $this->addToUrl($href);
 }
예제 #6
0
 /**
  * Handle the submit and determine which button has been triggered.
  *
  * This method will redirect the client.
  *
  * @param ModelInterface $model The model that has been submitted.
  *
  * @return void
  *
  * @SuppressWarnings(PHPMD.Superglobals)
  * @SuppressWarnings(PHPMD.CamelCaseVariableName)
  */
 protected function handleSubmit(ModelInterface $model)
 {
     $environment = $this->getEnvironment();
     $dispatcher = $environment->getEventDispatcher();
     $inputProvider = $environment->getInputProvider();
     if ($inputProvider->hasValue('save')) {
         $newUrlEvent = new AddToUrlEvent('act=edit&id=' . ModelId::fromModel($model)->getSerialized());
         $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, $newUrlEvent);
         $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($newUrlEvent->getUrl()));
     } elseif ($inputProvider->hasValue('saveNclose')) {
         $this->clearBackendStates();
         $newUrlEvent = new GetReferrerEvent();
         $dispatcher->dispatch(ContaoEvents::SYSTEM_GET_REFERRER, $newUrlEvent);
         $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($newUrlEvent->getReferrerUrl()));
     } elseif ($inputProvider->hasValue('saveNcreate')) {
         $this->clearBackendStates();
         $after = ModelId::fromModel($model);
         $newUrlEvent = new AddToUrlEvent('act=create&id=&after=' . $after->getSerialized());
         $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, $newUrlEvent);
         $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($newUrlEvent->getUrl()));
     } elseif ($inputProvider->hasValue('saveNback')) {
         $this->clearBackendStates();
         $parentProviderName = $environment->getDataDefinition()->getBasicDefinition()->getParentDataProvider();
         $newUrlEvent = new GetReferrerEvent(false, $parentProviderName);
         $dispatcher->dispatch(ContaoEvents::SYSTEM_GET_REFERRER, $newUrlEvent);
         $dispatcher->dispatch(ContaoEvents::CONTROLLER_REDIRECT, new RedirectEvent($newUrlEvent->getReferrerUrl()));
     }
 }
예제 #7
0
파일: Subscriber.php 프로젝트: zonky2/core
 /**
  * Generate the paste button.
  *
  * @param GetPasteButtonEvent $event The event.
  *
  * @return void
  */
 public function generatePasteButton(GetPasteButtonEvent $event)
 {
     if ($event->getEnvironment()->getDataDefinition()->getName() !== 'tl_metamodel_filtersetting') {
         return;
     }
     $environment = $event->getEnvironment();
     $model = $event->getModel();
     $clipboard = $environment->getClipboard();
     $filter = new Filter();
     $filter->andModelIs(ModelId::fromModel($model))->andActionIs($clipboard::MODE_CUT);
     // Disable all buttons if there is a circular reference.
     if ($event->isCircularReference() || !$clipboard->isEmpty($filter)) {
         $event->setPasteAfterDisabled(true)->setPasteIntoDisabled(true);
         return;
     }
     $factory = $this->getServiceContainer()->getFilterFactory()->getTypeFactory($model->getProperty('type'));
     // If setting does not support children, omit them.
     if ($model->getId() && !($factory && $factory->isNestedType())) {
         $event->setPasteIntoDisabled(true);
     }
 }
예제 #8
0
 /**
  * Generate the paste button.
  *
  * @param GetPasteButtonEvent $event The event.
  *
  * @return void
  *
  * @SuppressWarnings(PHPMD.Superglobals)
  * @SuppressWarnings(PHPMD.CamelCaseVariableName)
  */
 public function generatePasteButton(GetPasteButtonEvent $event)
 {
     if ($event->getEnvironment()->getDataDefinition()->getName() !== 'tl_metamodel_dcasetting_condition') {
         return;
     }
     $environment = $event->getEnvironment();
     $model = $event->getModel();
     $clipboard = $environment->getClipboard();
     // Disable all buttons if there is a circular reference.
     if ($clipboard->fetch(Filter::create()->andActionIs(ItemInterface::CUT)->andModelIs(ModelId::fromModel($model)))) {
         $event->setPasteAfterDisabled(true)->setPasteIntoDisabled(true);
         return;
     }
     $flags = $GLOBALS['METAMODELS']['inputscreen_conditions'][$model->getProperty('type')];
     // If setting does not support children, omit them.
     if ($model->getId() && !$flags['nestingAllowed']) {
         $event->setPasteIntoDisabled(true);
         return;
     }
     if (isset($flags['maxChildren']) && count($event->getEnvironment()->getController()->assembleAllChildrenFrom($model)) > $flags['maxChildren']) {
         $event->setPasteIntoDisabled(true);
     }
 }
예제 #9
0
 /**
  * Retrieve a list of html buttons to use in the top panel (submit area).
  *
  * @param ModelInterface $parentModel The parent model.
  *
  * @return null|string
  */
 protected function getHeaderEditButtons($parentModel)
 {
     $environment = $this->getEnvironment();
     $parentDefinition = $environment->getParentDataDefinition();
     if ($parentDefinition && $parentDefinition->getBasicDefinition()->isEditable()) {
         $definition = $environment->getDataDefinition();
         $basicDefinition = $definition->getBasicDefinition();
         $parentName = $basicDefinition->getParentDataProvider();
         $dispatcher = $environment->getEventDispatcher();
         $query = array('do' => $environment->getInputProvider()->getParameter('do'), 'act' => 'edit', 'table' => $parentName, 'id' => ModelId::fromModel($parentModel)->getSerialized());
         $factory = DcGeneralFactory::deriveFromEnvironment($this->environment);
         $factory->setContainerName($parentDefinition->getName());
         $parentContainer = $factory->createContainer();
         if ($parentContainer->getBasicDefinition()->getParentDataProvider()) {
             $container = $this->environment->getDataDefinition();
             $relationship = $container->getModelRelationshipDefinition()->getChildCondition($parentContainer->getBasicDefinition()->getParentDataProvider(), $parentContainer->getName());
             if ($relationship) {
                 $filter = $relationship->getInverseFilterFor($parentModel);
                 $grandParentProvider = $this->environment->getDataProvider($parentContainer->getBasicDefinition()->getParentDataProvider());
                 $config = $grandParentProvider->getEmptyConfig();
                 $config->setFilter($filter);
                 $parents = $grandParentProvider->fetchAll($config);
                 if ($parents->length() == 1) {
                     $query['pid'] = ModelId::fromModel($parents->get(0))->getSerialized();
                 } elseif ($parents->length() > 1) {
                     return null;
                 }
             }
         }
         /** @var GenerateHtmlEvent $imageEvent */
         $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('edit.gif', $this->translate('editheader.0', $definition->getName())));
         return sprintf('<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>', 'contao/main.php?' . str_replace('%3A', ':', http_build_query($query)), specialchars($this->translate('editheader.1', $definition->getName())), $imageEvent->getHtml());
     }
     return null;
 }
예제 #10
0
 /**
  * Compile buttons from the table configuration array and return them as HTML.
  *
  * @param ModelInterface $model    The model for which the buttons shall be generated for.
  * @param ModelInterface $previous The previous model in the collection.
  * @param ModelInterface $next     The next model in the collection.
  *
  * @return string
  */
 protected function generateButtons(ModelInterface $model, ModelInterface $previous = null, ModelInterface $next = null)
 {
     $environment = $this->getEnvironment();
     $dataDefinition = $environment->getDataDefinition();
     $basicDefinition = $dataDefinition->getBasicDefinition();
     $commands = $this->getViewSection()->getModelCommands();
     $clipboard = $environment->getClipboard();
     $dispatcher = $environment->getEventDispatcher();
     $filter = new Filter();
     $filter->andModelIsFromProvider($basicDefinition->getDataProvider());
     if ($parentDataProviderName = $basicDefinition->getParentDataProvider()) {
         $filter->andParentIsFromProvider($parentDataProviderName);
     } else {
         $filter->andHasNoParent();
     }
     if ($clipboard->isNotEmpty($filter)) {
         $circularIds = $clipboard->getCircularIds();
         $isCircular = in_array(ModelId::fromModel($model)->getSerialized(), $circularIds);
     } else {
         $circularIds = array();
         $isCircular = false;
     }
     $arrButtons = array();
     foreach ($commands->getCommands() as $command) {
         $arrButtons[$command->getName()] = $this->buildCommand($command, $model, $isCircular, $circularIds, $previous, $next);
     }
     if (ViewHelpers::getManualSortingProperty($this->environment)) {
         $clipboardIsEmpty = $clipboard->isEmpty($filter);
         if ($clipboardIsEmpty && BasicDefinitionInterface::MODE_HIERARCHICAL !== $basicDefinition->getMode()) {
             /** @var AddToUrlEvent $urlEvent */
             $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent('act=create&amp;after=' . ModelId::fromModel($model)->getSerialized()));
             /** @var GenerateHtmlEvent $imageEvent */
             $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('new.gif', $this->translate('pastenew.0', $this->getDataDefinition()->getName())));
             $arrButtons['pasteNew'] = sprintf('<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>', $urlEvent->getUrl(), specialchars($this->translate('pastenew.1', $this->getDataDefinition()->getName())), $imageEvent->getHtml());
         }
         // Add paste into/after icons.
         if (!$clipboardIsEmpty) {
             if ($clipboard->isCreate()) {
                 // Add ext. information.
                 $add2UrlAfter = sprintf('act=create&after=%s&', ModelId::fromModel($model)->getSerialized());
                 $add2UrlInto = sprintf('act=create&into=%s&', ModelId::fromModel($model)->getSerialized());
             } else {
                 // Add ext. information.
                 $add2UrlAfter = sprintf('act=paste&after=%s&', ModelId::fromModel($model)->getSerialized());
                 $add2UrlInto = sprintf('act=paste&into=%s&', ModelId::fromModel($model)->getSerialized());
             }
             /** @var AddToUrlEvent $urlAfter */
             $urlAfter = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent($add2UrlAfter));
             /** @var AddToUrlEvent $urlInto */
             $urlInto = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent($add2UrlInto));
             $models = $this->environment->getController()->getModelsFromClipboard($parentDataProviderName ? IdSerializer::fromValues($parentDataProviderName, null) : null);
             $buttonEvent = new GetPasteButtonEvent($this->getEnvironment());
             $buttonEvent->setModel($model)->setCircularReference($isCircular)->setPrevious($previous)->setNext($next)->setHrefAfter($urlAfter->getUrl())->setHrefInto($urlInto->getUrl())->setPasteAfterDisabled($clipboard->isCut() && $isCircular)->setPasteIntoDisabled($clipboard->isCut() && $isCircular)->setContainedModels($models);
             $this->getEnvironment()->getEventDispatcher()->dispatch(GetPasteButtonEvent::NAME, $buttonEvent);
             $arrButtons['pasteafter'] = $this->renderPasteAfterButton($buttonEvent);
             if ($this->getDataDefinition()->getBasicDefinition()->getMode() == BasicDefinitionInterface::MODE_HIERARCHICAL) {
                 $arrButtons['pasteinto'] = $this->renderPasteIntoButton($buttonEvent);
             }
         }
     }
     return implode(' ', $arrButtons);
 }
예제 #11
0
 /**
  * Serialize a model and return its ID.
  *
  * @param ModelInterface $model The model.
  *
  * @return string
  */
 public function serializeModelId(ModelInterface $model)
 {
     return ModelId::fromModel($model)->getSerialized();
 }
예제 #12
0
 /**
  * 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);
         }
     }
 }
예제 #13
0
 /**
  * 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);
     }
 }