* Installer: added new option BE/RTE_imageStorageDir. related to issue #7185
[Packages/TYPO3.CMS.git] / typo3 / sysext / install / modules / setup / class.tx_install_module_setup.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2006-2007 Thomas Hempel (thomas@work.de)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27
28 /**
29 *
30 * $Id$
31 *
32 * @author Thomas Hempel <thomas@work.de>
33 * @author Ingo Renner <ingo@typo3.org>
34 */
35 class tx_install_module_setup extends tx_install_module_base {
36
37 /**
38 * Main method of this module. This method is called by default at various places.
39 *
40 * @return plain HTML if AJAX request, otherwise array(content)
41 */
42 public function main() {
43 $returnValue = '';
44
45 // check if we should return AJAX content
46 if ($this->env['ajax'] == 1) {
47
48 $ajaxContent = '';
49 $titleSection = $this->get_LL('label_category_'.$this->env['categoryMain']);
50
51 // create a header box for main category if sub catagory is empty
52 if (empty($this->env['categorySub'])) {
53 $this->addAboutBox();
54
55 // get all deliverables for all modules in main category
56 $categoryDeliverables = $this->basicsObject->getCategoryModuleDeliverables($this->env['categoryMain']);
57 $subCategoryListElements = array();
58
59 // create a link to each subcategory (but not root)
60 foreach ($categoryDeliverables as $subCategory => $deliverables) {
61 if ($subCategory == 'root') continue;
62 $label = $this->get_LL('label_subcategory_'.$subCategory);
63 $subCategoryListElements[] = array (
64 'type' => 'plain',
65 'value' => '<a href="#" onclick="loadModuleContent(\''.$this->env['categoryMain'].'\', \''.$subCategory.'\'); return false;">'.$label.'</a>'
66 );
67 }
68
69 if (count($subCategoryListElements) > 0) {
70 // render a list with the links
71 $deliverableCode = $this->pObj->getViewObject()->render(array(
72 'type' => 'list',
73 'value' => $subCategoryListElements
74 ));
75
76 // add a new section to the output
77 $this->pObj->getViewObject()->addContent($this->get_LL('label_subsectionsfound'), $deliverableCode);
78 }
79
80 $categoryRootDeliverables = $this->basicsObject->getCategoryModuleDeliverables($this->env['categoryMain'], 'root');
81 if (is_array($categoryRootDeliverables)) {
82 $this->pObj->getViewObject()->addContent('', $this->renderCategoryDeliverables($categoryRootDeliverables));
83 }
84
85 $ajaxContent = $this->pObj->getViewObject()->getContent();
86
87 } else {
88 // sub category was selected...
89 $titleSection .= ' / '.$this->get_LL('label_subcategory_'.$this->env['categorySub']);
90 $moduleDeliverables = $this->pObj->getBasicsObject()->getCategoryModuleDeliverables($this->env['categoryMain'], $this->env['categorySub']);
91
92 $this->addAboutBox('categorySub');
93
94 if ($moduleDeliverables === false) {
95 // render errors if something went wrong before
96 $ajaxContent = $this->pObj->getViewObj()->renderErrors(true);
97 } else {
98 $filterResults = $this->pObj->getFilterResults();
99
100 // get content from deliverables
101 $ajaxContent = $this->renderCategoryDeliverables($moduleDeliverables);
102 }
103 }
104
105 // try to write the data to localconf
106 if (!$this->basicsObject->saveLocalconf()) {
107 $ajaxContent = $this->pObj->getViewObject()->renderErrors().$ajaxContent;
108 } else {
109 $modMessage = '';
110 if (count($modifiedFields) > 0) {
111 $modMessage = $this->pObj->getViewObject()->render(array('type' => 'list', 'value' => $modifiedFields));
112 }
113 $ajaxContent = $aboutBox.$this->pObj->getViewObject()->getLastMessage().$modMessage.$ajaxContent;
114 }
115
116 $returnValue = $this->pObj->getViewObject()->renderTag('h1', $titleSection).$ajaxContent;
117
118 } else {
119 // this is the default... In other words this is only executed on first call. All other requests are done via AJAX see above...
120
121 $catData = $this->basicsObject->getModuleCategoryData();
122 $tree = $this->renderCategoryTree($catData, $tree);
123
124 $installerWebPath = $this->basicsObject->getInstallerWebPath();
125
126 $this->pObj->getViewObject()->addJS(
127 'var minusSrc = "'.$installerWebPath.'imgs/icons/minus.gif";' .
128 'var plusSrc = "'.$installerWebPath.'imgs/icons/plus.gif";' .
129 'var expandSrc = "'.$installerWebPath.'imgs/icons/expandall.png";' .
130 'var collapseSrc = "'.$installerWebPath.'imgs/icons/collapseall.png";' .
131 'var labelExpand = "'.$this->get_LL('label_expandAll').'";' .
132 'var labelCollapse = "'.$this->get_LL('label_collapseAll').'";'
133 );
134
135 $returnValue = array('content' => $tree.'<div id="moduleContent"></div>');
136 }
137
138 return $returnValue;
139 }
140
141
142 /**
143 * Adds the about box on top of the page.
144 * The box is not displayed if no description was found.
145 *
146 * @param string $category: the category for which the about should be generated
147 */
148 private function addAboutBox($category = 'categoryMain') {
149 // create a about box
150 $categoryDescription = $this->get_LL('description_module_'.$this->env[$category]);
151
152 // if (!empty($categoryDescription)) {
153 $aboutBoxCode = array (
154 'type' => 'box',
155 'value' => array (
156 'class' => 'category_about',
157 'elements' => array (
158 array (
159 'type' => 'image',
160 'value' => array (
161 'path' => 'imgs/icons/'.$this->env[$category].'.png'
162 )
163 ),
164 array (
165 'type' => 'plain',
166 'value' => $categoryDescription
167 )
168 )
169 )
170 );
171
172 // add the about box
173 $this->pObj->getViewObject()->addContent('', $this->pObj->getViewObject()->render($aboutBoxCode));
174 // }
175 }
176
177
178 /**
179 * This one of the most important methods in setup. Here we render all pages and deliverables. It also
180 * looks for changes and pushes them to the localconf cache.
181 *
182 * @param array $deliverables: The deliverable configs
183 * @return HTML with the rendered deliverables
184 */
185 private function renderCategoryDeliverables($deliverables) {
186 $result = '';
187 $this->pObj->getViewObject()->clearLastMessage();
188
189 foreach ($deliverables as $deliverable => $names) {
190 if (!empty($this->env['categorySub'])) {
191 $result .= $this->pObj->getViewObject()->renderTag('h2', $this->get_LL('label_deliverable_'.$deliverable));
192 }
193
194 $modifiedFields = array();
195
196 if ($deliverable == 'options') {
197 $result .= '<form action="index.php" method="post" id="optionsForm">'.
198 '<input type="hidden" name="categoryMain" value="'.$this->env['categoryMain'].'" />'.
199 '<input type="hidden" name="categorySub" value="'.$this->env['categorySub'].'" />';
200 }
201
202 $odd = false;
203 foreach ($names as $name => $mod) {
204 $modConfig = $GLOBALS['MCA'][$mod][$deliverable][$name];
205
206 if (!isset($modConfig['title'])) {
207 $modConfig['title'] = 'title_'.$name;
208 }
209 if (!isset($modConfig['description'])) {
210 $modConfig['description'] = 'description_'.$name;
211 }
212 if (!isset($modConfig['help'])) {
213 $modConfig['help'] = 'help_'.$name;
214 }
215
216 $this->pObj->getBasicsObject()->loadModule($mod);
217
218 $helpData = $this->pObj->getViewObject()->renderHelp($this->get_LL($modConfig['help']), $name);
219 $descr = $this->pObj->getViewObject()->renderTag('div', $this->get_LL($modConfig['description']), array('class' => 'description'));
220 $deliverableContent = '';
221
222 switch ($deliverable) {
223 case 'checks':
224 // execute check and print out result in plain
225 $checkResult = $this->basicsObject->executeMethod($modConfig['method']);
226 $messageConfig = array(
227 'type' => 'message',
228 'value' => array (
229 'severity' => (($checkResult) ? 'ok' : 'error'),
230 'label' => (($checkResult) ? $this->pObj->getViewObject()->getLastMessage() : $this->get_LL('label_false'))
231 ));
232 if (!$checkResult) {
233 $messageConfig['value']['message'] = $this->pObj->getViewObject()->renderErrors();
234 } else {
235 $messageConfig['value']['message'] = $this->pObj->getViewObject()->clearLastMessage();
236 }
237 $deliverableContent = $this->pObj->getViewObject()->render($messageConfig);
238 $this->pObj->getViewObject()->clearLastMessage();
239 break;
240 case 'options':
241 // options are rendered as input elements
242
243 // save data
244 if ($this->env['saveData'] && isset($this->env[$mod.':'.$name])) {
245 // get data from environment
246
247 if ($modConfig['elementType'] == 'checkbox') {
248 $this->env[$mod.':'.$name] = intval($this->env[$mod.':'.$name]);
249 }
250
251 $saveData = $this->env[$mod.':'.$name];
252
253 // add only if data has really changed
254 $localConfValue = $this->basicsObject->getLocalconfValue($modConfig['value'], $modConfig['default']);
255 if ($saveData != $localConfValue) {
256 $this->basicsObject->addToLocalconf($modConfig['value'], $saveData, $modConfig['valueType']);
257
258 $modifiedFields[] = array (
259 'type' => 'message',
260 'value' => array (
261 'label' => sprintf($this->get_LL('label_value_modified'), $this->get_LL($modConfig['title']), $saveData)
262 )
263 );
264 }
265 }
266
267 $options = $modConfig;
268 $inputConfig = array (
269 'elementType' => $modConfig['elementType'],
270 'options' => array_merge($modConfig, array (
271 'name' => $mod.':'.$name,
272 'value' => $this->basicsObject->getLocalconfValue($modConfig['value'], $modConfig['default']),
273 'description' => $modConfig['description'],
274 'help' => $modConfig['help'],
275 'class' => 'bg'
276 ))
277 );
278
279 $descr .= $this->pObj->getViewObject()->renderTag('span', $this->get_LL('label_path').' '.$this->basicsObject->getLocalconfPath($modConfig['value']).' - '.$this->get_LL('label_default').' '.$modConfig['default'], array('class' => 'description italic'));
280 $deliverableContent = $this->pObj->getViewObject()->renderFormelement($inputConfig);
281
282 break;
283 case 'methods':
284 // the result of methods is simply printed out
285 $target = $name.'_result';
286 $hideButton = '<span style="display:none" id="hideBtn_'.$target.'">&nbsp;[<a href="#" onclick="hideElement(\''.$target.'\');">'.$this->get_LL('label_hide').'</a>]</span>';
287
288 if ($modConfig['autostart'] == true) {
289 $headerContent = $hideButton;
290 $deliverableContent = '<div id="'.$target.'">'.$this->basicsObject->executeMethod($modConfig['method']).'</div>';
291 } else {
292 list($module, $method) = t3lib_div::trimExplode(':', $modConfig['method']);
293 $headerContent = '&nbsp;[<a href="#" onclick="executeMethod(\''.$module.'\', \''.$method.'\', {target:\''.$target.'\'}, displayMethodResult)">'.$this->get_LL('label_execute').'</a>]'.$hideButton;
294 $deliverableContent = '<div id="'.$target.'">'.$deliverableContent.'</div>';
295 }
296 break;
297 }
298
299
300 if ($modConfig['elementType'] == 'checkbox') {
301 // draw checkboxes in front of the caption
302 $deliverableBox = $this->pObj->getViewObject()->renderTag('h3', $deliverableContent.$this->get_LL($modConfig['title'], $name).' '.(($helpData) ? $helpData['button'] : '')).(($helpData) ? $helpData['container'] : '').$descr;
303 } elseif ($deliverable == 'methods') {
304 // draw "execute" link after caption and target div under caption
305 $deliverableBox = $this->pObj->getViewObject()->renderTag('h3', $this->get_LL($modConfig['title'], $name).$headerContent.' '.(($helpData) ? $helpData['button'] : '')).(($helpData) ? $helpData['container'] : '').$descr.$deliverableContent;
306 } else {
307 // draw caption and content under it (default)
308 $deliverableBox = $this->pObj->getViewObject()->renderTag('h3', $this->get_LL($modConfig['title'], $name).' '.(($helpData) ? $helpData['button'] : '')).(($helpData) ? $helpData['container'] : '').$descr.$deliverableContent;
309 }
310
311 $paramData = array (
312 'id' => 'container_'.$name,
313 'class' => 'deliverable-box'.(($odd) ? ' odd' : '')
314 );
315
316 if ($filterResults[$name]) {
317 $paramData['style'] = 'background-color:#99ff99';
318 }
319
320 $result .= $this->pObj->getViewObject()->renderTag('div', $deliverableBox, $paramData);
321
322 $odd = !$odd;
323 }
324
325 // add form for saving options
326 if ($deliverable == 'options') {
327 $result .= '<input type="button" class="submit bg" onclick="sendForm(\'optionsForm\');" value="'.$this->get_LL('label_save').'" /></form>';
328 }
329 }
330
331 return $result;
332 }
333
334 /**
335 * Renders a collapsable tree from the collected category data.
336 *
337 * @param array $data: The collected category data (see: basicsObj->getModuleCategoryData())
338 * @return HTML of the tree as unordered list.
339 */
340 private function renderCategoryTree($data) {
341 // add the searchbox
342 $content = '<div class="categoryTreeContainer">
343 <div id="treeOptions">
344 <div id="treeFilterBox">
345 <input type="text" id="treeFilter" value="" />
346 </div>
347 </div>
348 <span id="filterStatus"></span>
349 <a href="#" onclick="toggleAllLeafs()" id="collapseExpandToggle">
350 '.$this->get_LL('label_expandAll').'
351 </a>
352 ';
353
354 $content .= '<ul class="categoryTree">';
355
356 // first level
357 foreach ($data as $level1Key => $level1Value) {
358 if (is_array($level1Value)) {
359 $onlyRootDeliverables = ((count($level1Value) == 1 && isset($level1Value['root'])));
360
361 if (!$onlyRootDeliverables) {
362 $content .= '<li id="item_'.$level1Key.'" class="tree_item">';
363 $content .= '<a href="#" onclick="toggleElement(\''.$level1Key.'\'); return false;"><img id="img_'.$level1Key.'" src="'.$this->pObj->getBasicsObject()->getInstallerWebPath().'imgs/icons/plus.gif" /></a>';
364 } else {
365 $content .= '<li id="item_'.$level1Key.'" class="tree_item_nosub">';
366 }
367 $content .= $this->renderTreeElement($level1Key, NULL, $onlyRootDeliverables);
368
369 if (is_array($level1Value) && !$onlyRootDeliverables) {
370 $content .= '<ul id="'.$level1Key.'" class="subLeaf" style="display:none">';
371 foreach ($level1Value as $level2Key => $level2Value) {
372 $content .= '<li id="item_'.$level2Key.'" class="tree_item">'.$this->renderTreeElement($level1Key, $level2Key).'</li>';
373 }
374 $content .= '</ul>';
375 }
376 $content .= '</li>';
377 }
378 }
379 $content .= '</ul></div>';
380
381 return $content;
382 }
383
384 private function renderTreeElement($level1Key, $level2Key = NULL, $onlyRootDeliverables = false) {
385 if(is_null($level2Key)) {
386 $label = $this->get_LL('label_category_'.$level1Key);
387 } else {
388 $label = $this->get_LL('label_subcategory_'.$level2Key);
389 }
390
391 $result = '<a href="#" onclick="';
392 if (!$onlyRootDeliverables) {
393 $result .= 'openLeaf(\''.$level1Key.'\');';
394 }
395 $result .= 'loadModuleContent(\''.$level1Key.'\', \''.$level2Key.'\'); return false;">'.$label.'</a>';
396 return $result;
397 }
398
399
400 /**
401 * Searches in all registered modules for a given string and returns a list of categories that contain
402 * the searchword.
403 *
404 * @param unknown_type $searchString
405 * @return unknown
406 */
407 public function searchCategories() {
408 $searchString = $this->env['searchString'];
409
410 $result = array(
411 'searchString' => $searchString,
412 'resultCount' => 0,
413 'resultMessage' => '',
414 'catMain' => array(),
415 'catSub' => array()
416 );
417 $filterResults = array();
418
419 if (strlen($searchString) >= 2) {
420
421 $this->basicsObject->getModuleCategoryData();
422 $localLang = $this->pObj->getLocalLang();
423 foreach ($localLang[$this->pObj->getLanguage()] as $index => $label) {
424 if (stripos($label, $searchString) !== false) {
425 $deliverableData = $this->pObj->getLabelIndexItem($index);
426 if (!empty($deliverableData)) {
427 $result['catMain'][$deliverableData['mainCat']] = true;
428 $result['catSub'][$deliverableData['subCat']][] = $deliverableData;
429 $result['resultCount']++;
430 $filterResults[$deliverableData['deliverable']] = true;
431 }
432 }
433 }
434
435 $result['resultMessage'] = sprintf($this->get_LL('msg_searchResultMessage'), $result['resultCount'], $searchString);
436 }
437
438 $this->pObj->setFilterResults($filterResults);
439 return json_encode($result);
440 }
441
442 }
443
444 ?>