[TASK] Re-work/simplify copyright header in PHP files - Part 2
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Category / CategoryRegistry.php
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
17 use TYPO3\CMS\Core\Utility\ArrayUtility;
18 use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
19
20 /**
21 * Class to register category configurations.
22 *
23 * @author Fabien Udriot <fabien.udriot@typo3.org>
24 * @author Oliver Hader <oliver.hader@typo3.org>
25 */
26 class CategoryRegistry implements \TYPO3\CMS\Core\SingletonInterface {
27
28 /**
29 * @var array
30 */
31 protected $registry = array();
32
33 /**
34 * @var array
35 */
36 protected $extensions = array();
37
38 /**
39 * @var array
40 */
41 protected $addedCategoryTabs = array();
42
43 /**
44 * @var string
45 */
46 protected $template = '';
47
48 /**
49 * Returns a class instance
50 *
51 * @return \TYPO3\CMS\Core\Category\CategoryRegistry
52 */
53 static public function getInstance() {
54 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(__CLASS__);
55 }
56
57 /**
58 * Creates this object.
59 */
60 public function __construct() {
61 $this->template = str_repeat(PHP_EOL, 3) . 'CREATE TABLE %s (' . PHP_EOL
62 . ' %s int(11) DEFAULT \'0\' NOT NULL' . PHP_EOL . ');' . str_repeat(PHP_EOL, 3);
63 }
64
65 /**
66 * Adds a new category configuration to this registry.
67 * TCA changes are directly applied
68 *
69 * @param string $extensionKey Extension key to be used
70 * @param string $tableName Name of the table to be registered
71 * @param string $fieldName Name of the field to be registered
72 * @param array $options Additional configuration options
73 * + fieldList: field configuration to be added to showitems
74 * + typesList: list of types that shall visualize the categories field
75 * + position: insert position of the categories field
76 * + label: backend label of the categories field
77 * + fieldConfiguration: TCA field config array to override defaults
78 * @return boolean
79 * @throws \InvalidArgumentException
80 * @throws \RuntimeException
81 */
82 public function add($extensionKey, $tableName, $fieldName = 'categories', array $options = array()) {
83 $didRegister = FALSE;
84 if (empty($tableName) || !is_string($tableName)) {
85 throw new \InvalidArgumentException('No or invalid table name "' . $tableName . '" given.', 1369122038);
86 }
87 if (empty($extensionKey) || !is_string($extensionKey)) {
88 throw new \InvalidArgumentException('No or invalid extension key "' . $extensionKey . '" given.', 1397836158);
89 }
90
91 if (!$this->isRegistered($tableName, $fieldName)) {
92 $this->registry[$tableName][$fieldName] = $options;
93 $this->extensions[$extensionKey][$tableName][$fieldName] = $fieldName;
94
95 if (!isset($GLOBALS['TCA'][$tableName]['columns']) && isset($GLOBALS['TCA'][$tableName]['ctrl']['dynamicConfigFile'])) {
96 // Handle deprecated old style dynamic TCA column loading.
97 ExtensionManagementUtility::loadNewTcaColumnsConfigFiles();
98 }
99
100 if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
101 $this->applyTcaForTableAndField($tableName, $fieldName);
102 $didRegister = TRUE;
103 }
104 }
105
106 return $didRegister;
107 }
108
109 /**
110 * Gets the registered category configurations.
111 *
112 * @deprecated since 6.2 will be removed two versions later - Use ->isRegistered to get information about registered category fields.
113 * @return array
114 */
115 public function get() {
116 \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
117 return $this->registry;
118 }
119
120 /**
121 * Gets all extension keys that registered a category configuration.
122 *
123 * @return array
124 */
125 public function getExtensionKeys() {
126 return array_keys($this->extensions);
127 }
128
129 /**
130 * Gets all categorized tables
131 *
132 * @return array
133 */
134 public function getCategorizedTables() {
135 return array_keys($this->registry);
136 }
137
138 /**
139 * Returns a list of category fields for a given table for populating selector "category_field"
140 * in tt_content table (called as itemsProcFunc).
141 *
142 * @param array $configuration Current field configuration
143 * @param \TYPO3\CMS\Backend\Form\FormEngine $formObject Back-reference to the calling object
144 * @throws \UnexpectedValueException
145 * @return void
146 */
147 public function getCategoryFieldsForTable(array &$configuration, \TYPO3\CMS\Backend\Form\FormEngine $formObject) {
148 $table = '';
149 // Define the table being looked up from the type of menu
150 if ($configuration['row']['menu_type'] == 'categorized_pages') {
151 $table = 'pages';
152 } elseif ($configuration['row']['menu_type'] == '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 = $GLOBALS['LANG']->sL($GLOBALS['TCA'][$tableName]['columns'][$fieldName]['label']);
164 $configuration['items'][] = array($fieldLabel, $fieldName);
165 }
166 }
167 }
168 }
169
170 /**
171 * Tells whether a table has a category configuration in the registry.
172 *
173 * @param string $tableName Name of the table to be looked up
174 * @param string $fieldName Name of the field to be looked up
175 * @return boolean
176 */
177 public function isRegistered($tableName, $fieldName = 'categories') {
178 return isset($this->registry[$tableName][$fieldName]);
179 }
180
181 /**
182 * Generates tables definitions for all registered tables.
183 *
184 * @return string
185 */
186 public function getDatabaseTableDefinitions() {
187 $sql = '';
188 foreach ($this->getExtensionKeys() as $extensionKey) {
189 $sql .= $this->getDatabaseTableDefinition($extensionKey);
190 }
191 return $sql;
192 }
193
194 /**
195 * Generates table definitions for registered tables by an extension.
196 *
197 * @param string $extensionKey Extension key to have the database definitions created for
198 * @return string
199 */
200 public function getDatabaseTableDefinition($extensionKey) {
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
214 /**
215 * @deprecated Since 6.2.2. This method was never intended to be called by extensions. Is is now deprecated and will be removed without substitution after two versions.
216 */
217 public function applyTca() {
218 \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
219 }
220
221 /**
222 * Apply TCA to all registered tables
223 *
224 * @return void
225 * @internal
226 */
227 public function applyTcaForPreRegisteredTables() {
228 $this->registerDefaultCategorizedTables();
229 foreach ($this->registry as $tableName => $fields) {
230 foreach (array_keys($fields) as $fieldName) {
231 $this->applyTcaForTableAndField($tableName, $fieldName);
232 }
233 }
234 }
235
236 /**
237 * Applies the additions directly to the TCA
238 *
239 * @param string $tableName
240 * @param string $fieldName
241 */
242 protected function applyTcaForTableAndField($tableName, $fieldName) {
243 $this->addTcaColumn($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
244 $this->addToAllTCAtypes($tableName, $fieldName, $this->registry[$tableName][$fieldName]);
245 }
246
247 /**
248 * Add default categorized tables to the registry
249 *
250 * @return void
251 */
252 protected function registerDefaultCategorizedTables() {
253 $defaultCategorizedTables = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(
254 ',',
255 $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'],
256 TRUE
257 );
258 foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
259 if (!$this->isRegistered($defaultCategorizedTable)) {
260 $this->add('core', $defaultCategorizedTable, 'categories');
261 }
262 }
263 }
264
265 /**
266 * Add a new field into the TCA types -> showitem
267 *
268 * @param string $tableName Name of the table to be categorized
269 * @param string $fieldName Name of the field to be used to store categories
270 * @param array $options Additional configuration options
271 * + fieldList: field configuration to be added to showitems
272 * + typesList: list of types that shall visualize the categories field
273 * + position: insert position of the categories field
274 * @return void
275 */
276 protected function addToAllTCAtypes($tableName, $fieldName, array $options) {
277
278 // Makes sure to add more TCA to an existing structure
279 if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
280
281 if (empty($options['fieldList'])) {
282 $fieldList = $this->addCategoryTab($tableName, $fieldName);
283 } else {
284 $fieldList = $options['fieldList'];
285 }
286
287 $typesList = '';
288 if (!empty($options['typesList'])) {
289 $typesList = $options['typesList'];
290 }
291
292 $position = '';
293 if (!empty($options['position'])) {
294 $position = $options['position'];
295 }
296
297 // Makes the new "categories" field to be visible in TSFE.
298 ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
299
300 }
301 }
302
303 /**
304 * Creates the 'fieldList' string for $fieldName which includes a categories tab.
305 * But only one categories tab is added per table.
306 *
307 * @param string $tableName
308 * @param string $fieldName
309 * @return string
310 */
311 protected function addCategoryTab($tableName, $fieldName) {
312 $fieldList = '';
313 if (!in_array($tableName, $this->addedCategoryTabs)) {
314 $fieldList .= '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ';
315 $this->addedCategoryTabs[] = $tableName;
316 }
317 $fieldList .= $fieldName;
318 return $fieldList;
319 }
320
321 /**
322 * Add a new TCA Column
323 *
324 * @param string $tableName Name of the table to be categorized
325 * @param string $fieldName Name of the field to be used to store categories
326 * @param array $options Additional configuration options
327 * + fieldConfiguration: TCA field config array to override defaults
328 * + label: backend label of the categories field
329 * @return void
330 */
331 protected function addTcaColumn($tableName, $fieldName, array $options) {
332 // Makes sure to add more TCA to an existing structure
333 if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
334 // Take specific label into account
335 $label = 'LLL:EXT:lang/locallang_tca.xlf:sys_category.categories';
336 if (!empty($options['label'])) {
337 $label = $options['label'];
338 }
339
340 // Take specific value of exclude flag into account
341 $exclude = TRUE;
342 if (isset($options['exclude'])) {
343 $exclude = (bool)$options['exclude'];
344 }
345
346 $fieldConfiguration = empty($options['fieldConfiguration']) ? array() : $options['fieldConfiguration'];
347
348 $columns = array(
349 $fieldName => array(
350 'exclude' => $exclude,
351 'label' => $label,
352 'config' => static::getTcaFieldConfiguration($tableName, $fieldName, $fieldConfiguration),
353 ),
354 );
355
356 if (empty($GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
357 $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName] = array();
358 }
359 if (!in_array($fieldName, $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName])) {
360 $GLOBALS['TCA']['sys_category']['columns']['items']['config']['MM_oppositeUsage'][$tableName][] = $fieldName;
361 }
362
363 // Adding fields to an existing table definition
364 ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
365 }
366 }
367
368 /**
369 * Get the config array for given table and field.
370 * This method does NOT take care of adding sql fields, adding the field to TCA types
371 * nor does it set the MM_oppositeUsage in the sys_category TCA. This has to be taken care of manually!
372 *
373 * @param string $tableName The table name
374 * @param string $fieldName The field name (default categories)
375 * @param array $fieldConfigurationOverride Changes to the default configuration
376 * @return array
377 * @api
378 */
379 static public function getTcaFieldConfiguration($tableName, $fieldName = 'categories', array $fieldConfigurationOverride = array()) {
380 // Forges a new field, default name is "categories"
381 $fieldConfiguration = array(
382 'type' => 'select',
383 'foreign_table' => 'sys_category',
384 'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.sorting ASC',
385 'MM' => 'sys_category_record_mm',
386 'MM_opposite_field' => 'items',
387 'MM_match_fields' => array(
388 'tablenames' => $tableName,
389 'fieldname' => $fieldName,
390 ),
391 'size' => 10,
392 'autoSizeMax' => 50,
393 'maxitems' => 9999,
394 'renderMode' => 'tree',
395 'treeConfig' => array(
396 'parentField' => 'parent',
397 'appearance' => array(
398 'expandAll' => TRUE,
399 'showHeader' => TRUE,
400 'maxLevels' => 99,
401 ),
402 ),
403 );
404
405 // Merge changes to TCA configuration
406 if (!empty($fieldConfigurationOverride)) {
407 ArrayUtility::mergeRecursiveWithOverrule(
408 $fieldConfiguration,
409 $fieldConfigurationOverride
410 );
411 }
412
413 return $fieldConfiguration;
414 }
415
416 /**
417 * A slot method to inject the required category database fields to the
418 * tables definition string
419 *
420 * @param array $sqlString
421 * @return array
422 */
423 public function addCategoryDatabaseSchemaToTablesDefinition(array $sqlString) {
424 $this->registerDefaultCategorizedTables();
425 $sqlString[] = $this->getDatabaseTableDefinitions();
426 return array('sqlString' => $sqlString);
427 }
428
429 /**
430 * A slot method to inject the required category database fields of an
431 * extension to the tables definition string
432 *
433 * @param array $sqlString
434 * @param string $extensionKey
435 * @return array
436 */
437 public function addExtensionCategoryDatabaseSchemaToTablesDefinition(array $sqlString, $extensionKey) {
438 $sqlString[] = $this->getDatabaseTableDefinition($extensionKey);
439 return array('sqlString' => $sqlString, 'extensionKey' => $extensionKey);
440 }
441 }