Merged new PageTree (version for TYPO3 4.5 Beta 3)
[Packages/TYPO3.CMS.git] / typo3 / sysext / pagetree / classes / contextmenu / class.tx_pagetree_contextmenu_dataprovider.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010 TYPO3 Tree Team <http://forge.typo3.org/projects/typo3v4-extjstrees>
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 // @TODO the most functionality should be moved to the parent data provider class
29
30 /**
31 * Context Menu Data Provider for the Page Tree
32 *
33 * @author Stefan Galinski <stefan.galinski@gmail.com>
34 * @package TYPO3
35 * @subpackage t3lib
36 */
37 class tx_pagetree_ContextMenu_DataProvider extends t3lib_contextmenu_AbstractDataProvider {
38 /**
39 * List of actions that are generally disabled
40 *
41 * @var array
42 */
43 protected $disableItems = array();
44
45 /**
46 * Old Context Menu Options (access mapping)
47 *
48 * Note: Only option with different namings are mapped!
49 *
50 * @var array
51 */
52 protected $legacyContextMenuMapping = array(
53 'hide' => 'disable',
54 'paste' => 'pasteInto,pasteAfter',
55 'mount_as_treeroot' => 'mountAsTreeroot',
56 );
57
58 /**
59 * Fetches the items that should be disabled from the context menu
60 *
61 * @return array
62 */
63 protected function getDisableActions() {
64 $tsConfig = $GLOBALS['BE_USER']->getTSConfig(
65 'options.contextMenu.' . $this->getContextMenuType() . '.disableItems'
66 );
67
68 $disableItems = array();
69 if (trim($tsConfig['value']) !== '') {
70 $disableItems = t3lib_div::trimExplode(',', $tsConfig['value']);
71 }
72
73 $tsConfig = $GLOBALS['BE_USER']->getTSConfig('options.contextMenu.pageTree.disableItems');
74 $oldDisableItems = array();
75 if (trim($tsConfig['value']) !== '') {
76 $oldDisableItems = t3lib_div::trimExplode(',', $tsConfig['value']);
77 }
78
79 $additionalItems = array();
80 foreach ($oldDisableItems as $item) {
81 if (!isset($this->legacyContextMenuMapping[$item])) {
82 $additionalItems[] = $item;
83 continue;
84 }
85
86 if (strpos($this->legacyContextMenuMapping[$item], ',')) {
87 $actions = t3lib_div::trimExplode(',', $this->legacyContextMenuMapping[$item]);
88 $additionalItems = array_merge($additionalItems, $actions);
89 } else {
90 $additionalItems[] = $item;
91 }
92 }
93
94 return array_merge($disableItems, $additionalItems);
95 }
96
97 /**
98 * Returns the actions for the node
99 *
100 * @param tx_pagetree_Node $node
101 * @return t3lib_contextmenu_ActionCollection
102 */
103 public function getActionsForNode(t3lib_tree_Node $node) {
104 $this->disableItems = $this->getDisableActions();
105 $configuration = $this->getConfiguration();
106 $contextMenuActions = array();
107 if (is_array($configuration)) {
108 $contextMenuActions = $this->getNextContextMenuLevel($configuration, $node);
109 }
110
111 return $contextMenuActions;
112 }
113
114 /**
115 * Evaluates a given display condition and returns true if the condition matches
116 *
117 * Examples:
118 * getContextInfo|inCutMode:1 || isInCopyMode:1
119 * isLeafNode:1
120 * isLeafNode:1 && isInCutMode:1
121 *
122 * @param tx_pagetree_Node $node
123 * @param string $displayCondition
124 * @return boolean
125 */
126 protected function evaluateDisplayCondition(tx_pagetree_Node $node, $displayCondition) {
127 if ($displayCondition === '') {
128 return TRUE;
129 }
130
131 // parse condition string
132 $conditions = array();
133 preg_match_all('/(.+?)(>=|<=|!=|=|>|<)(.+?)(\|\||&&|$)/is', $displayCondition, $conditions);
134
135 $lastResult = FALSE;
136 $chainType = '';
137 $amountOfConditions = count($conditions[0]);
138 for ($i = 0; $i < $amountOfConditions; ++$i) {
139 // check method for existence
140 $method = trim($conditions[1][$i]);
141 list($method, $index) = explode('|', $method);
142 if (!method_exists($node, $method)) {
143 continue;
144 }
145
146 // fetch compare value
147 $returnValue = call_user_func(array($node, $method));
148 if (is_array($returnValue)) {
149 $returnValue = $returnValue[$index];
150 }
151
152 // compare fetched and expected values
153 $operator = trim($conditions[2][$i]);
154 $expected = trim($conditions[3][$i]);
155 if ($operator === '=') {
156 $returnValue = ($returnValue == $expected);
157 } elseif ($operator === '>') {
158 $returnValue = ($returnValue > $expected);
159 } elseif ($operator === '<') {
160 $returnValue = ($returnValue < $expected);
161 } elseif ($operator === '>=') {
162 $returnValue = ($returnValue >= $expected);
163 } elseif ($operator === '<=') {
164 $returnValue = ($returnValue <= $expected);
165 } elseif ($operator === '!=') {
166 $returnValue = ($returnValue != $expected);
167 } else {
168 $returnValue = FALSE;
169 $lastResult = FALSE;
170 }
171
172 // chain last result and the current if requested
173 if ($chainType === '||') {
174 $lastResult = ($lastResult || $returnValue);
175 } elseif ($chainType === '&&') {
176 $lastResult = ($lastResult && $returnValue);
177 } else {
178 $lastResult = $returnValue;
179 }
180
181 // save chain type for the next condition
182 $chainType = trim($conditions[4][$i]);
183 }
184
185 return $lastResult;
186 }
187
188 /**
189 * Returns the next context menu level
190 *
191 * @param array $actions
192 * @param tx_pagetree_Node $node
193 * @param int $level
194 * @return t3lib_contextmenu_ActionCollection
195 */
196 protected function getNextContextMenuLevel(array $actions, tx_pagetree_Node $node, $level = 0) {
197 /** @var $actionCollection t3lib_contextmenu_ActionCollection */
198 $actionCollection = t3lib_div::makeInstance('t3lib_contextmenu_ActionCollection');
199
200 if ($level > 5) {
201 return $actionCollection;
202 }
203
204 $type = '';
205 foreach ($actions as $index => $actionConfiguration) {
206 if (substr($index, -1) !== '.') {
207 $type = $actionConfiguration;
208 if ($type !== 'DIVIDER') {
209 continue;
210 }
211 }
212
213 if (!in_array($type, array('DIVIDER', 'SUBMENU', 'ITEM'))) {
214 continue;
215 }
216
217 /** @var $action tx_pagetree_ContextMenu_Action */
218 $action = t3lib_div::makeInstance('tx_pagetree_ContextMenu_Action');
219 $action->setId($index);
220
221 if ($type === 'DIVIDER') {
222 $action->setType('divider');
223 } else {
224 if (in_array($actionConfiguration['name'], $this->disableItems)
225 || (isset($actionConfiguration['displayCondition'])
226 && trim($actionConfiguration['displayCondition']) !== ''
227 && !$this->evaluateDisplayCondition($node, $actionConfiguration['displayCondition'])
228 )
229 ) {
230 unset($action);
231 continue;
232 }
233
234 if ($type === 'SUBMENU') {
235 $label = $GLOBALS['LANG']->sL($actionConfiguration['label'], TRUE);
236 $action->setType('submenu');
237 $action->setChildActions(
238 $this->getNextContextMenuLevel($actionConfiguration, $node, ++$level)
239 );
240 } else {
241 $label = $GLOBALS['LANG']->sL($actionConfiguration['label'], TRUE);
242 $action->setType('action');
243 $action->setCallbackAction($actionConfiguration['callbackAction']);
244 }
245
246 $action->setLabel($label);
247 if (isset($actionConfiguration['icon']) && trim($actionConfiguration['icon']) !== '') {
248 $action->setIcon($actionConfiguration['icon']);
249 } elseif (isset($actionConfiguration['spriteIcon'])) {
250 $action->setClass(
251 t3lib_iconWorks::getSpriteIconClasses($actionConfiguration['spriteIcon'])
252 );
253 }
254 }
255
256 $actionCollection->offsetSet($level . intval($index), $action);
257 $actionCollection->ksort();
258 }
259
260 return $actionCollection;
261 }
262 }
263
264 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/sysext/pagetree/classes/class.tx_pagetree_contextmenu_dataprovider.php']) {
265 include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/sysext/pagetree/classes/class.tx_pagetree_contextmenu_dataprovider.php']);
266 }
267
268 ?>