TYPO3  7.6
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 = array();
32 
36  protected $extensions = array();
37 
41  protected $addedCategoryTabs = array();
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 = array(), $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']) && isset($GLOBALS['TCA'][$tableName]['ctrl']['dynamicConfigFile'])) {
104  // Handle deprecated old style dynamic TCA column loading.
106  }
107 
108  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
109  $this->applyTcaForTableAndField($tableName, $fieldName);
110  $didRegister = true;
111  }
112  }
113 
114  return $didRegister;
115  }
116 
122  public function getExtensionKeys()
123  {
124  return array_keys($this->extensions);
125  }
126 
132  public function getCategorizedTables()
133  {
134  return array_keys($this->registry);
135  }
136 
145  public function getCategoryFieldsForTable(array &$configuration)
146  {
147  $table = '';
148  $menuType = isset($configuration['row']['menu_type'][0]) ? $configuration['row']['menu_type'][0] : '';
149  // Define the table being looked up from the type of menu
150  if ($menuType === 'categorized_pages') {
151  $table = 'pages';
152  } elseif ($menuType === 'categorized_content') {
153  $table = 'tt_content';
154  }
155  // Return early if no table is defined
156  if (empty($table)) {
157  throw new \UnexpectedValueException('The given menu_type is not supported.', 1381823570);
158  }
159  // Loop on all registries and find entries for the correct table
160  foreach ($this->registry as $tableName => $fields) {
161  if ($tableName === $table) {
162  foreach ($fields as $fieldName => $options) {
163  $fieldLabel = $this->getLanguageService()->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
164  $configuration['items'][] = array($fieldLabel, $fieldName);
165  }
166  }
167  }
168  }
169 
177  public function isRegistered($tableName, $fieldName = 'categories')
178  {
179  return isset($this->registry[$tableName][$fieldName]);
180  }
181 
187  public function getDatabaseTableDefinitions()
188  {
189  $sql = '';
190  foreach ($this->getExtensionKeys() as $extensionKey) {
191  $sql .= $this->getDatabaseTableDefinition($extensionKey);
192  }
193  return $sql;
194  }
195 
202  public function getDatabaseTableDefinition($extensionKey)
203  {
204  if (!isset($this->extensions[$extensionKey]) || !is_array($this->extensions[$extensionKey])) {
205  return '';
206  }
207  $sql = '';
208 
209  foreach ($this->extensions[$extensionKey] as $tableName => $fields) {
210  foreach ($fields as $fieldName) {
211  $sql .= sprintf($this->template, $tableName, $fieldName);
212  }
213  }
214  return $sql;
215  }
216 
224  {
226  foreach ($this->registry as $tableName => $fields) {
227  foreach ($fields as $fieldName => $_) {
228  $this->applyTcaForTableAndField($tableName, $fieldName);
229  }
230  }
231  }
232 
239  protected function applyTcaForTableAndField($tableName, $fieldName)
240  {
241  $this->addTcaColumn($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
242  $this->addToAllTCAtypes($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
243  }
244 
250  protected function registerDefaultCategorizedTables()
251  {
252  $defaultCategorizedTables = GeneralUtility::trimExplode(
253  ',',
254  $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'],
255  true
256  );
257  foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
258  if (!$this->isRegistered($defaultCategorizedTable)) {
259  $this->add('core', $defaultCategorizedTable, 'categories');
260  }
261  }
262  }
263 
275  protected function addToAllTCAtypes($tableName, $fieldName, array $options)
276  {
277 
278  // Makes sure to add more TCA to an existing structure
279  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
280  if (empty($options['fieldList'])) {
281  $fieldList = $this->addCategoryTab($tableName, $fieldName);
282  } else {
283  $fieldList = $options['fieldList'];
284  }
285 
286  $typesList = '';
287  if (!empty($options['typesList'])) {
288  $typesList = $options['typesList'];
289  }
290 
291  $position = '';
292  if (!empty($options['position'])) {
293  $position = $options['position'];
294  }
295 
296  // Makes the new "categories" field to be visible in TSFE.
297  ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
298  }
299  }
300 
309  protected function addCategoryTab($tableName, $fieldName)
310  {
311  $fieldList = '';
312  if (!isset($this->addedCategoryTabs[$tableName])) {
313  $fieldList .= '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ';
314  $this->addedCategoryTabs[$tableName] = $tableName;
315  }
316  $fieldList .= $fieldName;
317  return $fieldList;
318  }
319 
333  protected function addTcaColumn($tableName, $fieldName, array $options)
334  {
335  // Makes sure to add more TCA to an existing structure
336  if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
337  // Take specific label into account
338  $label = 'LLL:EXT:lang/locallang_tca.xlf:sys_category.categories';
339  if (!empty($options['label'])) {
340  $label = $options['label'];
341  }
342 
343  // Take specific value of exclude flag into account
344  $exclude = true;
345  if (isset($options['exclude'])) {
346  $exclude = (bool)$options['exclude'];
347  }
348 
349  $fieldConfiguration = empty($options['fieldConfiguration']) ? array() : $options['fieldConfiguration'];
350 
351  $columns = array(
352  $fieldName => array(
353  'exclude' => $exclude,
354  'label' => $label,
355  'config' => static::getTcaFieldConfiguration($tableName, $fieldName, $fieldConfiguration),
356  ),
357  );
358 
359  if (isset($options['l10n_mode'])) {
360  $columns[$fieldName]['l10n_mode'] = $options['l10n_mode'];
361  }
362  if (isset($options['l10n_display'])) {
363  $columns[$fieldName]['l10n_display'] = $options['l10n_display'];
364  }
365 
366  // Register opposite references for the foreign side of a relation
367  if (empty($GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
368  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName] = array();
369  }
370  if (!in_array($fieldName, $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
371  $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName][] = $fieldName;
372  }
373 
374  // Add field to interface list per default (unless the 'interface' property is FALSE)
375  if (
376  (!isset($options['interface']) || $options['interface'])
377  && !empty($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'])
378  && !GeneralUtility::inList($GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'], $fieldName)
379  ) {
380  $GLOBALS['TCA'][$tableName]['interface']['showRecordFieldList'] .= ',' . $fieldName;
381  }
382 
383  // Adding fields to an existing table definition
384  ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
385  }
386  }
387 
399  public static function getTcaFieldConfiguration($tableName, $fieldName = 'categories', array $fieldConfigurationOverride = array())
400  {
401  // Forges a new field, default name is "categories"
402  $fieldConfiguration = array(
403  'type' => 'select',
404  'renderType' => 'selectTree',
405  'foreign_table' => 'sys_category',
406  'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.sorting ASC',
407  'MM' => 'sys_category_record_mm',
408  'MM_opposite_field' => 'items',
409  'MM_match_fields' => array(
410  'tablenames' => $tableName,
411  'fieldname' => $fieldName,
412  ),
413  'size' => 10,
414  'autoSizeMax' => 50,
415  'maxitems' => 9999,
416  'treeConfig' => array(
417  'parentField' => 'parent',
418  'appearance' => array(
419  'expandAll' => true,
420  'showHeader' => true,
421  'maxLevels' => 99,
422  ),
423  ),
424  );
425 
426  // Merge changes to TCA configuration
427  if (!empty($fieldConfigurationOverride)) {
429  $fieldConfiguration,
430  $fieldConfigurationOverride
431  );
432  }
433 
434  return $fieldConfiguration;
435  }
436 
444  public function addCategoryDatabaseSchemaToTablesDefinition(array $sqlString)
445  {
447  $sqlString[] = $this->getDatabaseTableDefinitions();
448  return array('sqlString' => $sqlString);
449  }
450 
459  public function addExtensionCategoryDatabaseSchemaToTablesDefinition(array $sqlString, $extensionKey)
460  {
461  $sqlString[] = $this->getDatabaseTableDefinition($extensionKey);
462  return array('sqlString' => $sqlString, 'extensionKey' => $extensionKey);
463  }
464 
468  protected function getLanguageService()
469  {
470  return $GLOBALS['LANG'];
471  }
472 
479  protected function remove($tableName, $fieldName)
480  {
481  if (!$this->isRegistered($tableName, $fieldName)) {
482  return;
483  }
484 
485  unset($this->registry[$tableName][$fieldName]);
486 
487  foreach ($this->extensions as $extensionKey => $tableFieldConfig) {
488  foreach ($tableFieldConfig as $extTableName => $fieldNameArray) {
489  if ($extTableName === $tableName && isset($fieldNameArray[$fieldName])) {
490  unset($this->extensions[$extensionKey][$tableName][$fieldName]);
491  break;
492  }
493  }
494  }
495 
496  // If no more fields are configured we unregister the categories tab.
497  if (empty($this->registry[$tableName]) && isset($this->addedCategoryTabs[$tableName])) {
498  unset($this->addedCategoryTabs[$tableName]);
499  }
500  }
501 }