/** * Determine the headline to use. * * @return string. */ private function getHeadline() { if ($this->model->getId()) { return $this->translateLabel('editRecord', ['ID ' . $this->model->getId()]); } return $this->translateLabel('newRecord', ['ID ' . $this->model->getId()]); }
/** * Update the sorting property values of all models. * * @return void */ private function updateSorting() { $ids = $this->getModelIds(); // If no "next" sibling, simply increment the sorting as we are at the end of the list. if (!$this->marker) { foreach ($this->results as $model) { $this->position += 128; /** @var ModelInterface $model */ $model->setProperty($this->getSortingProperty(), $this->position); } return; } $delta = $this->determineDelta(); // Loop over all models and increment sorting value. foreach ($this->results as $model) { $this->position += $delta; /** @var ModelInterface $model */ $model->setProperty($this->getSortingProperty(), $this->position); } // When the sorting exceeds the sorting of the "next" sibling, we need to push the remaining siblings to the // end of the list. if ($this->marker->getProperty($this->getSortingProperty()) <= $this->position) { do { // Skip models about to be pasted. if (in_array($this->marker->getId(), $ids)) { $this->marker = $this->siblingsCopy->shift(); continue; } $this->position += $delta; $this->marker->setProperty($this->getSortingProperty(), $this->position); $this->results->push($this->marker); $this->marker = $this->siblingsCopy->shift(); } while ($this->marker); } }
/** * Retrieve the instance of a widget for the given property. * * @param string $property Name of the property for which the widget shall be retrieved. * * @param PropertyValueBag $valueBag The input values to use (optional). * * @return \Widget * * @throws DcGeneralRuntimeException When No widget could be build. * @throws DcGeneralInvalidArgumentException When property is not defined in the property definitions. */ public function getWidget($property, PropertyValueBag $valueBag = null) { $environment = $this->getEnvironment(); $dispatcher = $environment->getEventDispatcher(); $propertyDefinitions = $environment->getDataDefinition()->getPropertiesDefinition(); if (!$propertyDefinitions->hasProperty($property)) { throw new DcGeneralInvalidArgumentException('Property ' . $property . ' is not defined in propertyDefinitions.'); } $model = clone $this->model; $model->setId($this->model->getId()); if ($valueBag) { $values = new PropertyValueBag($valueBag->getArrayCopy()); $this->environment->getController()->updateModelFromPropertyBag($model, $values); } $propertyDefinition = $propertyDefinitions->getProperty($property); $event = new BuildWidgetEvent($environment, $model, $propertyDefinition); $dispatcher->dispatch(DcGeneralFrontendEvents::BUILD_WIDGET, $event); if (!$event->getWidget()) { throw new DcGeneralRuntimeException(sprintf('Widget was not build for property %s::%s.', $this->model->getProviderName(), $property)); } return $event->getWidget(); }
/** * Calculate the resulting list. * * @return void */ protected function calculate() { if (isset($this->results) || $this->models->length() == 0) { return; } $ids = $this->getModelIds(); $this->results = clone $this->models; $this->siblingsCopy = clone $this->siblings; $this->scanToDesiredPosition(); // If no "next" sibling, simply increment the sorting as we are at the end of the list. if (!$this->marker) { foreach ($this->results as $model) { $this->position += 128; /** @var ModelInterface $model */ $model->setProperty($this->getSortingProperty(), $this->position); } return; } // Determine delta value: ((next sorting - current sorting) / amount of insert models). $delta = ($this->marker->getProperty($this->getSortingProperty()) - $this->position) / $this->results->length(); // If delta too narrow, we need to make room. if ($delta < 2) { $delta = 128; } // Loop over all models and increment sorting value. foreach ($this->results as $model) { $this->position += $delta; /** @var ModelInterface $model */ $model->setProperty($this->getSortingProperty(), $this->position); } // When the sorting exceeds the sorting of the "next" sibling, we need to push the remaining siblings to the // end of the list. if ($this->marker->getProperty($this->getSortingProperty()) <= $this->position) { do { // Skip models about to be pasted. if (in_array($this->marker->getId(), $ids)) { $this->marker = $this->siblingsCopy->shift(); continue; } $this->position += $delta; $this->marker->setProperty($this->getSortingProperty(), $this->position); $this->results->push($this->marker); $this->marker = $this->siblingsCopy->shift(); } while ($this->marker); } }
/** * Create the edit mask. * * @return string * * @throws DcGeneralRuntimeException If the data container is not editable, closed. * * @throws DcGeneralInvalidArgumentException If an unknown property is encountered in the palette. * * @SuppressWarnings(PHPMD.LongVariable) */ public function execute() { $environment = $this->getEnvironment(); $definition = $this->getDataDefinition(); $dataProvider = $environment->getDataProvider($this->model->getProviderName()); $dataProviderDefinition = $definition->getDataProviderDefinition(); $dataProviderInformation = $dataProviderDefinition->getInformation($this->model->getProviderName()); $inputProvider = $environment->getInputProvider(); $palettesDefinition = $definition->getPalettesDefinition(); $blnSubmitted = $inputProvider->getValue('FORM_SUBMIT') === $definition->getName(); $blnIsAutoSubmit = $inputProvider->getValue('SUBMIT_TYPE') === 'auto'; $widgetManager = new ContaoWidgetManager($environment, $this->model); $this->checkEditable($this->model); $this->checkCreatable($this->model); $environment->getEventDispatcher()->dispatch(PreEditModelEvent::NAME, new PreEditModelEvent($environment, $this->model)); $environment->getEventDispatcher()->dispatch(DcGeneralEvents::ENFORCE_MODEL_RELATIONSHIP, new EnforceModelRelationshipEvent($this->getEnvironment(), $this->model)); // Pass 1: Get the palette for the values stored in the model. $palette = $palettesDefinition->findPalette($this->model); $propertyValues = $this->processInput($widgetManager); if ($blnSubmitted && $propertyValues) { // Pass 2: Determine the real palette we want to work on if we have some data submitted. $palette = $palettesDefinition->findPalette($this->model, $propertyValues); // Update the model - the model might add some more errors to the propertyValueBag via exceptions. $this->getEnvironment()->getController()->updateModelFromPropertyBag($this->model, $propertyValues); } $fieldSets = $this->buildFieldSet($widgetManager, $palette, $propertyValues); if (!$blnIsAutoSubmit && $blnSubmitted && empty($this->errors)) { if ($this->doPersist()) { $this->handleSubmit($this->model); } } $objTemplate = new ContaoBackendViewTemplate('dcbe_general_edit'); $objTemplate->setData(array('fieldsets' => $fieldSets, 'versions' => $dataProviderInformation->isVersioningEnabled() ? $dataProvider->getVersions($this->model->getId()) : null, 'subHeadline' => $this->getHeadline(), 'table' => $definition->getName(), 'enctype' => 'multipart/form-data', 'error' => $this->errors, 'editButtons' => $this->getEditButtons(), 'noReload' => (bool) $this->errors, 'breadcrumb' => $this->breadcrumb)); if (in_array('ContaoCommunityAlliance\\DcGeneral\\Data\\MultiLanguageDataProviderInterface', class_implements($environment->getDataProvider($this->model->getProviderName())))) { /** @var MultiLanguageDataProviderInterface $dataProvider */ $langsNative = array(); require TL_ROOT . '/system/config/languages.php'; $objTemplate->set('languages', $environment->getController()->getSupportedLanguages($this->model->getId()))->set('language', $dataProvider->getCurrentLanguage())->set('languageHeadline', $langsNative[$dataProvider->getCurrentLanguage()]); } else { $objTemplate->set('languages', null)->set('languageHeadline', ''); } return $objTemplate->parse(); }
/** * Retrieve the image for the label. * * @param ModelInterface $model The filter setting to render. * * @return string */ protected function getLabelImage(ModelInterface $model) { $typeFactory = $this->getServiceContainer()->getFilterFactory()->getTypeFactory($model->getProperty('type')); $image = $typeFactory ? $typeFactory->getTypeIcon() : null; if (!$image || !file_exists(TL_ROOT . '/' . $image)) { $image = 'system/modules/metamodels/assets/images/icons/filter_default.png'; } if (!$model->getProperty('enabled')) { $intPos = strrpos($image, '.'); if ($intPos !== false) { $image = substr_replace($image, '_1', $intPos, 0); } } $dispatcher = $this->getServiceContainer()->getEventDispatcher(); /** @var AddToUrlEvent $urlEvent */ $urlEvent = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent('act=edit&id=' . $model->getId())); /** @var GenerateHtmlEvent $imageEvent */ $imageEvent = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent($image)); return sprintf('<a href="%s">%s</a>', $urlEvent->getUrl(), $imageEvent->getHtml()); }
/** * Check the PA and PI with a model and a normal flat build. * * @param ModelInterface $containedModel The model to check. * * @return void */ protected function checkModelWithoutVariants($containedModel) { $this->disablePA = $this->currentModel->getId() == $containedModel->getId() || $this->currentModel->getProperty('pid') == $containedModel->getProperty('pid'); $this->disablePI = $this->circularReference || $this->currentModel->getId() == $containedModel->getId() || $this->currentModel->getProperty('pid') == $containedModel->getId(); }
/** * Determine if the passed model is expanded. * * @param ModelInterface $model The model to check. * * @return bool */ protected function isModelOpen($model) { $providerName = $model->getProviderName(); $id = $model->getId(); $openElements = $this->getOpenElements(); if (!isset($openElements[$providerName])) { $openElements[$providerName] = array(); } return isset($openElements[$providerName][$id]) && $openElements[$providerName][$id]; }
/** * Save a model to the database. * * In general, this method fetches the solely property "rows" from the model and updates the local table against * these contents. * * The parent id (id of the model) will get checked and reflected also for new items. * * When rows with duplicate ids are encountered (like from MCW for example), the dupes are inserted as new rows. * * @param ModelInterface $objItem The model to save. * * @param bool $recursive Ignored as not relevant in this data provider. * * @return ModelInterface The passed Model. * * @throws DcGeneralException When the passed model does not contain a property named "rows", an Exception is * thrown. * * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function save(ModelInterface $objItem, $recursive = false) { $arrData = $objItem->getProperty('rows'); if (!($objItem->getID() && $arrData)) { throw new DcGeneralException('invalid input data in model.', 1); } $arrKeep = array(); foreach ($arrData as $arrRow) { $arrSQL = $arrRow; // Update all. $intId = intval($arrRow['id']); // Work around the fact that multicolumnwizard does not clear any hidden fields when copying a dataset. // therefore we do consider any dupe as new dataset and save it accordingly. if (in_array($intId, $arrKeep)) { $intId = 0; unset($arrSQL['id']); } if ($intId > 0) { $this->objDatabase->prepare(sprintf('UPDATE %s %%s WHERE id=? AND %s=?', $this->strSource, $this->strGroupCol))->set($arrSQL)->execute($intId, $objItem->getId()); $arrKeep[] = $intId; } else { // Force group col value. $arrSQL[$this->strGroupCol] = $objItem->getId(); $arrKeep[] = $this->objDatabase->prepare(sprintf('INSERT INTO %s %%s', $this->strSource))->set($arrSQL)->execute()->insertId; } } // House keeping, kill the rest. $this->objDatabase->prepare(sprintf('DELETE FROM %s WHERE %s=? AND id NOT IN (%s)', $this->strSource, $this->strGroupCol, implode(',', $arrKeep)))->execute($objItem->getId()); return $objItem; }
/** * Check the state of a model and set the metadata accordingly. * * @param ModelInterface $model The model of which the state shall be checked of. * * @param int $level The tree level the model is contained within. * * @return void */ private function determineModelState(ModelInterface $model, $level) { $model->setMeta(DCGE::TREE_VIEW_LEVEL, $level); $model->setMeta($model::SHOW_CHILDREN, $this->states->isModelOpen($model->getProviderName(), $model->getId())); }
/** * Render a command button. * * @param CommandInterface $objCommand The command to render the button for. * * @param ModelInterface $objModel The model to which the command shall get applied. * * @param bool $blnCircularReference Determinator if there exists a circular reference between the model * and the model(s) contained in the clipboard. * * @param array $arrChildRecordIds List of the ids of all child models of the current model. * * @param ModelInterface $previous The previous model in the collection. * * @param ModelInterface $next The next model in the collection. * * @return string */ protected function buildCommand($objCommand, $objModel, $blnCircularReference, $arrChildRecordIds, $previous, $next) { $environment = $this->getEnvironment(); $inputProvider = $environment->getInputProvider(); $dispatcher = $environment->getEventDispatcher(); $dataDefinitionName = $environment->getDataDefinition()->getName(); $commandName = $objCommand->getName(); $parameters = (array) $objCommand->getParameters(); $extra = (array) $objCommand->getExtra(); $extraAttributes = !empty($extra['attributes']) ? $extra['attributes'] : null; $attributes = ''; // Set basic information. $opLabel = $objCommand->getLabel(); if (strlen($opLabel)) { $label = $opLabel; } else { $label = $commandName; } $label = $this->translate($label, $dataDefinitionName); if (is_array($label)) { $label = $label[0]; } $opDesc = $this->translate($objCommand->getDescription(), $dataDefinitionName); if (strlen($opDesc)) { $title = sprintf($opDesc, $objModel->getID()); } else { $title = sprintf('%s id %s', $label, $objModel->getID()); } // Toggle has to trigger the javascript. if ($objCommand instanceof ToggleCommandInterface) { $parameters['act'] = $commandName; $icon = $extra['icon']; $iconDisabled = isset($extra['icon_disabled']) ? $extra['icon_disabled'] : 'invisible.gif'; $attributes = sprintf('onclick="Backend.getScrollOffset(); return BackendGeneral.toggleVisibility(this, \'%s\', \'%s\');"', $icon, $iconDisabled); $dataProvider = $this->getEnvironment()->getDataProvider($objModel->getProviderName()); if ($objCommand instanceof TranslatedToggleCommandInterface && $dataProvider instanceof MultiLanguageDataProviderInterface) { $language = $dataProvider->getCurrentLanguage(); $dataProvider->setCurrentLanguage($objCommand->getLanguage()); $propModel = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($objModel->getId())->setFields($objCommand->getToggleProperty())); $dataProvider->setCurrentLanguage($language); } else { $propModel = $objModel; } $state = $objCommand->isInverse() ? !$propModel->getProperty($objCommand->getToggleProperty()) : $propModel->getProperty($objCommand->getToggleProperty()); if (!$state) { $extra['icon'] = $iconDisabled ?: 'invisible.gif'; } } if ($extraAttributes) { $attributes .= ltrim(sprintf($extraAttributes, $objModel->getID())); } $serializedModelId = ModelId::fromModel($objModel)->getSerialized(); // Cut needs some special information. if ($objCommand instanceof CutCommandInterface) { $parameters = array(); $parameters['act'] = $commandName; // If we have a pid add it, used for mode 4 and all parent -> current views. if ($inputProvider->hasParameter('pid')) { $parameters['pid'] = $inputProvider->getParameter('pid'); } // Source is the id of the element which should move. $parameters['source'] = $serializedModelId; } elseif ($objCommand instanceof CopyCommandInterface) { // The copy operation. $parameters = array(); $parameters['act'] = $commandName; // If we have a pid add it, used for mode 4 and all parent -> current views. if ($inputProvider->hasParameter('pid')) { $parameters['pid'] = $inputProvider->getParameter('pid'); } // Source is the id of the element which should move. $parameters['source'] = $serializedModelId; } else { // TODO: Shall we interface this option? $idParam = isset($extra['idparam']) ? $extra['idparam'] : null; if ($idParam) { $parameters[$idParam] = $serializedModelId; } else { $parameters['id'] = $serializedModelId; } } $strHref = ''; foreach ($parameters as $key => $value) { $strHref .= sprintf('&%s=%s', $key, $value); } /** @var AddToUrlEvent $event */ $event = $dispatcher->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, new AddToUrlEvent($strHref)); $strHref = $event->getUrl(); $buttonEvent = new GetOperationButtonEvent($this->getEnvironment()); $buttonEvent->setCommand($objCommand)->setObjModel($objModel)->setAttributes($attributes)->setLabel($label)->setTitle($title)->setHref($strHref)->setChildRecordIds($arrChildRecordIds)->setCircularReference($blnCircularReference)->setPrevious($previous)->setNext($next)->setDisabled($objCommand->isDisabled()); $dispatcher->dispatch(GetOperationButtonEvent::NAME, $buttonEvent); // If the event created a button, use it. if ($buttonEvent->getHtml() !== null) { return trim($buttonEvent->getHtml()); } $icon = $extra['icon']; if ($buttonEvent->isDisabled()) { /** @var GenerateHtmlEvent $event */ $event = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent(substr_replace($icon, '_1', strrpos($icon, '.'), 0), $buttonEvent->getLabel())); return $event->getHtml(); } /** @var GenerateHtmlEvent $event */ $event = $dispatcher->dispatch(ContaoEvents::IMAGE_GET_HTML, new GenerateHtmlEvent($icon, $buttonEvent->getLabel())); return sprintf(' <a href="%s" title="%s" %s>%s</a>', $buttonEvent->getHref(), specialchars($buttonEvent->getTitle()), $buttonEvent->getAttributes(), $event->getHtml()); }
/** * Create the edit mask. * * @param ModelInterface $model The model with the current data. * * @param ModelInterface $originalModel The data from the original data. * * @param callable $preFunction The function to call before saving an item. * * @param callable $postFunction The function to call after saving an item. * * @return string * * @throws DcGeneralRuntimeException If the data container is not editable, closed. * * @throws DcGeneralInvalidArgumentException If an unknown property is encountered in the palette. */ protected function createEditMask($model, $originalModel, $preFunction, $postFunction) { $this->checkLanguage(); $environment = $this->getEnvironment(); $definition = $environment->getDataDefinition(); $basicDefinition = $definition->getBasicDefinition(); $dataProvider = $environment->getDataProvider($model->getProviderName()); $dataProviderDefinition = $definition->getDataProviderDefinition(); $dataProviderInformation = $dataProviderDefinition->getInformation($model->getProviderName()); $inputProvider = $environment->getInputProvider(); $palettesDefinition = $definition->getPalettesDefinition(); $modelId = $model->getId(); $propertyDefinitions = $definition->getPropertiesDefinition(); $blnSubmitted = $inputProvider->getValue('FORM_SUBMIT') === $definition->getName(); $blnIsAutoSubmit = $inputProvider->getValue('SUBMIT_TYPE') === 'auto'; $widgetManager = new ContaoWidgetManager($environment, $model); $event = new PreEditModelEvent($this->environment, $model); $environment->getEventPropagator()->propagate($event::NAME, $event, $definition->getName()); // Check if table is editable. if (!$basicDefinition->isEditable()) { $message = 'DataContainer ' . $definition->getName() . ' is not editable'; $environment->getEventPropagator()->propagate(ContaoEvents::SYSTEM_LOG, new LogEvent($message, TL_ERROR, 'DC_General - edit()')); throw new DcGeneralRuntimeException($message); } // Check if table is closed but we are adding a new item. if (!$modelId && $basicDefinition->isClosed()) { $message = 'DataContainer ' . $definition->getName() . ' is closed'; $environment->getEventPropagator()->propagate(ContaoEvents::SYSTEM_LOG, new LogEvent($message, TL_ERROR, 'DC_General - edit()')); throw new DcGeneralRuntimeException($message); } $this->enforceModelRelationship($model); // Pass 1: Get the palette for the values stored in the model. $palette = $palettesDefinition->findPalette($model); $propertyValues = $this->processInput($widgetManager); $errors = array(); if ($blnSubmitted && $propertyValues) { // Pass 2: Determine the real palette we want to work on if we have some data submitted. $palette = $palettesDefinition->findPalette($model, $propertyValues); // Update the model - the model might add some more errors to the propertyValueBag via exceptions. $this->getEnvironment()->getController()->updateModelFromPropertyBag($model, $propertyValues); } $arrFieldSets = array(); $blnFirst = true; foreach ($palette->getLegends() as $legend) { $legendName = $environment->getTranslator()->translate($legend->getName() . '_legend', $definition->getName()); $fields = array(); $properties = $legend->getProperties($model, $propertyValues); if (!$properties) { continue; } foreach ($properties as $property) { if (!$propertyDefinitions->hasProperty($property->getName())) { throw new DcGeneralInvalidArgumentException(sprintf('Property %s is mentioned in palette but not defined in propertyDefinition.', $property->getName())); } // If this property is invalid, fetch the error. if (!$blnIsAutoSubmit && $propertyValues && $propertyValues->hasPropertyValue($property->getName()) && $propertyValues->isPropertyValueInvalid($property->getName())) { $errors = array_merge($errors, $propertyValues->getPropertyValueErrors($property->getName())); } $fields[] = $widgetManager->renderWidget($property->getName(), $blnIsAutoSubmit, $propertyValues); } $arrFieldSet['label'] = $legendName; $arrFieldSet['class'] = $blnFirst ? 'tl_tbox' : 'tl_box'; $arrFieldSet['palette'] = implode('', $fields); $arrFieldSet['legend'] = $legend->getName(); $arrFieldSets[] = $arrFieldSet; $blnFirst = false; } if (!$blnIsAutoSubmit && $blnSubmitted && empty($errors)) { if ($model->getMeta($model::IS_CHANGED)) { // Trigger the event for post persists or create. if ($preFunction != null) { $preFunction($environment, $model, $originalModel); } $event = new PrePersistModelEvent($environment, $model, $originalModel); $environment->getEventPropagator()->propagate($event::NAME, $event, array($this->getEnvironment()->getDataDefinition()->getName())); if (!$model->getId() && $this->getManualSortingProperty()) { $models = $dataProvider->getEmptyCollection(); $models->push($model); $controller = $environment->getController(); if ($inputProvider->hasParameter('after')) { $after = IdSerializer::fromSerialized($inputProvider->getParameter('after')); $previousDataProvider = $environment->getDataProvider($after->getDataProviderName()); $previousFetchConfig = $previousDataProvider->getEmptyConfig(); $previousFetchConfig->setId($after->getId()); $previousModel = $previousDataProvider->fetch($previousFetchConfig); if ($previousModel) { $controller->pasteAfter($previousModel, $models, $this->getManualSortingProperty()); } else { $controller->pasteTop($models, $this->getManualSortingProperty()); } } elseif ($inputProvider->hasParameter('into')) { $into = IdSerializer::fromSerialized($inputProvider->getParameter('into')); $parentDataProvider = $environment->getDataProvider($into->getDataProviderName()); $parentFetchConfig = $parentDataProvider->getEmptyConfig(); $parentFetchConfig->setId($into->getId()); $parentModel = $parentDataProvider->fetch($parentFetchConfig); if ($parentModel) { $controller->pasteInto($parentModel, $models, $this->getManualSortingProperty()); } else { $controller->pasteTop($models, $this->getManualSortingProperty()); } } else { $controller->pasteTop($models, $this->getManualSortingProperty()); } $environment->getClipboard()->clear()->saveTo($environment); } else { // Save the model. $dataProvider->save($model); } // Trigger the event for post persists or create. if ($postFunction != null) { $postFunction($environment, $model, $originalModel); } $event = new PostPersistModelEvent($environment, $model, $originalModel); $environment->getEventPropagator()->propagate($event::NAME, $event, array($this->getEnvironment()->getDataDefinition()->getName())); $this->storeVersion($model); } $this->handleSubmit($model); } if ($model->getId()) { $strHeadline = sprintf($this->translate('editRecord', $definition->getName()), 'ID ' . $model->getId()); if ($strHeadline === 'editRecord') { $strHeadline = sprintf($this->translate('MSC.editRecord'), 'ID ' . $model->getId()); } } else { $strHeadline = sprintf($this->translate('newRecord', $definition->getName()), 'ID ' . $model->getId()); if ($strHeadline === 'newRecord') { $strHeadline = sprintf($this->translate('MSC.editRecord'), ''); } } $objTemplate = $this->getTemplate('dcbe_general_edit'); $objTemplate->setData(array('fieldsets' => $arrFieldSets, 'versions' => $dataProviderInformation->isVersioningEnabled() ? $dataProvider->getVersions($model->getId()) : null, 'subHeadline' => $strHeadline, 'table' => $definition->getName(), 'enctype' => 'multipart/form-data', 'error' => $errors, 'editButtons' => $this->getEditButtons(), 'noReload' => (bool) $errors)); if ($this->isMultiLanguage($model->getId())) { /** @var MultiLanguageDataProviderInterface $dataProvider */ $langsNative = array(); // @codingStandardsIgnoreStart - We have to include it multiple times. require TL_ROOT . '/system/config/languages.php'; // @codingStandardsIgnoreEnd $this->addToTemplate('languages', $environment->getController()->getSupportedLanguages($model->getId()), $objTemplate)->addToTemplate('language', $dataProvider->getCurrentLanguage(), $objTemplate)->addToTemplate('languageHeadline', $langsNative[$dataProvider->getCurrentLanguage()], $objTemplate); } else { $this->addToTemplate('languages', null, $objTemplate)->addToTemplate('languageHeadline', '', $objTemplate); } return $objTemplate->parse(); }
/** * Get value from the entity. * * @param Entity $entity The entity. * * @return mixed */ protected function getEntityValue(Entity $entity) { // no access to id by the entity if ($this->property == 'id') { return $entity->getId(); } return $entity->getProperty($this->property); }
/** * Render a given model. * * @param ModelInterface $objModel The model to render. * * @param string $strToggleID The id of the toggler. * * @return string */ protected function parseModel($objModel, $strToggleID) { $event = new FormatModelLabelEvent($this->environment, $objModel); $this->environment->getEventDispatcher()->dispatch(DcGeneralEvents::FORMAT_MODEL_LABEL, $event); $objModel->setMeta($objModel::LABEL_VALUE, $event->getLabel()); $objTemplate = $this->getTemplate('dcbe_general_treeview_entry'); if ($objModel->getMeta($objModel::SHOW_CHILDREN)) { $toggleTitle = $this->getEnvironment()->getTranslator()->translate('collapseNode', 'MSC'); } else { $toggleTitle = $this->getEnvironment()->getTranslator()->translate('expandNode', 'MSC'); } $toggleScript = sprintf('Backend.getScrollOffset(); return BackendGeneral.loadSubTree(this, ' . '{\'toggler\':\'%s\', \'id\':\'%s\', \'providerName\':\'%s\', \'level\':\'%s\', \'mode\':\'%s\'});', $strToggleID, $objModel->getId(), $objModel->getProviderName(), $objModel->getMeta('dc_gen_tv_level'), 6); $toggleUrlEvent = new AddToUrlEvent('ptg=' . $objModel->getId() . '&provider=' . $objModel->getProviderName()); $this->getEnvironment()->getEventDispatcher()->dispatch(ContaoEvents::BACKEND_ADD_TO_URL, $toggleUrlEvent); $this->addToTemplate('environment', $this->getEnvironment(), $objTemplate)->addToTemplate('objModel', $objModel, $objTemplate)->addToTemplate('select', $this->isSelectModeActive(), $objTemplate)->addToTemplate('intMode', 6, $objTemplate)->addToTemplate('strToggleID', $strToggleID, $objTemplate)->addToTemplate('toggleUrl', $toggleUrlEvent->getUrl(), $objTemplate)->addToTemplate('toggleTitle', $toggleTitle, $objTemplate)->addToTemplate('toggleScript', $toggleScript, $objTemplate); return $objTemplate->parse(); }
/** * Check the PA and PI with a model and a normal flat build. * * @param ModelInterface $containedModel The model to check. * * @return void */ protected function checkModelWithoutVariants($containedModel) { $parentDefinition = $this->environment->getDataDefinition()->getBasicDefinition()->getParentDataProvider(); $this->disablePA = $this->currentModel->getId() == $containedModel->getId() || $parentDefinition && $this->currentModel->getProperty('pid') == $containedModel->getProperty('pid'); $this->disablePI = $this->circularReference || $this->currentModel->getId() == $containedModel->getId() || $parentDefinition && $this->currentModel->getProperty('pid') == $containedModel->getId(); }
/** * Determine the toggle state of a toggle command. * * @param ToggleCommandInterface $command The toggle command. * * @param ModelInterface $model The model in scope. * * @return bool */ private function isTogglerInActiveState($command, $model) { $dataProvider = $this->environment->getDataProvider($model->getProviderName()); if ($command instanceof TranslatedToggleCommandInterface && $dataProvider instanceof MultiLanguageDataProviderInterface) { $language = $dataProvider->getCurrentLanguage(); $dataProvider->setCurrentLanguage($command->getLanguage()); $propModel = $dataProvider->fetch($dataProvider->getEmptyConfig()->setId($model->getId())->setFields($command->getToggleProperty())); $dataProvider->setCurrentLanguage($language); } else { $propModel = $model; } if ($command->isInverse()) { return !$propModel->getProperty($command->getToggleProperty()); } return (bool) $propModel->getProperty($command->getToggleProperty()); }
/** * Check the state of a model and set the metadata accordingly. * * @param ModelInterface $model The model of which the state shall be checked of. * * @param int $level The tree level the model is contained within. * * @return void */ protected function determineModelState(ModelInterface $model, $level) { $model->setMeta(DCGE::TREE_VIEW_LEVEL, $level); $model->setMeta(DCGE::TREE_VIEW_IS_OPEN, $this->getTreeNodeStates()->isModelOpen($model->getProviderName(), $model->getId())); }
/** * Retrieve the instance of a widget for the given property. * * @param string $property Name of the property for which the widget shall be retrieved. * * @param PropertyValueBag $inputValues The input values to use (optional). * * @throws DcGeneralInvalidArgumentException When an unknown property has been passed. * * @return \Widget */ public function getWidget($property, PropertyValueBag $inputValues = null) { $environment = $this->getEnvironment(); $defName = $environment->getDataDefinition()->getName(); $propertyDefinitions = $environment->getDataDefinition()->getPropertiesDefinition(); if (!$propertyDefinitions->hasProperty($property)) { throw new DcGeneralInvalidArgumentException('Property ' . $property . ' is not defined in propertyDefinitions.'); } $event = new BuildWidgetEvent($environment, $this->model, $propertyDefinitions->getProperty($property)); $environment->getEventPropagator()->propagate($event::NAME, $event, array($defName, $property)); if ($event->getWidget()) { return $event->getWidget(); } $propInfo = $propertyDefinitions->getProperty($property); $propExtra = $propInfo->getExtra(); $varValue = $this->decodeValue($property, $this->model->getProperty($property)); $xLabel = $this->getXLabel($propInfo); $strClass = $GLOBALS['BE_FFL'][$propInfo->getWidgetType()]; if (!class_exists($strClass)) { return null; } // FIXME TEMPORARY WORKAROUND! To be fixed in the core: Controller::prepareForWidget(..). if (in_array($propExtra['rgxp'], array('date', 'time', 'datim')) && !$propExtra['mandatory'] && is_numeric($varValue) && $varValue == 0) { $varValue = ''; } // OH: why not $required = $mandatory always? source: DataContainer 226. // OH: the whole prepareForWidget(..) thing is an only mess // Widgets should parse the configuration by themselves, depending on what they need. $propExtra['required'] = $varValue == '' && $propExtra['mandatory']; if ($inputValues) { $model = clone $this->model; $model->setId($this->model->getId()); $this->environment->getController()->updateModelFromPropertyBag($model, $inputValues); } else { $model = $this->model; } $options = $propInfo->getOptions(); $event = new GetPropertyOptionsEvent($environment, $model); $event->setPropertyName($property); $event->setOptions($options); $environment->getEventPropagator()->propagate($event::NAME, $event, $environment->getDataDefinition()->getName(), $property); if ($event->getOptions() !== $options) { $options = $event->getOptions(); } $arrConfig = array('inputType' => $propInfo->getWidgetType(), 'label' => array($propInfo->getLabel(), $propInfo->getDescription()), 'options' => $options, 'eval' => $propExtra); if (isset($propExtra['reference'])) { $arrConfig['reference'] = $propExtra['reference']; } $event = new GetAttributesFromDcaEvent($arrConfig, $propInfo->getName(), $varValue, $property, $defName, new DcCompat($environment, $this->model, $property)); $environment->getEventPropagator()->propagate(ContaoEvents::WIDGET_GET_ATTRIBUTES_FROM_DCA, $event, $environment->getDataDefinition()->getName(), $property); $arrPrepared = $event->getResult(); // Bugfix CS: ajax subpalettes are really broken. // Therefore we reset to the default checkbox behaviour here and submit the entire form. // This way, the javascript needed by the widget (wizards) will be correctly evaluated. if ($arrConfig['inputType'] == 'checkbox' && is_array($GLOBALS['TL_DCA'][$defName]['subpalettes']) && in_array($property, array_keys($GLOBALS['TL_DCA'][$defName]['subpalettes'])) && $arrConfig['eval']['submitOnChange']) { $arrPrepared['onclick'] = $arrConfig['eval']['submitOnChange'] ? "Backend.autoSubmit('" . $defName . "')" : ''; } $objWidget = new $strClass($arrPrepared); // OH: what is this? source: DataContainer 232. $objWidget->currentRecord = $this->model->getId(); $objWidget->wizard .= $xLabel; $event = new ManipulateWidgetEvent($environment, $this->model, $propInfo, $objWidget); $environment->getEventPropagator()->propagate($event::NAME, $event, array($defName, $property)); return $objWidget; }
/** * Create an instance from a model. * * @param ModelInterface $model The model. * * @return IdSerializer */ public static function fromModel(ModelInterface $model) { return self::fromValues($model->getProviderName(), $model->getId()); }
/** * Get the headline for the template. * * @param ModelInterface $model The model. * * @return string */ protected function getHeadline($model) { $translator = $this->getEnvironment()->getTranslator(); $headline = $translator->translate('MSC.showRecord', $model->getProviderName(), array('ID ' . $model->getId())); if ($headline !== 'MSC.showRecord') { return $headline; } return $translator->translate('MSC.showRecord', null, array('ID ' . $model->getId())); }
/** * Save a new version of a row. * * @param ModelInterface $objModel The model for which a new version shall be created. * * @param string $strUsername The username to attach to the version as creator. * * @return void */ public function saveVersion(ModelInterface $objModel, $strUsername) { $objCount = $this->objDatabase->prepare('SELECT count(*) as mycount FROM tl_version WHERE pid=? AND fromTable = ?')->execute($objModel->getId(), $this->strSource); $mixNewVersion = intval($objCount->mycount) + 1; $mixData = $objModel->getPropertiesAsArray(); $mixData[$this->idProperty] = $objModel->getId(); $arrInsert = array(); $arrInsert['pid'] = $objModel->getId(); $arrInsert['tstamp'] = time(); $arrInsert['version'] = $mixNewVersion; $arrInsert['fromTable'] = $this->strSource; $arrInsert['username'] = $strUsername; $arrInsert['data'] = serialize($mixData); $this->objDatabase->prepare('INSERT INTO tl_version %s')->set($arrInsert)->execute(); $this->setVersionActive($objModel->getId(), $mixNewVersion); }