* Added support for listing and calling methods in new installer
[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 $aboutBoxCode = array (
54 'type' => 'box',
55 'value' => array (
56 'class' => 'category_about',
57 'elements' => array (
58 array (
59 'type' => 'image',
60 'value' => array (
61 'path' => 'imgs/icons/'.$this->env['categoryMain'].'.png'
62 )
63 ),
64 array (
65 'type' => 'plain',
66 'value' => $this->get_LL('descr_'.$this->env['categoryMain'])
67 )
68 )
69 )
70 );
71
72 // add the about box
73 $this->pObj->getViewObject()->addContent('', $this->pObj->getViewObject()->render($aboutBoxCode));
74
75 // get all deliverables for all modules in main category
76 $categoryDeliverables = $this->basicsObject->getCategoryModuleDeliverables($this->env['categoryMain']);
77 $subCategoryListElements = array();
78
79 // create a link to each subcategory
80 foreach ($categoryDeliverables as $subCategory => $deliverables) {
81 $label = $this->get_LL('label_subcategory_'.$subCategory);
82 $subCategoryListElements[] = array (
83 'type' => 'plain',
84 'value' => '<a href="#" onclick="loadModuleContent(\''.$this->env['categoryMain'].'\', \''.$subCategory.'\'); return false;">'.$label.'</a>'
85 );
86 }
87
88 // render a list with the links
89 $deliverableCode = $this->pObj->getViewObject()->render(array(
90 'type' => 'list',
91 'value' => $subCategoryListElements
92 ));
93
94 // add a new section to the output
95 $this->pObj->getViewObject()->addContent($this->get_LL('label_subsectionsfound'), $deliverableCode);
96
97 $ajaxContent = $this->pObj->getViewObject()->getContent();
98 } else {
99 // sub category was selected...
100 $titleSection .= ' / '.$this->get_LL('label_subcategory_'.$this->env['categorySub']);
101 $moduleDeliverables = $this->pObj->getBasicsObject()->getCategoryModuleDeliverables($this->env['categoryMain'], $this->env['categorySub']);
102
103 // create a about box
104 $iconPath = 'imgs/icons/'.$this->env['categorySub'].'.png';
105 if (!file_exists($iconPath)) {
106 $iconPath = 'imgs/icons/'.$this->env['categoryMain'].'.png';
107 }
108
109 $aboutBoxCode = array (
110 'type' => 'box',
111 'value' => array (
112 'class' => 'category_about',
113 'elements' => array (
114 array (
115 'type' => 'image',
116 'value' => array (
117 'path' => $iconPath
118 )
119 ),
120 array (
121 'type' => 'plain',
122 'value' => $this->get_LL('descr_'.$this->env['categorySub'])
123 )
124 )
125 )
126 );
127
128 $aboutBox = $this->pObj->getViewObject()->render($aboutBoxCode);
129
130 if ($moduleDeliverables === false) {
131 // render errors if something went wrong before
132 $ajaxContent = $this->pObj->getViewObj()->renderErrors(true);
133 } else {
134 $filterResults = $this->pObj->getFilterResults();
135
136 // cycle through deliverables and execute or render them
137 foreach ($moduleDeliverables as $deliverable => $names) {
138 $ajaxContent .= $this->pObj->getViewObject()->renderTag('h2', $this->get_LL('label_deliverable_'.$deliverable));
139
140 // add form for saving options
141 if ($deliverable == 'options') {
142 $formWrap = array (
143 '<form action="index.php" method="post" id="optionsForm">'.
144 '<input type="hidden" name="categoryMain" value="'.$this->env['categoryMain'].'" />'.
145 '<input type="hidden" name="categorySub" value="'.$this->env['categorySub'].'" />',
146 '<input type="button" onclick="sendForm(\'optionsForm\');" value="'.$this->get_LL('label_save').'" /></form>'
147 );
148 } else {
149 $formWrap = array('', '');
150 }
151
152 $modifiedFields = array();
153
154 foreach ($names as $name => $mod) {
155 $modConfig = $GLOBALS['MCA'][$mod][$deliverable][$name];
156
157 if (!isset($modConfig['title'])) {
158 $modConfig['title'] = 'title_'.$name;
159 }
160 if (!isset($modConfig['description'])) {
161 $modConfig['description'] = 'description_'.$name;
162 }
163 if (!isset($modConfig['help'])) {
164 $modConfig['help'] = 'help_'.$name;
165 }
166
167 $this->pObj->getBasicsObject()->loadModule($mod);
168
169 $helpData = $this->pObj->getViewObject()->renderHelp($this->get_LL($modConfig['help']), $name);
170 $descr = $this->pObj->getViewObject()->renderTag('div', $this->get_LL($modConfig['description']));
171 $deliverableContent = '';
172
173 switch ($deliverable) {
174 case 'checks':
175 // execute check and print out result in plain
176 // $this->pObj->getViewObject()->clearLastMessage();
177 $checkResult = $this->basicsObject->executeMethod($modConfig['method']);
178 $deliverableContent = $this->get_LL('label_'.(($checkResult) ? 'true' : 'false'));
179 if (!$checkResult) {
180 $deliverableContent .= $this->pObj->getViewObject()->renderErrors();
181 } else {
182 $deliverableContent .= $this->pObj->getViewObject()->getLastMessage();
183 $this->pObj->getViewObject()->clearLastMessage();
184 }
185 break;
186 case 'options':
187 // options are rendered as input elements
188
189 // save data
190 if ($this->env['saveData'] && isset($this->env[$mod.':'.$name])) {
191 // get data from environment
192
193 if ($modConfig['elementType'] == 'checkbox') {
194 $this->env[$mod.':'.$name] = intval($this->env[$mod.':'.$name]);
195 }
196
197 $saveData = $this->env[$mod.':'.$name];
198
199 // add only if data has really changed
200 $localConfValue = $this->basicsObject->getLocalconfValue($modConfig['value'], $modConfig['default']);
201 if ($saveData != $localConfValue) {
202 $this->basicsObject->addToLocalconf($modConfig['value'], $saveData, $modConfig['valueType']);
203
204 $modifiedFields[] = array (
205 'type' => 'message',
206 'value' => array (
207 'label' => sprintf($this->get_LL('label_value_modified'), $this->get_LL($modConfig['title']), $saveData)
208 )
209 );
210 }
211 }
212
213 $options = $modConfig;
214 $inputConfig = array (
215 'elementType' => $modConfig['elementType'],
216 'options' => array_merge($modConfig, array (
217 'name' => $mod.':'.$name,
218 'value' => $this->basicsObject->getLocalconfValue($modConfig['value'], $modConfig['default']),
219 'description' => $modConfig['description'],
220 'help' => $modConfig['help']
221 ))
222 );
223
224 $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'));
225 $deliverableContent = $this->pObj->getViewObject()->renderFormelement($inputConfig);
226 break;
227 case 'methods':
228 // the result of methods is simply printed out
229 if ($modConfig['autostart'] == true) {
230 $deliverableContent = $this->basicsObject->executeMethod($modConfig['method']);
231 } else {
232 $target = $name.'_result';
233 list($module, $method) = t3lib_div::trimExplode(':', $modConfig['method']);
234 $deliverableContent = '<a href="#" onclick="executeMethod(\''.$module.'\', \''.$method.'\', {target:\''.$target.'\'}, displayMethodResult)">'.$this->get_LL('label_execute').'</a>
235 <div id="'.$target.'"></div>';
236 }
237 break;
238 }
239
240 if ($modConfig['elementType'] == 'checkbox') {
241 $deliverableBox = $this->pObj->getViewObject()->renderTag('h3', $deliverableContent.$this->get_LL($modConfig['title']).' '.(($helpData) ? $helpData['button'] : '')).(($helpData) ? $helpData['container'] : '').$descr;
242 } else {
243 $deliverableBox = $this->pObj->getViewObject()->renderTag('h3', $this->get_LL($modConfig['title']).' '.(($helpData) ? $helpData['button'] : '')).(($helpData) ? $helpData['container'] : '').$descr.$deliverableContent;
244 }
245
246 $paramData = array (
247 'id' => 'container_'.$name,
248 'class' => 'deliverable-box'
249 );
250 if ($filterResults[$name]) {
251 $paramData['style'] = 'background-color:#99ff99';
252 }
253
254 $ajaxContent .= $this->pObj->getViewObject()->renderTag('div', $deliverableBox, $paramData);
255 }
256 }
257
258 // try to write the data to localconf
259 if (!$this->basicsObject->saveLocalconf()) {
260 $ajaxContent = $this->pObj->getViewObject()->renderErrors().$ajaxContent;
261 } else {
262 $modMessage = '';
263 // var_dump($modifiedFields);
264 if (count($modifiedFields) > 0) {
265 $modMessage = $this->pObj->getViewObject()->render(array('type' => 'list', 'value' => $modifiedFields));
266 }
267 $ajaxContent = $aboutBox.$this->pObj->getViewObject()->getLastMessage().$modMessage.$ajaxContent;
268 }
269
270 }
271 }
272
273 $returnValue = $this->pObj->getViewObject()->renderTag('h1', $titleSection).$formWrap[0].$ajaxContent.$formWrap[1];
274
275 } else {
276 // this is the default... In other words this is only executed on first call. All other requests are done via AJAX see above...
277
278 $catData = $this->basicsObject->getModuleCategoryData();
279 $tree = $this->renderCategoryTree($catData, $tree);
280
281 $installerWebPath = $this->basicsObject->getInstallerWebPath();
282
283 $this->pObj->getViewObject()->addJS(
284 'var minusSrc = "'.$installerWebPath.'imgs/icons/minus.gif";' .
285 'var plusSrc = "'.$installerWebPath.'imgs/icons/plus.gif";' .
286 'var expandSrc = "'.$installerWebPath.'imgs/icons/expandall.png";' .
287 'var collapseSrc = "'.$installerWebPath.'imgs/icons/collapseall.png";' .
288 'var labelExpand = "'.$this->get_LL('label_expandAll').'";' .
289 'var labelCollapse = "'.$this->get_LL('label_collapseAll').'";'
290 );
291
292 $returnValue = array('content' => $tree.'<div id="moduleContent"></div>');
293 }
294
295 return $returnValue;
296 }
297
298
299 /**
300 * Renders a collapsable tree from the collected category data.
301 *
302 * @param array $data: The collected category data (see: basicsObj->getModuleCategoryData())
303 * @return HTML of the tree as unordered list.
304 */
305 private function renderCategoryTree($data) {
306 // add the searchbox
307 $content = '<div class="categoryTreeContainer">
308 <input type="text" id="treeFilter" value="" /><br />
309 <span id="filterStatus"></span>
310 <a href="#" onclick="toggleAllLeafs()" id="collapseExpandToggle">
311 '.$this->get_LL('label_expandAll').'
312 </a>
313 ';
314
315 $content .= '<ul class="categoryTree">';
316
317 // first level
318 foreach ($data as $level1Key => $level1Value) {
319 if (is_array($level1Value)) {
320 $content .= '<li id="item_'.$level1Key.'" class="tree_item"><a href="#" onclick="toggleElement(\''.$level1Key.'\'); return false;"><img id="img_'.$level1Key.'" src="'.$this->pObj->getBasicsObject()->getInstallerWebPath().'imgs/icons/plus.gif" /></a>'.$this->renderTreeElement($level1Key);
321 if (is_array($level1Value)) {
322 $content .= '<ul id="'.$level1Key.'" class="subLeaf" style="display:none">';
323 foreach ($level1Value as $level2Key => $level2Value) {
324 $content .= '<li id="item_'.$level2Key.'" class="tree_item">'.$this->renderTreeElement($level1Key, $level2Key).'</li>';
325 }
326 $content .= '</ul>';
327 }
328 $content .= '</li>';
329 }
330 }
331 $content .= '</ul></div>';
332
333 return $content;
334 }
335
336 private function renderTreeElement($level1Key, $level2Key = NULL) {
337 if(is_null($level2Key)) {
338 $label = $this->get_LL('label_category_'.$level1Key);
339 } else {
340 $label = $this->get_LL('label_subcategory_'.$level2Key);
341 }
342
343 return '<a href="#" onclick="openLeaf(\''.$level1Key.'\'); loadModuleContent(\''.$level1Key.'\', \''.$level2Key.'\'); return false;">'.$label.'</a>';
344 }
345
346
347 /**
348 * Searches in all registered modules for a given string and returns a list of categories that contain
349 * the searchword.
350 *
351 * @param unknown_type $searchString
352 * @return unknown
353 */
354 public function searchCategories() {
355 $searchString = $this->env['searchString'];
356
357 $result = array(
358 'searchString' => $searchString,
359 'resultCount' => 0,
360 'resultMessage' => '',
361 'catMain' => array(),
362 'catSub' => array()
363 );
364 $filterResults = array();
365
366 if (strlen($searchString) >= 2) {
367
368 $this->basicsObject->getModuleCategoryData();
369 $localLang = $this->pObj->getLocalLang();
370 foreach ($localLang[$this->pObj->getLanguage()] as $index => $label) {
371 if (stripos($label, $searchString) !== false) {
372 $deliverableData = $this->pObj->getLabelIndexItem($index);
373 if (!empty($deliverableData)) {
374 $result['catMain'][$deliverableData['mainCat']] = true;
375 $result['catSub'][$deliverableData['subCat']][] = $deliverableData;
376 $result['resultCount']++;
377 $filterResults[$deliverableData['deliverable']] = true;
378 }
379 }
380 }
381
382 $result['resultMessage'] = sprintf($this->get_LL('msg_searchResultMessage'), $result['resultCount'], $searchString);
383 }
384
385 $this->pObj->setFilterResults($filterResults);
386 return json_encode($result);
387 }
388
389 }
390
391 ?>