[FEATURE] Allow multiple category fields per table
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Category / CategoryRegistry.php
1 <?php
2 namespace TYPO3\CMS\Core\Category;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012-2013 Fabien Udriot <fabien.udriot@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Class to register category configurations.
31 *
32 * @author Fabien Udriot <fabien.udriot@typo3.org>
33 * @author Oliver Hader <oliver.hader@typo3.org>
34 */
35 class CategoryRegistry implements \TYPO3\CMS\Core\SingletonInterface {
36
37 /**
38 * @var array
39 */
40 protected $registry = array();
41
42 /**
43 * @var array
44 */
45 protected $addedCategoryTabs = array();
46
47 /**
48 * @var string
49 */
50 protected $template = '';
51
52 /**
53 * Returns a class instance
54 *
55 * @return \TYPO3\CMS\Core\Category\CategoryRegistry
56 */
57 static public function getInstance() {
58 return \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(__CLASS__);
59 }
60
61 /**
62 * Creates this object.
63 */
64 public function __construct() {
65 $this->template = str_repeat(PHP_EOL, 3) . 'CREATE TABLE %s (' . PHP_EOL . ' %s int(11) DEFAULT \'0\' NOT NULL' . PHP_EOL . ');' . str_repeat(PHP_EOL, 3);
66 }
67
68 /**
69 * Adds a new category configuration to this registry.
70 *
71 * @param string $extensionKey Extension key to be used
72 * @param string $tableName Name of the table to be registered
73 * @param string $fieldName Name of the field to be registered
74 * @param array $options Additional configuration options
75 * + fieldList: field configuration to be added to showitems
76 * + typesList: list of types that shall visualize the categories field
77 * + position: insert position of the categories field
78 * + label: backend label of the categories field
79 * + fieldConfiguration: TCA field config array to override defaults
80 * @return boolean
81 * @throws \InvalidArgumentException
82 */
83 public function add($extensionKey, $tableName, $fieldName = 'categories', $options = array()) {
84 $result = FALSE;
85
86 if ($tableName === '') {
87 throw new \InvalidArgumentException('TYPO3\\CMS\\Core\\Category\\CategoryRegistry No tableName given.', 1369122038);
88 }
89
90 if (!is_array($options)) {
91 throw new \InvalidArgumentException('TYPO3\\CMS\\Core\\Category\\CategoryRegistry options parameter must be an array', 1378976970);
92 }
93
94 // Makes sure there is an existing table configuration and nothing registered yet:
95 if (isset($GLOBALS['TCA'][$tableName]) && !$this->isRegistered($tableName, $fieldName)) {
96 $this->registry[$extensionKey][$tableName][$fieldName] = $options;
97 $result = TRUE;
98 }
99 return $result;
100 }
101
102 /**
103 * Gets the registered category configurations.
104 *
105 * @deprecated since 6.2 will be removed two versions later - Use ->isRegistered to get information about registered category fields.
106 * @return array
107 */
108 public function get() {
109 \TYPO3\CMS\Core\Utility\GeneralUtility::logDeprecatedFunction();
110 return $this->registry;
111 }
112
113 /**
114 * Gets all extension keys that registered a category configuration.
115 *
116 * @return array
117 */
118 public function getExtensionKeys() {
119 return array_keys($this->registry);
120 }
121
122 /**
123 * Gets all categorized tables
124 *
125 * @return array
126 */
127 public function getCategorizedTables() {
128 $categorizedTables = array();
129
130 foreach ($this->registry as $registry) {
131 $categorizedTables = array_merge($categorizedTables, array_keys($registry));
132 }
133
134 return $categorizedTables;
135 }
136
137 /**
138 * Tells whether a table has a category configuration in the registry.
139 *
140 * @param string $tableName Name of the table to be looked up
141 * @param string $fieldName Name of the field to be looked up
142 * @return boolean
143 */
144 public function isRegistered($tableName, $fieldName = 'categories') {
145 $isRegistered = FALSE;
146 foreach ($this->registry as $configuration) {
147 if (isset($configuration[$tableName][$fieldName])) {
148 $isRegistered = TRUE;
149 break;
150 }
151 }
152 return $isRegistered;
153 }
154
155 /**
156 * Generates tables definitions for all registered tables.
157 *
158 * @return string
159 */
160 public function getDatabaseTableDefinitions() {
161 $sql = '';
162 foreach ($this->getExtensionKeys() as $extensionKey) {
163 $sql .= $this->getDatabaseTableDefinition($extensionKey);
164 }
165 return $sql;
166 }
167
168 /**
169 * Generates table definitions for registered tables by an extension.
170 *
171 * @param string $extensionKey Extension key to have the database definitions created for
172 * @return string
173 */
174 public function getDatabaseTableDefinition($extensionKey) {
175 if (!isset($this->registry[$extensionKey]) || !is_array($this->registry[$extensionKey])) {
176 return '';
177 }
178 $sql = '';
179
180 foreach ($this->registry[$extensionKey] as $tableName => $fields) {
181 foreach (array_keys($fields) as $fieldName) {
182 $sql .= sprintf($this->template, $tableName, $fieldName);
183 }
184 }
185 return $sql;
186 }
187
188 /**
189 * Apply TCA to all registered tables
190 *
191 * @return void
192 */
193 public function applyTca() {
194
195 $this->registerDefaultCategorizedTables();
196
197 foreach ($this->registry as $registry) {
198 foreach ($registry as $tableName => $fields) {
199 foreach ($fields as $fieldName => $options) {
200 $this->addTcaColumn($tableName, $fieldName, $options);
201 $this->addToAllTCAtypes($tableName, $fieldName, $options);
202 }
203 }
204 }
205 }
206
207 /**
208 * Add default categorized tables to the registry
209 *
210 * @return void
211 */
212 protected function registerDefaultCategorizedTables() {
213 $defaultCategorizedTables = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(
214 ',',
215 $GLOBALS['TYPO3_CONF_VARS']['SYS']['defaultCategorizedTables'],
216 TRUE
217 );
218 foreach ($defaultCategorizedTables as $defaultCategorizedTable) {
219 if (!$this->isRegistered($defaultCategorizedTable)) {
220 $this->add('core', $defaultCategorizedTable, 'categories');
221 }
222 }
223 }
224
225 /**
226 * Add a new field into the TCA types -> showitem
227 *
228 * @param string $tableName Name of the table to be categorized
229 * @param string $fieldName Name of the field to be used to store categories
230 * @param array $options Additional configuration options
231 * + fieldList: field configuration to be added to showitems
232 * + typesList: list of types that shall visualize the categories field
233 * + position: insert position of the categories field
234 * @return void
235 */
236 protected function addToAllTCAtypes($tableName, $fieldName, $options) {
237
238 // Makes sure to add more TCA to an existing structure
239 if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
240
241 if (empty($options['fieldList'])) {
242 $fieldList = $this->addCategoryTab($tableName, $fieldName);
243 } else {
244 $fieldList = $options['fieldList'];
245 }
246
247 $typesList = '';
248 if (!empty($options['typesList'])) {
249 $typesList = $options['typesList'];
250 }
251
252 $position = '';
253 if (!empty($options['position'])) {
254 $position = $options['position'];
255 }
256
257 // Makes the new "categories" field to be visible in TSFE.
258 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes($tableName, $fieldList, $typesList, $position);
259
260 }
261 }
262
263 /**
264 * Creates the 'fieldList' string for $fieldName which includes a categories tab.
265 * But only one categories tab is added per table.
266 *
267 * @param string $tableName
268 * @param string $fieldName
269 * @return string
270 */
271 protected function addCategoryTab($tableName, $fieldName) {
272 $fieldList = '';
273 if (!in_array($tableName, $this->addedCategoryTabs)) {
274 $fieldList .= '--div--;LLL:EXT:lang/locallang_tca.xlf:sys_category.tabs.category, ';
275 $this->addedCategoryTabs[] = $tableName;
276 }
277 $fieldList .= $fieldName;
278 return $fieldList;
279 }
280
281 /**
282 * Add a new TCA Column
283 *
284 * @param string $tableName Name of the table to be categorized
285 * @param string $fieldName Name of the field to be used to store categories
286 * @param array $options Additional configuration options
287 * + fieldConfiguration: TCA field config array to override defaults
288 * + label: backend label of the categories field
289 * @return void
290 */
291 protected function addTcaColumn($tableName, $fieldName, $options) {
292
293 // Makes sure to add more TCA to an existing structure
294 if (isset($GLOBALS['TCA'][$tableName]['columns'])) {
295
296 // Forges a new field, default name is "categories"
297 $fieldConfiguration = array(
298 'type' => 'select',
299 'foreign_table' => 'sys_category',
300 'foreign_table_where' => ' AND sys_category.sys_language_uid IN (-1, 0) ORDER BY sys_category.title ASC',
301 'MM' => 'sys_category_record_mm',
302 'MM_opposite_field' => 'items',
303 'MM_match_fields' => array(
304 'tablenames' => $tableName,
305 'fieldname' => $fieldName,
306 ),
307 'size' => 10,
308 'autoSizeMax' => 50,
309 'maxitems' => 9999,
310 'renderMode' => 'tree',
311 'treeConfig' => array(
312 'parentField' => 'parent',
313 'appearance' => array(
314 'expandAll' => TRUE,
315 'showHeader' => TRUE,
316 ),
317 ),
318 'wizards' => array(
319 '_PADDING' => 1,
320 '_VERTICAL' => 1,
321 'edit' => array(
322 'type' => 'popup',
323 'title' => 'Edit',
324 'script' => 'wizard_edit.php',
325 'icon' => 'edit2.gif',
326 'popup_onlyOpenIfSelected' => 1,
327 'JSopenParams' => 'height=350,width=580,status=0,menubar=0,scrollbars=1',
328 ),
329 'add' => Array(
330 'type' => 'script',
331 'title' => 'Create new',
332 'icon' => 'add.gif',
333 'params' => array(
334 'table' => 'sys_category',
335 'pid' => '###CURRENT_PID###',
336 'setValue' => 'prepend'
337 ),
338 'script' => 'wizard_add.php',
339 ),
340 ),
341 );
342
343 if (!empty($options['fieldConfiguration'])) {
344 $fieldConfiguration = \TYPO3\CMS\Core\Utility\GeneralUtility::array_merge_recursive_overrule(
345 $fieldConfiguration,
346 $options['fieldConfiguration']
347 );
348 }
349
350 $label = 'LLL:EXT:lang/locallang_tca.xlf:sys_category.categories';
351 if (!empty($options['label'])) {
352 $label = $options['label'];
353 }
354
355 $columns = array(
356 $fieldName => array(
357 'exclude' => 0,
358 'label' => $label,
359 'config' => $fieldConfiguration,
360 ),
361 );
362
363 // Adding fields to an existing table definition
364 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTCAcolumns($tableName, $columns);
365 }
366 }
367 }
368
369 ?>