vendor/metamodels/core/src/CoreBundle/Contao/Hooks/LoadDataContainer.php line 105

Open in your IDE?
  1. <?php
  2. /**
  3.  * This file is part of MetaModels/core.
  4.  *
  5.  * (c) 2012-2019 The MetaModels team.
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  *
  10.  * This project is provided in good faith and hope to be usable by anyone.
  11.  *
  12.  * @package    MetaModels/core
  13.  * @author     Christian Schiffler <c.schiffler@cyberspectrum.de>
  14.  * @author     Sven Baumann <baumann.sv@gmail.com>
  15.  * @copyright  2012-2019 The MetaModels team.
  16.  * @license    https://github.com/MetaModels/core/blob/master/LICENSE LGPL-3.0-or-later
  17.  * @filesource
  18.  */
  19. namespace MetaModels\CoreBundle\Contao\Hooks;
  20. use Contao\Controller;
  21. use Contao\CoreBundle\Framework\Adapter;
  22. use ContaoCommunityAlliance\DcGeneral\Data\ModelId;
  23. use MetaModels\CoreBundle\Assets\IconBuilder;
  24. use MetaModels\IFactory;
  25. use MetaModels\IMetaModel;
  26. use MetaModels\ViewCombination\ViewCombination;
  27. /**
  28.  * This class handles loading of the virtual data containers.
  29.  */
  30. class LoadDataContainer
  31. {
  32.     /**
  33.      * Adapter to the Contao\Controller class.
  34.      *
  35.      * @var Controller
  36.      */
  37.     private $controller;
  38.     /**
  39.      * The MetaModels factory.
  40.      *
  41.      * @var IFactory
  42.      */
  43.     private $factory;
  44.     /**
  45.      * The view combination.
  46.      *
  47.      * @var ViewCombination
  48.      */
  49.     private $combination;
  50.     /**
  51.      * The icon builder.
  52.      *
  53.      * @var IconBuilder
  54.      */
  55.     private $iconBuilder;
  56.     /**
  57.      * Create a new instance.
  58.      *
  59.      * @param IFactory        $factory           The MetaModels factory.
  60.      * @param ViewCombination $combination       The view combination provider.
  61.      * @param Adapter         $controllerAdapter The controller adapter to load languages and data containers.
  62.      * @param IconBuilder     $iconBuilder       The icon builder.
  63.      */
  64.     public function __construct(
  65.         IFactory $factory,
  66.         ViewCombination $combination,
  67.         Adapter $controllerAdapter,
  68.         IconBuilder $iconBuilder
  69.     ) {
  70.         $this->factory     $factory;
  71.         $this->combination $combination;
  72.         $this->controller  $controllerAdapter;
  73.         $this->iconBuilder $iconBuilder;
  74.     }
  75.     /**
  76.      * Load a data container.
  77.      *
  78.      * @param string $tableName The table name.
  79.      *
  80.      * @return void
  81.      */
  82.     public function onLoadDataContainer($tableName)
  83.     {
  84.         static $tableExists;
  85.         // Test that the tables have been created.
  86.         if (null === $tableExists) {
  87.             $tableExists = \System::getContainer()
  88.                 ->get('database_connection')
  89.                 ->getSchemaManager()
  90.                 ->tablesExist(['tl_metamodel']);
  91.         }
  92.         if (false === $tableExists) {
  93.             return;
  94.         }
  95.         $this->handleMetaModelTable($tableName);
  96.         $this->handleNonMetaModelTable($tableName);
  97.     }
  98.     /**
  99.      * Handle for MetaModel tables - this loads the base definition "tl_metamodel_item".
  100.      *
  101.      * @param string $tableName The table name.
  102.      *
  103.      * @return void
  104.      *
  105.      * @SuppressWarnings(PHPMD.Superglobals)
  106.      * @SuppressWarnings(PHPMD.CamelCaseVariableName)
  107.      */
  108.     private function handleMetaModelTable($tableName)
  109.     {
  110.         static $tableNames;
  111.         if (!$tableNames) {
  112.             $tableNames $this->factory->collectNames();
  113.         }
  114.         // Not a MetaModel, get out now.
  115.         if (!in_array($tableName$tableNames)) {
  116.             return;
  117.         }
  118.         $this->controller->loadLanguageFile('tl_metamodel_item');
  119.         $this->controller->loadDataContainer('tl_metamodel_item');
  120.         if (!isset($GLOBALS['TL_DCA'][$tableName])) {
  121.             $GLOBALS['TL_DCA'][$tableName] = [];
  122.         }
  123.         $GLOBALS['TL_DCA'][$tableName] = array_replace_recursive(
  124.             (array) $GLOBALS['TL_DCA']['tl_metamodel_item'],
  125.             (array) $GLOBALS['TL_DCA'][$tableName]
  126.         );
  127.     }
  128.     /**
  129.      * Handle for non MetaModel tables - this adds the child operations.
  130.      *
  131.      * @param string $tableName The table name.
  132.      *
  133.      * @return void
  134.      *
  135.      * @SuppressWarnings(PHPMD.Superglobals)
  136.      * @SuppressWarnings(PHPMD.CamelCaseVariableName)
  137.      */
  138.     private function handleNonMetaModelTable($tableName)
  139.     {
  140.         // Nothing to do for MetaModel tables.
  141.         if (substr($tableName03) === 'mm_') {
  142.             return;
  143.         }
  144.         static $map;
  145.         if (!isset($map)) {
  146.             $map $this->buildMap();
  147.         }
  148.         // No children for this table.
  149.         if (!isset($map[$tableName])) {
  150.             return;
  151.         }
  152.         $parentDCA = &$GLOBALS['TL_DCA'][$tableName];
  153.         $this->controller->loadLanguageFile('default');
  154.         foreach ($map[$tableName] as $metaModelTable => $inputScreen) {
  155.             $metaModel $this->factory->getMetaModel($metaModelTable);
  156.             $caption   $this->buildCaption($metaModel$inputScreen);
  157.             $operationName                                   'edit_' $metaModel->getTableName();
  158.             $parentDCA['list']['operations'][$operationName] = array
  159.             (
  160.                 'label'      => &$caption,
  161.                 'href'       => 'table=' $metaModelTable,
  162.                 'icon'       => $this->iconBuilder->getBackendIcon($inputScreen['meta']['backendicon']),
  163.                 'attributes' => 'onclick="Backend.getScrollOffset()"',
  164.             );
  165.             // Is the destination table a metamodel with variants?
  166.             if ($metaModel->hasVariants()) {
  167.                 $parentDCA['list']['operations'][$operationName]['idparam'] = 'id_' $tableName;
  168.             } else {
  169.                 $parentDCA['list']['operations'][$operationName]['idparam'] = 'pid';
  170.             }
  171.             // Compatibility with DC_Table.
  172.             if ($parentDCA['config']['dataContainer'] !== 'General') {
  173.                 $idParameter                                                        =
  174.                     $parentDCA['list']['operations'][$operationName]['idparam'];
  175.                 $parentDCA['list']['operations'][$operationName]['button_callback'] =
  176.                     function ($row$href$label$name$icon$attributes$table) use ($idParameter) {
  177.                         return $this->buildChildOperationButton(
  178.                             $idParameter,
  179.                             $row['id'],
  180.                             $href,
  181.                             $label,
  182.                             $name,
  183.                             $icon,
  184.                             $attributes,
  185.                             $table
  186.                         );
  187.                     };
  188.             }
  189.         }
  190.     }
  191.     /**
  192.      * Build the data container map.
  193.      *
  194.      * @return array
  195.      */
  196.     private function buildMap()
  197.     {
  198.         $map = [];
  199.         foreach ($this->combination->getParented() as $childName => $child) {
  200.             $map[$child['meta']['ptable']][$childName] = $child;
  201.         }
  202.         return $map;
  203.     }
  204.     /**
  205.      * Build the caption for a table.
  206.      *
  207.      * @param IMetaModel $metaModel   The MetaModel to build the caption for.
  208.      * @param array      $inputScreen The input screen information.
  209.      *
  210.      * @return array
  211.      *
  212.      * @SuppressWarnings(PHPMD.Superglobals)
  213.      * @SuppressWarnings(PHPMD.CamelCaseVariableName)
  214.      */
  215.     private function buildCaption($metaModel$inputScreen): array
  216.     {
  217.         $caption = [
  218.             sprintf($GLOBALS['TL_LANG']['MSC']['metamodel_edit_as_child']['label'], $metaModel->getName()),
  219.             ''
  220.         ];
  221.         foreach ($inputScreen['label'] as $langCode => $label) {
  222.             if ($label !== '' && $langCode === $GLOBALS['TL_LANGUAGE']) {
  223.                 $caption = [
  224.                     $label,
  225.                     $inputScreen['description'][$langCode]
  226.                 ];
  227.             }
  228.         }
  229.         return $caption;
  230.     }
  231.     /**
  232.      * This method exists only for being compatible when MetaModels are being used as child table from DC_Table context.
  233.      *
  234.      * @param string $idParameter The id parameter in use.
  235.      *
  236.      * @param string $itemId      The current data row.
  237.      *
  238.      * @param string $href        The href to be appended.
  239.      *
  240.      * @param string $label       The operation label.
  241.      *
  242.      * @param string $name        The operation name.
  243.      *
  244.      * @param string $icon        The icon path.
  245.      *
  246.      * @param string $attributes  The button attributes.
  247.      *
  248.      * @param string $table       The table name.
  249.      *
  250.      * @return string
  251.      */
  252.     private function buildChildOperationButton($idParameter$itemId$href$label$name$icon$attributes$table)
  253.     {
  254.         $modelId ModelId::fromValues($table$itemId);
  255.         $url $href '&amp;' $idParameter '=' $modelId->getSerialized();
  256.         // If id parameter different, we have to override it in the URL.
  257.         if ('id' !== $idParameter) {
  258.             $url .= '&amp;id=';
  259.         }
  260.         $url $this->controller->addToUrl($url);
  261.         // If id parameter different, we have to clean out the id in the URL now.
  262.         if ('id' !== $idParameter) {
  263.             $url preg_replace('#(&amp;)id=(?:&amp;)?#''$1'$url);
  264.         }
  265.         $title sprintf($label ?: $name$itemId);
  266.         return sprintf(
  267.             '<a href="%1$s" title="%2$s"%3$s>%4$s</a> ',
  268.             $url,
  269.             specialchars($title),
  270.             $attributes,
  271.             $this->iconBuilder->getBackendIconImageTag($icon$label)
  272.         );
  273.     }
  274. }