vendor/contao/core-bundle/src/Resources/contao/library/Contao/DcaLoader.php line 120

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of Contao.
  4. *
  5. * (c) Leo Feyer
  6. *
  7. * @license LGPL-3.0-or-later
  8. */
  9. namespace Contao;
  10. /**
  11. * Loads a set of DCA files
  12. *
  13. * The class loads the DCA files of a certain table and stores a combined
  14. * version in the cache directory.
  15. *
  16. * Usage:
  17. *
  18. * $dca = new DcaLoader('tl_user');
  19. * $dca->load();
  20. */
  21. class DcaLoader extends Controller
  22. {
  23. /**
  24. * @var array
  25. */
  26. protected static $arrLoaded = array();
  27. /**
  28. * Table name
  29. * @var string
  30. */
  31. protected $strTable;
  32. /**
  33. * Store the table name
  34. *
  35. * @param string $strTable The table name
  36. *
  37. * @throws \Exception If $strTable is empty
  38. */
  39. public function __construct($strTable)
  40. {
  41. if (!$strTable)
  42. {
  43. throw new \Exception('The table name must not be empty');
  44. }
  45. if (Validator::isInsecurePath($strTable))
  46. {
  47. throw new \InvalidArgumentException('The table name contains invalid characters');
  48. }
  49. parent::__construct();
  50. $this->strTable = $strTable;
  51. }
  52. /**
  53. * Load a set of DCA files
  54. *
  55. * @param boolean $blnNoCache If true, the cache will be bypassed
  56. */
  57. public function load($blnNoCache=false)
  58. {
  59. if (\func_num_args() > 0)
  60. {
  61. trigger_deprecation('contao/core-bundle', '4.13', 'Calling "%s" with the $blnNoCache parameter has been deprecated and will no longer work in Contao 5.0.', __METHOD__);
  62. }
  63. try
  64. {
  65. $this->loadDcaFiles($blnNoCache);
  66. }
  67. catch (\Throwable $e)
  68. {
  69. unset(static::$arrLoaded['dcaFiles'][$this->strTable]);
  70. throw $e;
  71. }
  72. }
  73. /**
  74. * Load the DCA files
  75. *
  76. * @param boolean $blnNoCache
  77. */
  78. private function loadDcaFiles($blnNoCache)
  79. {
  80. // Return if the data has been loaded already
  81. if (!$blnNoCache && isset(static::$arrLoaded['dcaFiles'][$this->strTable]))
  82. {
  83. return;
  84. }
  85. static::$arrLoaded['dcaFiles'][$this->strTable] = true; // see #6145
  86. $strCacheDir = System::getContainer()->getParameter('kernel.cache_dir');
  87. // Try to load from cache
  88. if (file_exists($strCacheDir . '/contao/dca/' . $this->strTable . '.php'))
  89. {
  90. include $strCacheDir . '/contao/dca/' . $this->strTable . '.php';
  91. }
  92. else
  93. {
  94. try
  95. {
  96. $files = System::getContainer()->get('contao.resource_locator')->locate('dca/' . $this->strTable . '.php', null, false);
  97. }
  98. catch (\InvalidArgumentException $e)
  99. {
  100. $files = array();
  101. }
  102. foreach ($files as $file)
  103. {
  104. include $file;
  105. }
  106. }
  107. // Set the ptable dynamically
  108. $this->setDynamicPTable();
  109. // HOOK: allow loading custom settings
  110. if (isset($GLOBALS['TL_HOOKS']['loadDataContainer']) && \is_array($GLOBALS['TL_HOOKS']['loadDataContainer']))
  111. {
  112. foreach ($GLOBALS['TL_HOOKS']['loadDataContainer'] as $callback)
  113. {
  114. $this->import($callback[0]);
  115. $this->{$callback[0]}->{$callback[1]}($this->strTable);
  116. }
  117. }
  118. $projectDir = System::getContainer()->getParameter('kernel.project_dir');
  119. // Local configuration file
  120. if (file_exists($projectDir . '/system/config/dcaconfig.php'))
  121. {
  122. trigger_deprecation('contao/core-bundle', '4.3', 'Using the "dcaconfig.php" file has been deprecated and will no longer work in Contao 5.0. Create custom DCA files in the "contao/dca" folder instead.');
  123. include $projectDir . '/system/config/dcaconfig.php';
  124. }
  125. $this->addDefaultLabels($blnNoCache);
  126. }
  127. /**
  128. * Add the default labels (see #509)
  129. *
  130. * @param boolean $blnNoCache
  131. */
  132. private function addDefaultLabels($blnNoCache)
  133. {
  134. // Operations
  135. foreach (array('global_operations', 'operations') as $key)
  136. {
  137. if (!isset($GLOBALS['TL_DCA'][$this->strTable]['list'][$key]))
  138. {
  139. continue;
  140. }
  141. foreach ($GLOBALS['TL_DCA'][$this->strTable]['list'][$key] as $k=>&$v)
  142. {
  143. if (\is_array($v) && \array_key_exists('label', $v))
  144. {
  145. continue;
  146. }
  147. if (isset($GLOBALS['TL_LANG'][$this->strTable][$k]) || !isset($GLOBALS['TL_LANG']['DCA'][$k]))
  148. {
  149. $v['label'] = &$GLOBALS['TL_LANG'][$this->strTable][$k];
  150. }
  151. elseif (isset($GLOBALS['TL_LANG']['DCA'][$k]))
  152. {
  153. $v['label'] = &$GLOBALS['TL_LANG']['DCA'][$k];
  154. }
  155. }
  156. unset($v);
  157. }
  158. // Fields
  159. if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields']))
  160. {
  161. foreach ($GLOBALS['TL_DCA'][$this->strTable]['fields'] as $k=>&$v)
  162. {
  163. if (isset($v['label']))
  164. {
  165. continue;
  166. }
  167. $v['label'] = &$GLOBALS['TL_LANG'][$this->strTable][$k];
  168. }
  169. unset($v);
  170. }
  171. }
  172. /**
  173. * Sets the parent table for the current table, if enabled and not set.
  174. */
  175. private function setDynamicPTable(): void
  176. {
  177. if (!($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable'] ?? null) || !isset($GLOBALS['BE_MOD']) || isset($GLOBALS['TL_DCA'][$this->strTable]['config']['ptable']))
  178. {
  179. return;
  180. }
  181. if (!$do = Input::get('do'))
  182. {
  183. return;
  184. }
  185. foreach (array_merge(...array_values($GLOBALS['BE_MOD'])) as $key => $module)
  186. {
  187. if ($do !== $key || !isset($module['tables']) || !\is_array($module['tables']))
  188. {
  189. continue;
  190. }
  191. foreach ($module['tables'] as $table)
  192. {
  193. Controller::loadDataContainer($table);
  194. $ctable = $GLOBALS['TL_DCA'][$table]['config']['ctable'] ?? array();
  195. if (\in_array($this->strTable, $ctable, true))
  196. {
  197. $GLOBALS['TL_DCA'][$this->strTable]['config']['ptable'] = $table;
  198. return;
  199. }
  200. }
  201. }
  202. }
  203. }
  204. class_alias(DcaLoader::class, 'DcaLoader');