[TASK] Deprecate class ModuleSettings
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Module / ModuleSettings.php
1 <?php
2 namespace TYPO3\CMS\Backend;
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\Backend\Module\BaseScriptClass;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Manage storing and restoring of $this->getModule()->MOD_SETTINGS settings.
22 * Provides a presets box for BE modules.
23 *
24 * usage inside of BaseScriptClass class
25 *
26 * ....
27 *
28 * $this->MOD_MENU = array(
29 * 'function' => array('xxx'),
30 * 'tx_someext_storedSettings' => '',
31 *
32 * ....
33 *
34 * function main() {
35 * // reStore settings
36 * $store = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\ModuleSettings::class);
37 * $store->init('tx_someext');
38 * $store->setStoreList('tx_someext');
39 * $store->processStoreControl();
40 *
41 * // show control panel
42 * $this->content .= $this->doc->section('Settings', $store->getStoreControl(), 0, 1);
43 *
44 * Format of saved settings
45 *
46 * $this->getModule()->MOD_SETTINGS[$this->prefix . '_storedSettings'] = serialize(
47 * array (
48 * 'any id' => array(
49 * 'title' => 'title for saved settings',
50 * 'desc' => 'description text, not mandatory',
51 * 'data' => array(), // data from MOD_SETTINGS
52 * 'user' => NULL, // can be used for extra data used by the application to identify this entry
53 * 'tstamp' => 12345, // $GLOBALS['EXEC_TIME']
54 * ),
55 * 'another id' => ...
56 * )
57 *
58 * @deprecated since TYPO3 CMS 7, will be removed with TYPO3 CMS 8.
59 */
60 class ModuleSettings {
61
62 /**
63 * If type is set 'ses' then the module data will be stored into the session and will be lost with logout.
64 * Type 'perm' will store the data permanently.
65 *
66 * @var string
67 */
68 public $type = 'perm';
69
70 /**
71 * prefix of MOD_SETTING array keys that should be stored
72 *
73 * @var string
74 */
75 public $prefix = '';
76
77 /**
78 * Names of keys of the MOD_SETTING array which should be stored
79 *
80 * @var array
81 */
82 public $storeList = array();
83
84 /**
85 * The stored settings array
86 *
87 * @var array
88 */
89 public $storedSettings = array();
90
91 /**
92 * Message from the last storage command
93 *
94 * @var string
95 */
96 public $msg = '';
97
98 /**
99 * Name of the form. Needed for JS
100 *
101 * @var string
102 */
103 public $formName = 'storeControl';
104
105 /**
106 * Write messages into the devlog?
107 *
108 * @var bool
109 */
110 public $writeDevLog = FALSE;
111
112 /********************************
113 *
114 * Init / setup
115 *
116 ********************************/
117
118 /**
119 * Default constructor
120 */
121 public function __construct() {
122 GeneralUtility::deprecationLog('Class ModuleSettings is deprecated since TYPO3 CMS 7 and will be removed with TYPO3 CMS 8');
123 }
124
125 /**
126 * Initializes the object
127 *
128 * @param string $prefix Prefix of MOD_SETTING array keys that should be stored
129 * @param array|string $storeList Additional names of keys of the MOD_SETTING array which should be stored (array or comma list)
130 * @return void
131 */
132 public function init($prefix = '', $storeList = '') {
133 $this->prefix = $prefix;
134 $this->setStoreList($storeList);
135 $this->type = 'perm';
136 // Enable dev logging if set
137 if (!empty($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_modSettings.php']['writeDevLog'])) {
138 $this->writeDevLog = TRUE;
139 }
140 if (TYPO3_DLOG) {
141 $this->writeDevLog = TRUE;
142 }
143 }
144
145 /**
146 * Set session type to 'ses' which will store the settings data not permanently.
147 *
148 * @param string $type Default is 'ses'
149 * @return void
150 */
151 public function setSessionType($type = 'ses') {
152 $this->type = $type;
153 }
154
155 /********************************
156 *
157 * Store list - which values should be stored
158 *
159 ********************************/
160 /**
161 * Set MOD_SETTINGS keys which should be stored
162 *
163 * @param array|string $storeList Add names of keys of the MOD_SETTING array which should be stored
164 * @return void
165 */
166 public function setStoreList($storeList) {
167 $this->storeList = array();
168 $this->addToStoreList($storeList);
169 }
170
171 /**
172 * Add MOD_SETTINGS keys to the current list
173 *
174 * @param array|string $storeList Add names of keys of the MOD_SETTING array which should be stored
175 * @return void
176 */
177 public function addToStoreList($storeList) {
178 $storeList = is_array($storeList) ? $storeList : GeneralUtility::trimExplode(',', $storeList, TRUE);
179 $this->storeList = array_merge($this->storeList, $storeList);
180 if ($this->writeDevLog) {
181 GeneralUtility::devLog('Store list:' . implode(',', $this->storeList), __CLASS__, 0);
182 }
183 }
184
185 /**
186 * Add names of keys of the MOD_SETTING array by a prefix
187 *
188 * @param string $prefix Prefix of MOD_SETTING array keys that should be stored
189 * @return void
190 */
191 public function addToStoreListFromPrefix($prefix = '') {
192 $prefix = $prefix ?: $this->prefix;
193 $prefix = preg_quote($prefix, '/');
194 foreach ($this->getModule()->MOD_SETTINGS as $key => $value) {
195 if (preg_match('/^' . $prefix . '/', $key)) {
196 $this->storeList[$key] = $key;
197 }
198 }
199 unset($this->storeList[$this->prefix . '_storedSettings']);
200 if ($this->writeDevLog) {
201 GeneralUtility::devLog('Store list:' . implode(',', $this->storeList), __CLASS__, 0);
202 }
203 }
204
205 /********************************
206 *
207 * Process storage array
208 *
209 ********************************/
210 /**
211 * Get the stored settings from MOD_SETTINGS and set them in $this->storedSettings
212 *
213 * @return void
214 */
215 public function initStorage() {
216 $storedSettings = unserialize($this->getModule()->MOD_SETTINGS[$this->prefix . '_storedSettings']);
217 $this->storedSettings = $this->cleanupStorageArray($storedSettings);
218 }
219
220 /**
221 * Remove corrupted data entries from the stored settings array
222 *
223 * @param array $storedSettings The stored settings
224 * @return array Cleaned up stored settings
225 */
226 public function cleanupStorageArray($storedSettings) {
227 $storedSettings = is_array($storedSettings) ? $storedSettings : array();
228 // Clean up the array
229 foreach ($storedSettings as $id => $sdArr) {
230 if (!is_array($sdArr)) {
231 unset($storedSettings[$id]);
232 } elseif (!is_array($sdArr['data'])) {
233 unset($storedSettings[$id]);
234 } elseif (!trim($sdArr['title'])) {
235 $storedSettings[$id]['title'] = '[no title]';
236 }
237 }
238 return $storedSettings;
239 }
240
241 /**
242 * Creates an entry for the stored settings array
243 * Collects data from MOD_SETTINGS selected by the storeList
244 *
245 * @param array $data Should work with data from _GP('storeControl'). This is ['title']: Title for the entry. ['desc']: A description text. Currently not used by this class
246 * @return array Entry for the stored settings array
247 */
248 public function compileEntry($data) {
249 $storageData = array();
250 foreach ($this->storeList as $MS_key) {
251 $storageData[$MS_key] = $this->getModule()->MOD_SETTINGS[$MS_key];
252 }
253 $storageArr = array(
254 'title' => $data['title'],
255 'desc' => (string)$data['desc'],
256 'data' => $storageData,
257 'user' => NULL,
258 'tstamp' => $GLOBALS['EXEC_TIME']
259 );
260 $storageArr = $this->processEntry($storageArr);
261 return $storageArr;
262 }
263
264 /**
265 * Copies the stored data from entry $index to $writeArray which can be used to set MOD_SETTINGS
266 *
267 * @param mixed $storeIndex The entry key
268 * @param array $writeArray Preset data array. Will be overwritten by copied values.
269 * @return array Data array
270 */
271 public function getStoredData($storeIndex, $writeArray = array()) {
272 if ($this->storedSettings[$storeIndex]) {
273 foreach ($this->storeList as $k) {
274 $writeArray[$k] = $this->storedSettings[$storeIndex]['data'][$k];
275 }
276 }
277 return $writeArray;
278 }
279
280 /**
281 * Processing of the storage command LOAD, SAVE, REMOVE
282 *
283 * @param string $mconfName Name of the module to store the settings for. Default: $this->getModule()->MCONF['name'] (current module)
284 * @return string Storage message. Also set in $this->msg
285 */
286 public function processStoreControl($mconfName = '') {
287 $this->initStorage();
288 $storeControl = GeneralUtility::_GP('storeControl');
289 $storeIndex = $storeControl['STORE'];
290 $msg = '';
291 $saveSettings = FALSE;
292 $writeArray = array();
293 if (is_array($storeControl)) {
294 if ($this->writeDevLog) {
295 GeneralUtility::devLog('Store command: ' . GeneralUtility::arrayToLogString($storeControl), __CLASS__, 0);
296 }
297 // Processing LOAD
298 if ($storeControl['LOAD'] && $storeIndex) {
299 $writeArray = $this->getStoredData($storeIndex, $writeArray);
300 $saveSettings = TRUE;
301 $msg = '\'' . $this->storedSettings[$storeIndex]['title'] . '\' preset loaded!';
302 } elseif ($storeControl['SAVE']) {
303 if (trim($storeControl['title'])) {
304 // Get the data to store
305 $newEntry = $this->compileEntry($storeControl);
306 // Create an index for the storage array
307 if (!$storeIndex) {
308 $storeIndex = GeneralUtility::shortMD5($newEntry['title']);
309 }
310 // Add data to the storage array
311 $this->storedSettings[$storeIndex] = $newEntry;
312 $saveSettings = TRUE;
313 $msg = '\'' . $newEntry['title'] . '\' preset saved!';
314 } else {
315 $msg = 'Please enter a name for the preset!';
316 }
317 } elseif ($storeControl['REMOVE'] and $storeIndex) {
318 // Removing entry
319 $msg = '\'' . $this->storedSettings[$storeIndex]['title'] . '\' preset entry removed!';
320 unset($this->storedSettings[$storeIndex]);
321 $saveSettings = TRUE;
322 }
323 $this->msg = $msg;
324 if ($saveSettings) {
325 $this->writeStoredSetting($writeArray, $mconfName);
326 }
327 }
328 return $this->msg;
329 }
330
331 /**
332 * Write the current storage array and update MOD_SETTINGS
333 *
334 * @param array $writeArray Array of settings which should be overwrite current MOD_SETTINGS
335 * @param string $mconfName Name of the module to store the settings for. Default: $this->getModule()->MCONF['name'] (current module)
336 * @return void
337 */
338 public function writeStoredSetting($writeArray = array(), $mconfName = '') {
339 // Making sure, index 0 is not set
340 unset($this->storedSettings[0]);
341 $this->storedSettings = $this->cleanupStorageArray($this->storedSettings);
342 $writeArray[$this->prefix . '_storedSettings'] = serialize($this->storedSettings);
343 $this->getModule()->MOD_SETTINGS = Utility\BackendUtility::getModuleData(
344 $this->getModule()->MOD_MENU,
345 $writeArray,
346 $mconfName ?: $this->getModule()->MCONF['name'],
347 $this->type
348 );
349 if ($this->writeDevLog) {
350 GeneralUtility::devLog('Settings stored:' . $this->msg, __CLASS__, 0);
351 }
352 }
353
354 /********************************
355 *
356 * GUI
357 *
358 ********************************/
359 /**
360 * Returns the storage control box
361 *
362 * @param string $showElements List of elemetns which should be shown: load,remove,save
363 * @param bool $useOwnForm If set the box is wrapped with own form tag
364 * @return string HTML code
365 */
366 public function getStoreControl($showElements = 'load,remove,save', $useOwnForm = TRUE) {
367 $showElements = GeneralUtility::trimExplode(',', $showElements, TRUE);
368 $this->initStorage();
369 // Preset selector
370 $opt = array();
371 $opt[] = '<option value="0"> </option>';
372 foreach ($this->storedSettings as $id => $v) {
373 $opt[] = '<option value="' . $id . '">' . htmlspecialchars($v['title']) . '</option>';
374 }
375 $storedEntries = count($opt) > 1;
376 $codeTD = array();
377 $code = '';
378 // LOAD, REMOVE, but also show selector so you can overwrite an entry with SAVE
379 if ($storedEntries && !empty($showElements)) {
380 // Selector box
381 $onChange = 'document.forms[' . GeneralUtility::quoteJSvalue($this->formName) . '][\'storeControl[title]\'].value= this.options[this.selectedIndex].value!=0 ? this.options[this.selectedIndex].text : \'\';';
382 $code = '
383 <select name="storeControl[STORE]" onChange="' . htmlspecialchars($onChange) . '">
384 ' . implode('
385 ', $opt) . '
386 </select>';
387 // Load button
388 if (in_array('load', $showElements)) {
389 $code .= '
390 <input class="btn btn-default" type="submit" name="storeControl[LOAD]" value="Load" /> ';
391 }
392 // Remove button
393 if (in_array('remove', $showElements)) {
394 $code .= '
395 <input class="btn btn-default" type="submit" name="storeControl[REMOVE]" value="Remove" /> ';
396 }
397 $codeTD[] = '<td width="1%">Preset:</td>';
398 $codeTD[] = '<td nowrap="nowrap">' . $code . '&nbsp;&nbsp;</td>';
399 }
400 // SAVE
401 if (in_array('save', $showElements)) {
402 $onClick = !$storedEntries ? '' : 'if (document.forms[' . GeneralUtility::quoteJSvalue($this->formName) . '][\'storeControl[STORE]\'].options[document.forms[' . GeneralUtility::quoteJSvalue($this->formName) . '][\'storeControl[STORE]\'].selectedIndex].value<0) return confirm(\'Are you sure you want to overwrite the existing entry?\');';
403 $code = '<input name="storeControl[title]" value="" type="text" max="80" width="25"> ';
404 $code .= '<input class="btn btn-default" type="submit" name="storeControl[SAVE]" value="Save" onClick="' . htmlspecialchars($onClick) . '" />';
405 $codeTD[] = '<td nowrap="nowrap">' . $code . '</td>';
406 }
407 $codeTD = implode('
408 ', $codeTD);
409 if (trim($code)) {
410 $code = '
411 <!--
412 Store control
413 -->
414 <table border="0" cellpadding="3" cellspacing="0" width="100%">
415 <tr class="bgColor4">
416 ' . $codeTD . '
417 </tr>
418 </table>
419 ';
420 }
421 if ($this->msg) {
422 $code .= '
423 <div><strong>' . htmlspecialchars($this->msg) . '</strong></div>';
424 }
425 if ($useOwnForm && trim($code)) {
426 $code = '
427 <form action="' . GeneralUtility::getIndpEnv('SCRIPT_NAME') . '" method="post" name="' . $this->formName . '" enctype="multipart/form-data">' . $code . '</form>';
428 }
429 return $code;
430 }
431
432 /********************************
433 *
434 * Misc
435 *
436 ********************************/
437 /**
438 * Processing entry for the stored settings array
439 * Can be overwritten by extended class
440 *
441 * @param array $storageArr Entry for the stored settings array
442 * @return array Entry for the stored settings array
443 */
444 public function processEntry($storageArr) {
445 return $storageArr;
446 }
447
448 /**
449 * @return BaseScriptClass
450 */
451 protected function getModule() {
452 return $GLOBALS['SOBE'];
453 }
454 }