/** * Render paste top button. Returns null if no button should be rendered. * * @param string $sorting The sorting mode. * * @return string */ protected function renderPasteTopButton($sorting) { $definition = $this->getEnvironment()->getDataDefinition(); $dispatcher = $this->getEnvironment()->getEventDispatcher(); $basicDefinition = $definition->getBasicDefinition(); $clipboard = $this->getEnvironment()->getClipboard(); $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); if ($sorting && $clipboard->isNotEmpty($filter)) { $allowPasteTop = ViewHelpers::getManualSortingProperty($this->environment); if ($allowPasteTop) { /** @var AddToUrlEvent $urlEvent */ $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent('act=paste&after=' . IdSerializer::fromValues($definition->getName(), 0)->getSerialized())); /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('pasteafter.gif', $this->translate('pasteafter.0', $definition->getName()), 'class="blink"')); return sprintf('<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>', $urlEvent->getUrl(), specialchars($this->translate('pasteafter.0', $definition->getName())), $imageEvent->getHtml()); } } return null; }
/** * Fetch actions from the clipboard. * * @param FilterInterface|null $filter The clipboard filter. * @param ModelIdInterface $parentModelId The parent id. * * @return array */ private function fetchModelsFromClipboard(FilterInterface $filter = null, ModelIdInterface $parentModelId = null) { $environment = $this->getEnvironment(); $dataDefinition = $environment->getDataDefinition(); if (!$filter) { $filter = new Filter(); } $basicDefinition = $dataDefinition->getBasicDefinition(); $modelProviderName = $basicDefinition->getDataProvider(); $filter->andModelIsFromProvider($modelProviderName); if ($parentModelId) { $filter->andParentIsFromProvider($parentModelId->getDataProviderName()); } else { $filter->andHasNoParent(); } $environment = $this->getEnvironment(); $clipboard = $environment->getClipboard(); $items = $clipboard->fetch($filter); $actions = array(); foreach ($items as $item) { $model = null; if (!$item->isCreate() && $item->getModelId()) { $modelId = $item->getModelId(); $dataProvider = $environment->getDataProvider($item->getDataProviderName()); $config = $dataProvider->getEmptyConfig()->setId($modelId->getId()); $model = $dataProvider->fetch($config); } $actions[] = array('model' => $model, 'item' => $item); } return $actions; }
/** * Calculate all clipboard items for the current view. * * @return ItemInterface[] */ private function calculateClipboardItems() { $dataDefinition = $this->environment->getDataDefinition(); $basicDefinition = $dataDefinition->getBasicDefinition(); $clipboard = $this->environment->getClipboard(); $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); if ($parentDataProviderName = $basicDefinition->getParentDataProvider()) { $filter->andParentIsFromProvider($parentDataProviderName); } else { $filter->andHasNoParent(); } return $clipboard->fetch($filter); }
/** * Handle view. * * @param ViewEvent $event The view event. * * @return void */ public function handleView(ViewEvent $event) { if (DcGeneralViews::CLIPBOARD !== $event->getViewName()) { return; } $environment = $event->getEnvironment(); $input = $environment->getInputProvider(); $clipboard = $environment->getClipboard(); $eventDispatcher = $environment->getEventDispatcher(); $basicDefinition = $environment->getDataDefinition()->getBasicDefinition(); $modelProviderName = $basicDefinition->getDataProvider(); $parentProviderName = $basicDefinition->getParentDataProvider(); $filter = new Filter(); $filter->andModelIsFromProvider($modelProviderName); if ($parentProviderName) { $filter->andParentIsFromProvider($parentProviderName); } else { $filter->andHasNoParent(); } $options = array(); foreach ($clipboard->fetch($filter) as $item) { $modelId = $item->getModelId(); $dataProvider = $environment->getDataProvider($item->getDataProviderName()); if ($modelId) { $config = $dataProvider->getEmptyConfig(); $config->setId($modelId->getId()); $model = $dataProvider->fetch($config); // The model might have been deleted meanwhile. if (!$model) { continue; } $formatModelLabelEvent = new FormatModelLabelEvent($environment, $model); $eventDispatcher->dispatch(DcGeneralEvents::FORMAT_MODEL_LABEL, $formatModelLabelEvent); $label = $formatModelLabelEvent->getLabel(); $label = array_shift($label); $label = $label['content']; } else { $model = $dataProvider->getEmptyModel(); $label = $environment->getTranslator()->translate('new.0', $item->getDataProviderName()); } $options[$item->getClipboardId()] = array('item' => $item, 'model' => $model, 'label' => $label); } $addToUrlEvent = new AddToUrlEvent('act=clear-clipboard&original-act=' . $input->getParameter('act')); $eventDispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, $addToUrlEvent); $clearUrl = $addToUrlEvent->getUrl(); $addToUrlEvent = new AddToUrlEvent('clipboard-item=%id%&act=clear-clipboard&original-act=' . $input->getParameter('act')); $eventDispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, $addToUrlEvent); $clearItemUrl = $addToUrlEvent->getUrl(); $template = new \BackendTemplate('dcbe_general_clipboard'); $template->setData(array('environment' => $environment, 'options' => $options, 'clearUrl' => $clearUrl, 'clearItemUrl' => $clearItemUrl)); $event->setResponse($template->parse()); }
/** * Test and sub filter. * * @dataProvider provideSubFilter() */ public function testOrSub($expected, FilterInterface $subFilter) { $item = new MockedAbstractItem(ItemInterface::CREATE); $firstSub = new MockedFilter(false); $filter = new Filter(); $filter->orSub($firstSub); $filter->orSub($subFilter); $this->assertEquals($expected, $filter->accepts($item)); }
/** * Create the "new" button. * * @return null|Command */ protected function getCreateModelCommand() { $environment = $this->getEnvironment(); $definition = $environment->getDataDefinition(); $basicDefinition = $definition->getBasicDefinition(); $providerName = $environment->getDataDefinition()->getName(); $mode = $basicDefinition->getMode(); $config = $this->getEnvironment()->getBaseConfigRegistry()->getBaseConfig(); if ($serializedPid = $environment->getInputProvider()->getParameter('pid')) { $pid = ModelId::fromSerialized($serializedPid); } else { $pid = null; } if (!$basicDefinition->isCreatable()) { return null; } $command = new Command(); $parameters = $command->getParameters(); $extra = $command->getExtra(); $extra['class'] = 'header_new'; $extra['accesskey'] = 'n'; $extra['attributes'] = 'onclick="Backend.getScrollOffset();"'; $command->setName('button_new')->setLabel($this->translate('new.0', $providerName))->setDescription($this->translate('new.1', $providerName)); $this->getPanel()->initialize($config); // Add new button. if ($mode == BasicDefinitionInterface::MODE_PARENTEDLIST || $mode == BasicDefinitionInterface::MODE_HIERARCHICAL) { $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); if ($parentDataProviderName = $basicDefinition->getParentDataProvider()) { $filter->andParentIsFromProvider($parentDataProviderName); } else { $filter->andHasNoParent(); } if ($environment->getClipboard()->isNotEmpty($filter)) { return null; } } $parameters['act'] = 'create'; // Add new button. if ($pid) { $parameters['pid'] = $pid->getSerialized(); } return $command; }
/** * 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); } }
/** * 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); } }
/** * Retrieve a list of html buttons to use in the top panel (submit area). * * @param ModelInterface $parentModel The parent model. * * @return string */ protected function getHeaderButtons($parentModel) { $environment = $this->getEnvironment(); $definition = $environment->getDataDefinition(); $clipboard = $environment->getClipboard(); $basicDefinition = $definition->getBasicDefinition(); $headerButtons = array(); if (!$this->isSelectModeActive()) { return ''; } $dispatcher = $environment->getEventDispatcher(); $objConfig = $this->getEnvironment()->getBaseConfigRegistry()->getBaseConfig(); $this->getPanel()->initialize($objConfig); $sorting = $objConfig->getSorting(); $headerButtons['editHeader'] = $this->getHeaderEditButtons($parentModel); $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); if ($parentDataProviderName = $basicDefinition->getParentDataProvider()) { $filter->andParentIsFromProvider($parentDataProviderName); } else { $filter->andHasNoParent(); } if ($sorting && $clipboard->isEmpty($filter) && $basicDefinition->isCreatable()) { /** @var AddToUrlEvent $urlEvent */ $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent('act=edit&pid=' . ModelId::fromModel($parentModel)->getSerialized())); /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('new.gif', $this->translate('pastenew.0', $definition->getName()))); $headerButtons['pasteNew'] = sprintf('<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>', $urlEvent->getUrl(), specialchars($this->translate('pastenew.1', $definition->getName())), $imageEvent->getHtml()); } $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); $filter->andParentIsFromProvider($basicDefinition->getParentDataProvider()); if ($sorting && $clipboard->isNotEmpty($filter)) { $allowPasteTop = ViewHelpers::getManualSortingProperty($this->environment); if (!$allowPasteTop) { $subFilter = new Filter(); $subFilter->andActionIsNotIn(array(ItemInterface::COPY, ItemInterface::DEEP_COPY)); $subFilter->andParentIsNot(ModelId::fromModel($parentModel)); $subFilter->orActionIsIn(array(ItemInterface::COPY, ItemInterface::DEEP_COPY)); $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); $filter->andParentIsFromProvider($basicDefinition->getParentDataProvider()); $filter->andSub($subFilter); $allowPasteTop = (bool) $clipboard->fetch($filter); } if ($allowPasteTop) { /** @var AddToUrlEvent $urlEvent */ $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent('act=paste' . '&pid=' . ModelId::fromModel($parentModel)->getSerialized())); /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('pasteafter.gif', $this->translate('pasteafter.0', $definition->getName()), 'class="blink"')); $headerButtons['pasteAfter'] = sprintf('<a href="%s" title="%s" onclick="Backend.getScrollOffset()">%s</a>', $urlEvent->getUrl(), specialchars($this->translate('pasteafter.0', $definition->getName())), $imageEvent->getHtml()); } else { /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent('pasteafter_.gif', $this->translate('pasteafter.0', $definition->getName()), 'class="blink"')); $headerButtons['pasteAfter'] = $imageEvent->getHtml(); } } return implode(' ', $headerButtons); }
/** * Check the buttons based on the action. * * @param ClipboardInterface $clipboard The clipboard. * * @param string $action The action to be checked. * * @return void */ protected function checkForAction($clipboard, $action) { // Make a filter for the given action. $filter = new Filter(); $filter->andActionIs($action); $items = $clipboard->fetch($filter); // Check if there are items. if ($items === null) { return; } /** @var ItemInterface[] $items */ foreach ($items as $item) { // Check the context. $itemProviderName = $item->getModelId()->getDataProviderName(); $modelId = $item->getModelId()->getId(); if ($this->providerName !== $itemProviderName) { continue; } $containedModel = $this->getModelById($modelId); if ($this->currentModel == null) { $this->checkForRoot($containedModel, $action); } elseif ($containedModel) { $this->checkForModel($containedModel, $action); } else { $this->checkEmpty($action); } } }
/** * 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&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); }
/** * Render the tree view. * * @param CollectionInterface $collection The collection of items. * * @return string */ protected function viewTree($collection) { $definition = $this->getDataDefinition(); $listing = $this->getViewSection()->getListingConfig(); $basicDefinition = $definition->getBasicDefinition(); $environment = $this->getEnvironment(); $dispatcher = $environment->getEventDispatcher(); // Init some Vars switch (6) { case 6: $treeClass = 'tree_xtnd'; break; default: $treeClass = 'tree'; } // Label + Icon. if (strlen($listing->getRootLabel()) == 0) { $strLabelText = 'DC General Tree BackendView Ultimate'; } else { $strLabelText = $listing->getRootLabel(); } if (strlen($listing->getRootIcon()) == 0) { $strLabelIcon = 'pagemounts.gif'; } else { $strLabelIcon = $listing->getRootIcon(); } $filter = new Filter(); $filter->andModelIsFromProvider($basicDefinition->getDataProvider()); if ($parentDataProviderName = $basicDefinition->getParentDataProvider()) { $filter->andParentIsFromProvider($parentDataProviderName); } else { $filter->andHasNoParent(); } // Root paste into. if ($environment->getClipboard()->isNotEmpty($filter)) { /** @var AddToUrlEvent $urlEvent */ $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent(sprintf('act=paste&into=%s::0', $definition->getName()))); $buttonEvent = new GetPasteRootButtonEvent($this->getEnvironment()); $buttonEvent->setHref($urlEvent->getUrl())->setPasteDisabled(false); $dispatcher->dispatch($buttonEvent::NAME, $buttonEvent); $strRootPasteInto = $this->renderPasteRootButton($buttonEvent); } else { $strRootPasteInto = ''; } /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent($strLabelIcon)); // Build template. $objTemplate = $this->getTemplate('dcbe_general_treeview'); $objTemplate->treeClass = 'tl_' . $treeClass; $objTemplate->tableName = $definition->getName(); $objTemplate->strLabelIcon = $imageEvent->getHtml(); $objTemplate->strLabelText = $strLabelText; $objTemplate->strHTML = $this->generateTreeView($collection, $treeClass); $objTemplate->strRootPasteinto = $strRootPasteInto; $objTemplate->select = $this->isSelectModeActive(); $objTemplate->selectButtons = $this->getSelectButtons(); $objTemplate->intMode = 6; // Add breadcrumb, if we have one. $strBreadcrumb = $this->breadcrumb(); if ($strBreadcrumb != null) { $objTemplate->breadcrumb = $strBreadcrumb; } return $objTemplate->parse(); }
/** * Add sub filter. * * @param string $conjunction AND or OR. * @param Filter $filter The sub filter. * * @return static */ private function sub($conjunction, Filter $filter) { if (!empty($this->expression)) { $this->expression[] = $conjunction; } $expression = $filter->getExpression(); $variables = $filter->getVariables(); $index = count($this->variables); $expression = str_replace('variables', 'variables[' . $index . ']', $expression); $this->expression[] = '(' . $expression . ')'; $this->variables[] = $variables; return $this; }