TYPO3CMS  8
 All Classes Namespaces Files Functions Variables Pages
CategoryRegistry.php
Go to the documentation of this file.
1 <?php
2 namespace TYPO3\CMS\Core\Category;
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 
140  public function getCategoryFieldsForTable(array &$configuration)
141  {
142  $table = '';
143  $menuType = isset($configuration['row']['menu_type'][0]) ? $configuration['row']['menu_type'][0] : '';
144  // Define the table being looked up from the type of menu
145  if ($menuType === 'categorized_pages') {
146  $table = 'pages';
147  } elseif ($menuType === 'categorized_content') {
148  $table = 'tt_content';
149  }
150  // Return early if no table is defined
151  if (empty($table)) {
152  throw new \UnexpectedValueException('The given menu_type is not supported.', 1381823570);
153  }
154  // Loop on all registries and find entries for the correct table
155  foreach ($this->registry as $tableName => $fields) {
156  if ($tableName === $table) {
157  foreach ($fields as $fieldName => $options) {
158  $fieldLabel = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
159  $configuration['items'][] = [$fieldLabel, $fieldName];
160  }
161  }
162  }
163  }
164 
172  public function isRegistered($tableName, $fieldName = 'categories')
173  {
174  return isset($this->registry[$tableName][$fieldName]);
175  }
176 
182  public function getDatabaseTableDefinitions()
183  {
184  $sql = '';
185  foreach ($this->getExtensionKeys() as $extensionKey) {
186  $sql .= $this->getDatabaseTableDefinition($extensionKey);
187  }
188  return $sql;
189  }
190 
197  public function getDatabaseTableDefinition($extensionKey)
198  {
199  if (!isset($this->extensions[$extensionKey]) || !is_array($this->extensions[$extensionKey])) {
200  return '';
201  }
202  $sql = '';
203 
204  foreach ($this->extensions[$extensionKey] as $tableName => $fields) {
205  foreach ($fields as $fieldName) {
206  $sql .= sprintf($this->template, $tableName, $fieldName);
207  }
208  }
209  return $sql;
210  }
211 
219  {
221  foreach ($this->registry as $tableName => $fields) {
222  foreach ($fields as $fieldName => $_) {
223  $this->applyTcaForTableAndField($tableName, $fieldName);
224  }
225  }
226  }
227 
234  protected function applyTcaForTableAndField($tableName, $fieldName)
235  {
236  $this->addTcaColumn($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
237  $this->addToAllTCAtypes($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
238  }
239 
245  protected function registerDefaultCategorizedTables()
246  {
247  $defaultCategorizedTables = GeneralUtility::trimExplode(
248  ',',
249  $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'],
250  true
251  );
252  foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
253  if (!$this->isRegistered($defaultCategorizedTable)) {
254  $this->add('core', $defaultCategorizedTable, 'categories');
255  }
256  }
257  }
258 
270  protected function addToAllTCAtypes($tableName, $fieldName, array $options)
271  {
272 
273  // Makes sure to add more TCA to an existing structure
274  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
275  if (empty($options['fieldList'])) {
276  $fieldList = $this->addCategoryTab($tableName, $fieldName);
277  } else {
278  $fieldList = $options['fieldList'];
279  }
280 
281  $typesList = '';
282  if (isset($options['typesList']) && $options['typesList'] !== '') {
283  $typesList = $options['typesList'];
284  }
285 
286  $position = '';
287  if (!empty($options['position'])) {
288  $position = $options['position'];
289  }
290 
291  // Makes the new "categories" field to be visible in TSFE.
292  ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
293  }
294  }
295 
304  protected function addCategoryTab($tableName, $fieldName)
305  {
306  $fieldList = '';
307  if (!isset($this->addedCategoryTabs[$tableName])) {
308  $fieldList .= '--div--;LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_category.tabs.category, ';
309  $this->addedCategoryTabs[$tableName] = $tableName;
310  }
311  $fieldList .= $fieldName;
312  return $fieldList;
313  }
314 
328  protected function addTcaColumn($tableName, $fieldName, array $options)
329  {
330  // Makes sure to add more TCA to an existing structure
331  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
332  // Take specific label into account
333  $label = 'LLL:EXT:lang/Resources/Private/Language/locallang_tca.xlf:sys_category.categories';
334  if (!empty($options['label'])) {
335  $label = $options['label'];
336  }
337 
338  // Take specific value of exclude flag into account
339  $exclude = true;
340  if (isset($options['exclude'])) {
341  $exclude = (bool)$options['exclude'];
342  }
343 
344  $fieldConfiguration = empty($options['fieldConfiguration']) ? [] : $options['fieldConfiguration'];
345 
346  $columns = [
347  $fieldName => [
348  'exclude' => $exclude,
349  'label' => $label,
350  'config' => static::getTcaFieldConfiguration($tableName, $fieldName, $fieldConfiguration),
351  ],
352  ];
353 
354  if (isset($options['l10n_mode'])) {
355  $columns[$fieldName]['l10n_mode'] = $options['l10n_mode'];
356  }
357  if (isset($options['l10n_display'])) {
358  $columns[$fieldName]['l10n_display'] = $options['l10n_display'];
359  }
360  if (isset($options['displayCond'])) {
361  $columns[$fieldName]['displayCond'] = $options['displayCond'];
362  }
363 
364  // Register opposite references for the foreign side of a relation
365  if (empty($GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
366  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName] = [];
367  }
368  if (!in_array($fieldName, $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
369  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName][] = $fieldName;
370  }
371 
372  // Add field to interface list per default (unless the 'interface' property is FALSE)
373  if (
374  (!isset($options['interface']) || $options['interface'])
375  && !empty($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'])
376  && !GeneralUtility::inList($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'], $fieldName)
377  ) {
378  $GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'] .= ',' . $fieldName;
379  }
380 
381  // Adding fields to an existing table definition
382  ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
383  }
384  }
385 
397  public static function getTcaFieldConfiguration($tableName, $fieldName = 'categories', array $fieldConfigurationOverride = [])
398  {
399  // Forges a new field, default name is "categories"
400  $fieldConfiguration = [
401  'type' => 'select',
402  'renderType' => 'selectTree',
403  'foreign_table' => 'sys_category',
404  'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.sorting ASC',
405  'MM' => 'sys_category_record_mm',
406  'MM_opposite_field' => 'items',
407  'MM_match_fields' => [
408  'tablenames' => $tableName,
409  'fieldname' => $fieldName,
410  ],
411  'size' => 20,
412  'maxitems' => 9999,
413  'treeConfig' => [
414  'parentField' => 'parent',
415  'appearance' => [
416  'expandAll' => true,
417  'showHeader' => true,
418  'maxLevels' => 99,
419  ],
420  ],
421  ];
422 
423  // Merge changes to TCA configuration
424  if (!empty($fieldConfigurationOverride)) {
426  $fieldConfiguration,
427  $fieldConfigurationOverride
428  );
429  }
430 
431  return $fieldConfiguration;
432  }
433 
441  public function addCategoryDatabaseSchemaToTablesDefinition(array $sqlString)
442  {
444  $sqlString[] = $this->getDatabaseTableDefinitions();
445  return ['sqlString' => $sqlString];
446  }
447 
456  public function addExtensionCategoryDatabaseSchemaToTablesDefinition(array $sqlString, $extensionKey)
457  {
458  $sqlString[] = $this->getDatabaseTableDefinition($extensionKey);
459  return ['sqlString' => $sqlString, 'extensionKey' => $extensionKey];
460  }
461 
465  protected function getLanguageService()
466  {
467  return $GLOBALS['LANG'];
468  }
469 
476  protected function remove($tableName, $fieldName)
477  {
478  if (!$this->isRegistered($tableName, $fieldName)) {
479  return;
480  }
481 
482  unset($this->registry[$tableName][$fieldName]);
483 
484  foreach ($this->extensions as $extensionKey => $tableFieldConfig) {
485  foreach ($tableFieldConfig as $extTableName => $fieldNameArray) {
486  if ($extTableName === $tableName && isset($fieldNameArray[$fieldName])) {
487  unset($this->extensions[$extensionKey][$tableName][$fieldName]);
488  break;
489  }
490  }
491  }
492 
493  // If no more fields are configured we unregister the categories tab.
494  if (empty($this->registry[$tableName]) && isset($this->addedCategoryTabs[$tableName])) {
495  unset($this->addedCategoryTabs[$tableName]);
496  }
497  }
498 }
getCategoryFieldsForTable(array &$configuration)
static getTcaFieldConfiguration($tableName, $fieldName= 'categories', array $fieldConfigurationOverride=[])
static addToAllTCAtypes($table, $newFieldsString, $typeList= '', $position= '')
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
applyTcaForTableAndField($tableName, $fieldName)
addCategoryDatabaseSchemaToTablesDefinition(array $sqlString)
add($extensionKey, $tableName, $fieldName= 'categories', array $options=[], $override=false)
static mergeRecursiveWithOverrule(array &$original, array $overrule, $addKeys=true, $includeEmptyValues=true, $enableUnsetFeature=true)
if(TYPO3_MODE=== 'BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']
addTcaColumn($tableName, $fieldName, array $options)
static makeInstance($className,...$constructorArguments)
isRegistered($tableName, $fieldName= 'categories')
addExtensionCategoryDatabaseSchemaToTablesDefinition(array $sqlString, $extensionKey)
addToAllTCAtypes($tableName, $fieldName, array $options)