TYPO3 CMS  TYPO3_8-7
CategoryRegistry.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
22 
27 {
31  protected $registry = [];
32 
36  protected $extensions = [];
37 
41  protected $addedCategoryTabs = [];
42 
46  protected $template = '';
47 
53  public static function getInstance()
54  {
55  return GeneralUtility::makeInstance(__CLASS__);
56  }
57 
61  public function __construct()
62  {
63  $this->template = str_repeat(PHP_EOL, 3) . 'CREATE TABLE %s (' . PHP_EOL
64  . ' %s int(11) DEFAULT \'0\' NOT NULL' . PHP_EOL . ');' . str_repeat(PHP_EOL, 3);
65  }
66 
85  public function add($extensionKey, $tableName, $fieldName = 'categories', array $options = [], $override = false)
86  {
87  $didRegister = false;
88  if (empty($tableName) || !is_string($tableName)) {
89  throw new \InvalidArgumentException('No or invalid table name "' . $tableName . '" given.', 1369122038);
90  }
91  if (empty($extensionKey) || !is_string($extensionKey)) {
92  throw new \InvalidArgumentException('No or invalid extension key "' . $extensionKey . '" given.', 1397836158);
93  }
94 
95  if ($override) {
96  $this->remove($tableName, $fieldName);
97  }
98 
99  if (!$this->isRegistered($tableName, $fieldName)) {
100  $this->registry[$tableName][$fieldName] = $options;
101  $this->extensions[$extensionKey][$tableName][$fieldName] = $fieldName;
102 
103  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
104  $this->applyTcaForTableAndField($tableName, $fieldName);
105  $didRegister = true;
106  }
107  }
108 
109  return $didRegister;
110  }
111 
117  public function getExtensionKeys()
118  {
119  return array_keys($this->extensions);
120  }
121 
127  public function getCategorizedTables()
128  {
129  return array_keys($this->registry);
130  }
131 
139  public function getCategoryFieldsForTable(array &$configuration)
140  {
141  $table = $configuration['config']['itemsProcConfig']['table'] ?? '';
142  // Lookup table for legacy menu content element
143  if (empty($table)) {
144  $menuType = $configuration['row']['menu_type'][0] ?? '';
145  // Define the table being looked up from the type of menu
146  if ($menuType === 'categorized_pages') {
147  $table = 'pages';
148  } elseif ($menuType === 'categorized_content') {
149  $table = 'tt_content';
150  }
151  }
152  // Return early if no table is defined
153  if (empty($table)) {
154  throw new \UnexpectedValueException('The given menu_type is not supported.', 1381823570);
155  }
156  // Loop on all registries and find entries for the correct table
157  foreach ($this->registry as $tableName => $fields) {
158  if ($tableName === $table) {
159  foreach ($fields as $fieldName => $options) {
160  $fieldLabel = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
161  $configuration['items'][] = [$fieldLabel, $fieldName];
162  }
163  }
164  }
165  }
166 
174  public function isRegistered($tableName, $fieldName = 'categories')
175  {
176  return isset($this->registry[$tableName][$fieldName]);
177  }
178 
184  public function getDatabaseTableDefinitions()
185  {
186  $sql = '';
187  foreach ($this->getExtensionKeys() as $extensionKey) {
188  $sql .= $this->getDatabaseTableDefinition($extensionKey);
189  }
190  return $sql;
191  }
192 
199  public function getDatabaseTableDefinition($extensionKey)
200  {
201  if (!isset($this->extensions[$extensionKey]) || !is_array($this->extensions[$extensionKey])) {
202  return '';
203  }
204  $sql = '';
205 
206  foreach ($this->extensions[$extensionKey] as $tableName => $fields) {
207  foreach ($fields as $fieldName) {
208  $sql .= sprintf($this->template, $tableName, $fieldName);
209  }
210  }
211  return $sql;
212  }
213 
220  {
222  foreach ($this->registry as $tableName => $fields) {
223  foreach ($fields as $fieldName => $_) {
224  $this->applyTcaForTableAndField($tableName, $fieldName);
225  }
226  }
227  }
228 
235  protected function applyTcaForTableAndField($tableName, $fieldName)
236  {
237  $this->addTcaColumn($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
238  $this->addToAllTCAtypes($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
239  }
240 
244  protected function registerDefaultCategorizedTables()
245  {
246  $defaultCategorizedTables = GeneralUtility::trimExplode(
247  ',',
248  $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'],
249  true
250  );
251  foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
252  if (!$this->isRegistered($defaultCategorizedTable)) {
253  $this->add('core', $defaultCategorizedTable, 'categories');
254  }
255  }
256  }
257 
268  protected function addToAllTCAtypes($tableName, $fieldName, array $options)
269  {
270 
271  // Makes sure to add more TCA to an existing structure
272  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
273  if (empty($options['fieldList'])) {
274  $fieldList = $this->addCategoryTab($tableName, $fieldName);
275  } else {
276  $fieldList = $options['fieldList'];
277  }
278 
279  $typesList = '';
280  if (isset($options['typesList']) && $options['typesList'] !== '') {
281  $typesList = $options['typesList'];
282  }
283 
284  $position = '';
285  if (!empty($options['position'])) {
286  $position = $options['position'];
287  }
288 
289  // Makes the new "categories" field to be visible in TSFE.
290  ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
291  }
292  }
293 
302  protected function addCategoryTab($tableName, $fieldName)
303  {
304  $fieldList = '';
305  if (!isset($this->addedCategoryTabs[$tableName])) {
306  $fieldList .= '--div--;LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_category.tabs.category, ';
307  $this->addedCategoryTabs[$tableName] = $tableName;
308  }
309  $fieldList .= $fieldName;
310  return $fieldList;
311  }
312 
325  protected function addTcaColumn($tableName, $fieldName, array $options)
326  {
327  // Makes sure to add more TCA to an existing structure
328  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
329  // Take specific label into account
330  $label = 'LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_category.categories';
331  if (!empty($options['label'])) {
332  $label = $options['label'];
333  }
334 
335  // Take specific value of exclude flag into account
336  $exclude = true;
337  if (isset($options['exclude'])) {
338  $exclude = (bool)$options['exclude'];
339  }
340 
341  $fieldConfiguration = empty($options['fieldConfiguration']) ? [] : $options['fieldConfiguration'];
342 
343  $columns = [
344  $fieldName => [
345  'exclude' => $exclude,
346  'label' => $label,
347  'config' => static::getTcaFieldConfiguration($tableName, $fieldName, $fieldConfiguration),
348  ],
349  ];
350 
351  if (isset($options['l10n_mode'])) {
352  $columns[$fieldName]['l10n_mode'] = $options['l10n_mode'];
353  }
354  if (isset($options['l10n_display'])) {
355  $columns[$fieldName]['l10n_display'] = $options['l10n_display'];
356  }
357  if (isset($options['displayCond'])) {
358  $columns[$fieldName]['displayCond'] = $options['displayCond'];
359  }
360 
361  // Register opposite references for the foreign side of a relation
362  if (empty($GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
363  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName] = [];
364  }
365  if (!in_array($fieldName, $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
366  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName][] = $fieldName;
367  }
368 
369  // Add field to interface list per default (unless the 'interface' property is FALSE)
370  if (
371  (!isset($options['interface']) || $options['interface'])
372  && !empty($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'])
373  && !GeneralUtility::inList($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'], $fieldName)
374  ) {
375  $GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'] .= ',' . $fieldName;
376  }
377 
378  // Adding fields to an existing table definition
379  ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
380  }
381  }
382 
394  public static function getTcaFieldConfiguration($tableName, $fieldName = 'categories', array $fieldConfigurationOverride = [])
395  {
396  // Forges a new field, default name is "categories"
397  $fieldConfiguration = [
398  'type' => 'select',
399  'renderType' => 'selectTree',
400  'foreign_table' => 'sys_category',
401  'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.sorting ASC',
402  'MM' => 'sys_category_record_mm',
403  'MM_opposite_field' => 'items',
404  'MM_match_fields' => [
405  'tablenames' => $tableName,
406  'fieldname' => $fieldName,
407  ],
408  'size' => 20,
409  'maxitems' => 9999,
410  'treeConfig' => [
411  'parentField' => 'parent',
412  'appearance' => [
413  'expandAll' => true,
414  'showHeader' => true,
415  'maxLevels' => 99,
416  ],
417  ],
418  ];
419 
420  // Merge changes to TCA configuration
421  if (!empty($fieldConfigurationOverride)) {
423  $fieldConfiguration,
424  $fieldConfigurationOverride
425  );
426  }
427 
428  return $fieldConfiguration;
429  }
430 
438  public function addCategoryDatabaseSchemaToTablesDefinition(array $sqlString)
439  {
441  $sqlString[] = $this->getDatabaseTableDefinitions();
442  return ['sqlString' => $sqlString];
443  }
444 
448  protected function getLanguageService()
449  {
450  return $GLOBALS['LANG'];
451  }
452 
459  protected function remove($tableName, $fieldName)
460  {
461  if (!$this->isRegistered($tableName, $fieldName)) {
462  return;
463  }
464 
465  unset($this->registry[$tableName][$fieldName]);
466 
467  foreach ($this->extensions as $extensionKey => $tableFieldConfig) {
468  foreach ($tableFieldConfig as $extTableName => $fieldNameArray) {
469  if ($extTableName === $tableName && isset($fieldNameArray[$fieldName])) {
470  unset($this->extensions[$extensionKey][$tableName][$fieldName]);
471  break;
472  }
473  }
474  }
475 
476  // If no more fields are configured we unregister the categories tab.
477  if (empty($this->registry[$tableName]) && isset($this->addedCategoryTabs[$tableName])) {
478  unset($this->addedCategoryTabs[$tableName]);
479  }
480  }
481 }
addToAllTCAtypes($tableName, $fieldName, array $options)
isRegistered($tableName, $fieldName='categories')
static getTcaFieldConfiguration($tableName, $fieldName='categories', array $fieldConfigurationOverride=[])
addTcaColumn($tableName, $fieldName, array $options)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static makeInstance($className,... $constructorArguments)
$fields
Definition: pages.php:4
static addToAllTCAtypes($table, $newFieldsString, $typeList='', $position='')
applyTcaForTableAndField($tableName, $fieldName)
getCategoryFieldsForTable(array &$configuration)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
addCategoryDatabaseSchemaToTablesDefinition(array $sqlString)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
add($extensionKey, $tableName, $fieldName='categories', array $options=[], $override=false)