/** * Create a new instance. * * @param string $strTable The table name. * * @param array $arrBackendModule The backend module information array. */ public function __construct($strTable, array &$arrBackendModule = null) { $strTable = $this->getTablenameCallback($strTable); $dispatcher = $GLOBALS['container']['event-dispatcher']; /** @var \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */ $dispatcher->addListener(PopulateEnvironmentEvent::NAME, array($this, 'handlePopulateEnvironment'), 4800); $propagator = new EventPropagator($dispatcher); $translator = new TranslatorChain(); $translator->add(new LangArrayTranslator($dispatcher)); $factory = new DcGeneralFactory(); $factory->setContainerName($strTable)->setEventPropagator($propagator)->setTranslator($translator)->createDcGeneral(); $dispatcher->removeListener(PopulateEnvironmentEvent::NAME, array($this, 'handlePopulateEnvironment')); // Switch user for FE / BE support. switch (TL_MODE) { case 'FE': $this->import('FrontendUser', 'User'); break; default: case 'BE': $this->import('BackendUser', 'User'); break; } // Load the clipboard. $this->getEnvironment()->getClipboard()->loadFrom($this->getEnvironment()); // Execute AJAX request, called from Backend::getBackendModule // we have to do this here, as otherwise the script will exit as it only checks for DC_Table and DC_File // derived classes. // @codingStandardsIgnoreStart - The access to $_POST is sane here. if ($_POST && (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest')) { $this->getViewHandler()->handleAjaxCall(); } }
/** * Create a new instance. * * @param string $strTable The table name. * * @SuppressWarnings(PHPMD.CamelCaseVariableName) * @SuppressWarnings(PHPMD.Superglobals) */ public function __construct($strTable) { $strTable = $this->getTablenameCallback($strTable); $translator = $this->getTranslator(); $dispatcher = $this->getEventDispatcher(); $dispatcher->addListener(PopulateEnvironmentEvent::NAME, array($this, 'handlePopulateEnvironment'), 4800); $factory = new DcGeneralFactory(); $factory->setContainerName($strTable)->setEventDispatcher($dispatcher)->setTranslator($translator)->createDcGeneral(); $dispatcher->removeListener(PopulateEnvironmentEvent::NAME, array($this, 'handlePopulateEnvironment')); // Load the clipboard. $this->getEnvironment()->getClipboard()->loadFrom($this->getEnvironment()); // Execute AJAX request, called from Backend::getBackendModule // we have to do this here, as otherwise the script will exit as it only checks for DC_Table and DC_File // derived classes. $this->checkAjaxCall(); }
/** * @param array $options * * @return array */ public function getImportableRecipientFieldOptions($options = array()) { global $container; // todo issue to dc-general \System::loadLanguageFile('orm_avisota_recipient'); /** @var EventDispatcher $eventDispatcher */ $eventDispatcher = $container['event-dispatcher']; $dcGeneralFactory = new DcGeneralFactory(); $dcGeneralFactory->setContainerName('orm_avisota_recipient'); $dcGeneralFactory->setEventDispatcher($eventDispatcher); $containerFactory = $dcGeneralFactory->createContainer(); foreach ($containerFactory->getPropertiesDefinition()->getProperties() as $property) { $extra = $property->getExtra(); if (isset($extra['importable']) && $extra['importable']) { $options[$property->getName()] = $property->getLabel(); } } return $options; }
/** * Create a new factory with basic settings from the environment. * * This factory can be used to create a new Container, Environment, DcGeneral with the same base settings as the * given environment. * * @param EnvironmentInterface $environment The environment to use as base. * * @return DcGeneralFactory */ public static function deriveEmptyFromEnvironment(EnvironmentInterface $environment) { $factory = new DcGeneralFactory(); $factory->setEventDispatcher($environment->getEventDispatcher()); $factory->setEventDispatcher($environment->getEventDispatcher()); $factory->setTranslator($environment->getTranslator()); $factory->setEnvironmentClassName(get_class($environment)); $factory->setContainerClassName(get_class($environment->getDataDefinition())); return $factory; }
/** * @param array $options * @param DC_General|DcCompat $general * * @return array */ public function getRecipientFieldOptions(DC_General $general, $options = array()) { global $container; //TODO check general parameter /** @var EventDispatcher $eventDispatcher */ $eventDispatcher = $container['event-dispatcher']; $eventDispatcher->dispatch(ContaoEvents::SYSTEM_LOAD_LANGUAGE_FILE, new LoadLanguageFileEvent('orm_avisota_recipient')); $eventDispatcher->dispatch(ContaoEvents::CONTROLLER_LOAD_DATA_CONTAINER, new LoadDataContainerEvent('orm_avisota_recipient')); $factory = DcGeneralFactory::deriveFromEnvironment($general->getEnvironment()); $factory->setContainerName('orm_avisota_recipient'); $containerFactory = $factory->createContainer(); if ($containerFactory->hasPropertiesDefinition()) { $properties = $containerFactory->getPropertiesDefinition()->getProperties(); foreach ($properties as $property) { if ($property->getWidgetType()) { $options[$property->getName()] = $property->getLabel(); } } } return $options; }
/** * @param EnvironmentInterface $environment * @param array $options * * @return array * @SuppressWarnings(PHPMD.LongVariable) */ public function getRecipientPropertiesOptions(EnvironmentInterface $environment, $options = array()) { global $container; if (!is_array($options)) { $options = (array) $options; } /** @var EventDispatcher $eventDispatcher */ $eventDispatcher = $container['event-dispatcher']; $loadDataContainerEvent = new LoadDataContainerEvent('orm_avisota_recipient'); $eventDispatcher->dispatch(ContaoEvents::CONTROLLER_LOAD_DATA_CONTAINER, $loadDataContainerEvent); $loadLanguageFileEvent = new LoadLanguageFileEvent('orm_avisota_recipient'); $eventDispatcher->dispatch(ContaoEvents::SYSTEM_LOAD_LANGUAGE_FILE, $loadLanguageFileEvent); $dcGeneralFactory = DcGeneralFactory::deriveFromEnvironment($environment); $dcGeneralFactory->setContainerName('orm_avisota_recipient'); $containerFactory = $dcGeneralFactory->createContainer(); $properties = $containerFactory->getPropertiesDefinition()->getProperties(); foreach ($properties as $property) { $options[$property->getName()] = $property->getLabel() ?: $property->getName(); } return $options; }
/** * 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); } } }
/** * Load additional definitions, like naming of parent data provider. * * This method will register an event to the populate environment event in which the parent data provider container * will get loaded. * * @param ContainerInterface $container The container where the data shall be stored. * * @return void */ protected function loadAdditionalDefinitions(ContainerInterface $container) { if ($this->getFromDca('config/ptable')) { $containerName = $container->getName(); $this->getDispatcher()->addListener(PopulateEnvironmentEvent::NAME, function (PopulateEnvironmentEvent $event) use($containerName) { $environment = $event->getEnvironment(); $definition = $environment->getDataDefinition(); if ($definition->getName() !== $containerName) { return; } $parentName = $definition->getBasicDefinition()->getParentDataProvider(); $factory = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($parentName); $parentDefinition = $factory->createContainer(); $environment->setParentDataDefinition($parentDefinition); }); } }
/** * Create the dc-general and return it's environment instance. * * @param string $containerName The name of the data container to edit. * * @return EnvironmentInterface */ private function createDcGeneral($containerName) { $factory = new DcGeneralFactory(); $dcGeneral = $factory->setContainerName($containerName)->setEventDispatcher($this->dispatcher)->setTranslator($this->translator)->createDcGeneral(); return $dcGeneral->getEnvironment(); }
/** * Retrieve a list of html buttons to use in the top panel (submit area). * * @param ModelInterface $parentModel The parent model. * * @return array */ protected function getHeaderEditButtons($parentModel) { $environment = $this->getEnvironment(); $parentDefinition = $environment->getParentDataDefinition(); if ($parentDefinition && $parentDefinition->getBasicDefinition()->isEditable()) { $definition = $environment->getDataDefinition(); $basicDefinition = $definition->getBasicDefinition(); $parentName = $basicDefinition->getParentDataProvider(); $propagator = $environment->getEventPropagator(); $query = array('do' => $environment->getInputProvider()->getParameter('do'), 'act' => 'edit', 'table' => $parentName, 'id' => IdSerializer::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); $parentsParentProvider = $this->environment->getDataProvider($parentContainer->getBasicDefinition()->getParentDataProvider()); $config = $parentsParentProvider->getEmptyConfig(); $config->setFilter($filter); $parents = $parentsParentProvider->fetchAll($config); if ($parents->length() == 1) { $query['pid'] = IdSerializer::fromModel($parents->get(0))->getSerialized(); } elseif ($parents->length() > 1) { return null; } } } /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $propagator->propagate(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?' . http_build_query($query), specialchars($this->translate('editheader.1', $definition->getName())), $imageEvent->getHtml()); } return null; }
/** * @param ActionEvent $event * @param null $eventName * @param EventDispatcherInterface|null $eventDispatcher * @SuppressWarnings(PHPMD.CamelCaseVariableName) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function injectAutocompleter(ActionEvent $event, $eventName = null, EventDispatcherInterface $eventDispatcher = null) { global $container, $TL_CSS, $TL_JAVASCRIPT, $TL_MOOTOOLS; static $injected; if (!$injected && $event->getEnvironment()->getDataDefinition()->getName() == 'orm_avisota_salutation') { // backwards compatibility if (!$eventDispatcher) { /** @var EventDispatcher $eventDispatcher */ $eventDispatcher = $container['event-dispatcher']; } // load language file $loadEvent = new LoadLanguageFileEvent('orm_avisota_recipient'); $eventDispatcher->dispatch(ContaoEvents::SYSTEM_LOAD_LANGUAGE_FILE, $loadEvent); // load data container $loadEvent = new LoadDataContainerEvent('orm_avisota_recipient'); $eventDispatcher->dispatch(ContaoEvents::CONTROLLER_LOAD_DATA_CONTAINER, $loadEvent); // inject styles $TL_CSS[] = 'assets/avisota/subscription-recipient/css/meio.autocomplete.css'; // inject scripts $TL_JAVASCRIPT[] = 'assets/avisota/subscription-recipient/js/Meio.Autocomplete.js'; $TL_JAVASCRIPT[] = 'assets/avisota/subscription-recipient/js/mootools-more-1.5.0.js'; // build container for orm_avisota_recipient $factory = DcGeneralFactory::deriveFromEnvironment($event->getEnvironment()); $factory->setContainerName('orm_avisota_recipient'); $containerFactory = $factory->createContainer(); // build token list $tokens = array(); foreach ($containerFactory->getPropertiesDefinition()->getPropertyNames() as $propertyName) { $tokens[] = array('value' => $propertyName, 'text' => sprintf('##%s##', $propertyName)); } $tokens = json_encode($tokens); // inject runtime code // TODO outsource in template $TL_MOOTOOLS[] = <<<EOF <script> var element = \$('ctrl_salutation'); if (element) { \tvar tokens = {$tokens}; \tvar options = { \t\tfilter: { \t\t\ttype: 'contains', \t\t\tpath: 'text' \t\t}, \t\ttokenize: { \t\t\tget: function(element) { \t\t\t\tvar text = element.get('value'); \t\t\t\tvar position = element.getCaretPosition(); \t\t\t\tvar start = text.lastIndexOf(' ', position - 1); \t\t\t\tvar end = text.indexOf(' ', position); \t\t\t\tif (start == -1) { \t\t\t\t\tstart = 0; \t\t\t\t} \t\t\t\telse { \t\t\t\t\tstart ++; \t\t\t\t} \t\t\t\tif (end == -1) { \t\t\t\t\tend = text.length; \t\t\t\t} \t\t\t\tvar token = text.substring(start, end); \t\t\t\tconsole.log('position: ' + position + ', start: ' + start + ', end: ' + end + ', token: ' + token); \t\t\t\treturn token; \t\t\t}, \t\t\tset: function(element, token) { \t\t\t\tvar text = element.get('value'); \t\t\t\tvar position = element.getCaretPosition(); \t\t\t\tvar start = text.lastIndexOf(' ', position - 1); \t\t\t\tvar end = text.indexOf(' ', position); \t\t\t\tif (start == -1) { \t\t\t\t\tstart = 0; \t\t\t\t} \t\t\t\telse { \t\t\t\t\tstart ++; \t\t\t\t} \t\t\t\tif (end == -1) { \t\t\t\t\tend = text.length; \t\t\t\t} \t\t\t\ttext = text.substring(0, start) + token + text.substring(end); \t\t\t\telement.set('value', text); \t\t\t\telement.setCaretPosition(start + token.length); \t\t\t} \t\t} \t}; \tnew Meio.Autocomplete(element, tokens, options); } </script> EOF; $injected = true; } }
/** * Setup all local values and create the dc instance for the referenced data source. * * @param DC_General $dataContainer The data container to use. * * @return void */ protected function setUp(DC_General $dataContainer = null) { $this->dataContainer = $dataContainer ?: $this->objDca; if (!$this->dataContainer) { return; } $environment = $this->dataContainer->getEnvironment(); if (!$this->sourceName) { $property = $environment->getDataDefinition()->getPropertiesDefinition()->getProperty($environment->getInputProvider()->getValue('name')); foreach ($property->getExtra() as $k => $v) { $this->{$k} = $v; } $name = $environment->getInputProvider()->getValue('name'); $this->strField = $name; $this->strName = $name; $this->strId = $name; $this->label = $property->getLabel() ?: $name; $this->strTable = $environment->getDataDefinition()->getName(); } $factory = new DcGeneralFactory(); $this->itemContainer = $factory->setContainerName($this->sourceName)->setTranslator($environment->getTranslator())->setEventDispatcher($environment->getEventDispatcher())->createDcGeneral(); }
/** * Run the controller and parse the template. * * @return void */ public function run() { $template = new \BackendTemplate('be_picker'); $template->main = ''; // Ajax request. // @codingStandardsIgnoreStart - We need POST access here. if ($_POST && \Environment::get('isAjaxRequest')) { $ajax = new \Ajax(\Input::post('action')); $ajax->executePreActions(); } $strTable = \Input::get('table'); $strField = \Input::get('field'); // Define the current ID. define('CURRENT_ID', $strTable ? \Session::getInstance()->get('CURRENT_ID') : \Input::get('id')); $dispatcher = $GLOBALS['container']['event-dispatcher']; /** @var \Symfony\Component\EventDispatcher\EventDispatcher $dispatcher */ $propagator = new EventPropagator($dispatcher); $translator = new TranslatorChain(); $translator->add(new LangArrayTranslator($dispatcher)); $factory = new DcGeneralFactory(); $this->itemContainer = $factory->setContainerName($strTable)->setTranslator($translator)->setEventPropagator($propagator)->createDcGeneral(); $information = (array) $GLOBALS['TL_DCA'][$strTable]['fields'][$strField]; // Merge with the information from the data container. $property = $this->itemContainer->getEnvironment()->getDataDefinition()->getPropertiesDefinition()->getProperty($strField); $extra = $property->getExtra(); $information['eval']['sourceName'] = $extra['sourceName']; $information['eval']['fieldType'] = $extra['fieldType']; /** @var \ContaoCommunityAlliance\DcGeneral\Contao\View\Contao2BackendView\TreePicker $objTreeSelector */ $objTreeSelector = new $GLOBALS['BE_FFL']['DcGeneralTreePicker'](\Widget::getAttributesFromDca($information, $strField, array_filter(explode(',', \Input::get('value'))), $strField, $strTable, new DcCompat($this->itemContainer->getEnvironment()))); // AJAX request. if (isset($ajax)) { $objTreeSelector->generateAjax(); $ajax->executePostActions(new DcCompat($this->itemContainer->getEnvironment())); } $template->main = $objTreeSelector->generatePopup(); $template->theme = \Backend::getTheme(); $template->base = \Environment::get('base'); $template->language = $GLOBALS['TL_LANGUAGE']; $template->title = specialchars($GLOBALS['TL_LANG']['MSC']['treepicker']); $template->charset = $GLOBALS['TL_CONFIG']['characterSet']; $template->addSearch = $objTreeSelector->searchField; $template->search = $GLOBALS['TL_LANG']['MSC']['search']; $template->action = ampersand(\Environment::get('request')); $template->value = \Session::getInstance()->get($objTreeSelector->getSearchSessionKey()); $template->manager = $GLOBALS['TL_LANG']['MSC']['treepickerManager']; $template->breadcrumb = $GLOBALS['TL_DCA'][$objTreeSelector->foreignTable]['list']['sorting']['breadcrumb']; $template->managerHref = ''; // Add the manager link. if ($objTreeSelector->managerHref) { $template->managerHref = 'contao/main.php?' . ampersand($objTreeSelector->managerHref) . '&popup=1'; } // Prevent debug output at all cost. $GLOBALS['TL_CONFIG']['debugMode'] = false; $template->output(); }
/** * Load all additional definitions, like naming of parent data provider etc. * * @param ContainerInterface $container The container where the data shall be stored. * * @param BuildDataDefinitionEvent $event The event being emitted. * * @return void */ protected function loadAdditionalDefinitions(ContainerInterface $container, BuildDataDefinitionEvent $event) { if (($providers = $this->getFromDca('dca_config/data_provider')) !== null) { $event->getDispatcher()->addListener(sprintf('%s[%s]', PopulateEnvironmentEvent::NAME, $container->getName()), function (PopulateEnvironmentEvent $event) { $environment = $event->getEnvironment(); $definition = $environment->getDataDefinition(); $parentName = $definition->getBasicDefinition()->getParentDataProvider(); if ($parentName) { $factory = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($parentName); $parentDefinition = $factory->createContainer(); $environment->setParentDataDefinition($parentDefinition); } $rootName = $definition->getBasicDefinition()->getRootDataProvider(); if ($rootName) { $factory = DcGeneralFactory::deriveEmptyFromEnvironment($environment)->setContainerName($rootName); $rootDefinition = $factory->createContainer(); $environment->setRootDataDefinition($rootDefinition); } }); } }
/** * Obtain the values of a property within a dc-general instance. * * @param IMetaModel $metaModel The metamodel instance to obtain the values from. * * @param EnvironmentInterface $environment The environment used in the input screen table dc-general. * * @param IAttribute $attribute The attribute to obtain the values for. * * @return array */ private function getOptionsViaDcGeneral($metaModel, $environment, $attribute) { $factory = new DcGeneralFactory(); $dcGeneral = $factory->setContainerName($metaModel->getTableName())->setEventDispatcher($environment->getEventDispatcher())->setTranslator($environment->getTranslator())->createDcGeneral(); $subEnv = $dcGeneral->getEnvironment(); $optEv = new GetPropertyOptionsEvent($subEnv, $subEnv->getDataProvider()->getEmptyModel()); $optEv->setPropertyName($attribute->getColName()); $subEnv->getEventDispatcher()->dispatch(GetPropertyOptionsEvent::NAME, $optEv); $options = $optEv->getOptions(); return $options; }