[TASK] Introduced getter for $GLOBALS in backend/Classes/ContextMenu
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / ContextMenu / AbstractContextMenuDataProvider.php
1 <?php
2 namespace TYPO3\CMS\Backend\ContextMenu;
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\Utility\BackendUtility;
18
19 /**
20 * Abstract Context Menu Data Provider
21 *
22 * @author Stefan Galinski <stefan.galinski@gmail.com>
23 */
24 abstract class AbstractContextMenuDataProvider {
25
26 /**
27 * List of actions that are generally disabled
28 *
29 * @var array
30 */
31 protected $disableItems = array();
32
33 /**
34 * Context Menu Type (e.g. table.pages, table.tt_content)
35 *
36 * @var string
37 */
38 protected $contextMenuType = '';
39
40 /**
41 * Returns the context menu type
42 *
43 * @return string
44 */
45 public function getContextMenuType() {
46 return $this->contextMenuType;
47 }
48
49 /**
50 * Sets the context menu type
51 *
52 * @param string $contextMenuType
53 * @return void
54 */
55 public function setContextMenuType($contextMenuType) {
56 $this->contextMenuType = $contextMenuType;
57 }
58
59 /**
60 * Returns the actions of the node
61 *
62 * @param \TYPO3\CMS\Backend\Tree\TreeNode $node
63 * @return \TYPO3\CMS\Backend\ContextMenu\ContextMenuActionCollection
64 */
65 abstract public function getActionsForNode(\TYPO3\CMS\Backend\Tree\TreeNode $node);
66
67 /**
68 * Returns the configuration of the specified context menu type
69 *
70 * @return array
71 */
72 protected function getConfiguration() {
73 $contextMenuActions = $this->getBackendUser()->getTSConfig('options.contextMenu.' . $this->contextMenuType . '.items');
74 return $contextMenuActions['properties'];
75 }
76
77 /**
78 * Evaluates a given display condition and returns TRUE if the condition matches
79 *
80 * Examples:
81 * getContextInfo|inCutMode:1 || isInCopyMode:1
82 * isLeafNode:1
83 * isLeafNode:1 && isInCutMode:1
84 *
85 * @param \TYPO3\CMS\Backend\Tree\TreeNode $node
86 * @param string $displayCondition
87 * @return bool
88 */
89 protected function evaluateDisplayCondition(\TYPO3\CMS\Backend\Tree\TreeNode $node, $displayCondition) {
90 if ($displayCondition === '') {
91 return TRUE;
92 }
93 // Parse condition string
94 $conditions = array();
95 preg_match_all('/(.+?)(>=|<=|!=|=|>|<)(.+?)(\\|\\||&&|$)/is', $displayCondition, $conditions);
96 $lastResult = FALSE;
97 $chainType = '';
98 $amountOfConditions = count($conditions[0]);
99 for ($i = 0; $i < $amountOfConditions; ++$i) {
100 // Check method for existence
101 $method = trim($conditions[1][$i]);
102 list($method, $index) = explode('|', $method);
103 if (!method_exists($node, $method)) {
104 continue;
105 }
106 // Fetch compare value
107 $returnValue = call_user_func(array($node, $method));
108 if (is_array($returnValue)) {
109 $returnValue = $returnValue[$index];
110 }
111 // Compare fetched and expected values
112 $operator = trim($conditions[2][$i]);
113 $expected = trim($conditions[3][$i]);
114 if ($operator === '=') {
115 $returnValue = $returnValue == $expected;
116 } elseif ($operator === '>') {
117 $returnValue = $returnValue > $expected;
118 } elseif ($operator === '<') {
119 $returnValue = $returnValue < $expected;
120 } elseif ($operator === '>=') {
121 $returnValue = $returnValue >= $expected;
122 } elseif ($operator === '<=') {
123 $returnValue = $returnValue <= $expected;
124 } elseif ($operator === '!=') {
125 $returnValue = $returnValue != $expected;
126 } else {
127 $returnValue = FALSE;
128 $lastResult = FALSE;
129 }
130 // Chain last result and the current if requested
131 if ($chainType === '||') {
132 $lastResult = $lastResult || $returnValue;
133 } elseif ($chainType === '&&') {
134 $lastResult = $lastResult && $returnValue;
135 } else {
136 $lastResult = $returnValue;
137 }
138 // Save chain type for the next condition
139 $chainType = trim($conditions[4][$i]);
140 }
141 return $lastResult;
142 }
143
144 /**
145 * Returns the next context menu level
146 *
147 * @param array $actions
148 * @param \TYPO3\CMS\Backend\Tree\TreeNode $node
149 * @param int $level
150 * @return \TYPO3\CMS\Backend\ContextMenu\ContextMenuActionCollection
151 */
152 protected function getNextContextMenuLevel(array $actions, \TYPO3\CMS\Backend\Tree\TreeNode $node, $level = 0) {
153 /** @var $actionCollection \TYPO3\CMS\Backend\ContextMenu\ContextMenuActionCollection */
154 $actionCollection = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\ContextMenu\ContextMenuActionCollection::class);
155 if ($level > 5) {
156 return $actionCollection;
157 }
158 $type = '';
159 foreach ($actions as $index => $actionConfiguration) {
160 if (substr($index, -1) !== '.') {
161 $type = $actionConfiguration;
162 if ($type !== 'DIVIDER') {
163 continue;
164 }
165 }
166 if (!in_array($type, array('DIVIDER', 'SUBMENU', 'ITEM'))) {
167 continue;
168 }
169 /** @var $action \TYPO3\CMS\Backend\ContextMenu\ContextMenuAction */
170 $action = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Backend\ContextMenu\ContextMenuAction::class);
171 $action->setId($index);
172 if ($type === 'DIVIDER') {
173 $action->setType('divider');
174 } else {
175 if (in_array($actionConfiguration['name'], $this->disableItems) || isset($actionConfiguration['displayCondition']) && trim($actionConfiguration['displayCondition']) !== '' && !$this->evaluateDisplayCondition($node, $actionConfiguration['displayCondition'])) {
176 unset($action);
177 continue;
178 }
179 $label = $this->getLanguageService()->sL($actionConfiguration['label'], TRUE);
180 if ($type === 'SUBMENU') {
181 $action->setType('submenu');
182 $action->setChildActions($this->getNextContextMenuLevel($actionConfiguration, $node, $level + 1));
183 } else {
184 $action->setType('action');
185 $action->setCallbackAction($actionConfiguration['callbackAction']);
186 if (is_array($actionConfiguration['customAttributes.'])) {
187 if (!empty($actionConfiguration['customAttributes.']['contentUrl'])) {
188 $actionConfiguration['customAttributes.']['contentUrl'] = $this->replaceModuleTokenInContentUrl($actionConfiguration['customAttributes.']['contentUrl']);
189 }
190 $action->setCustomAttributes($actionConfiguration['customAttributes.']);
191 }
192 }
193 $action->setLabel($label);
194 if (isset($actionConfiguration['icon']) && trim($actionConfiguration['icon']) !== '') {
195 $action->setIcon($actionConfiguration['icon']);
196 } elseif (isset($actionConfiguration['spriteIcon'])) {
197 $action->setClass(\TYPO3\CMS\Backend\Utility\IconUtility::getSpriteIconClasses($actionConfiguration['spriteIcon']));
198 }
199 }
200 $actionCollection->offsetSet($level . (int)$index, $action);
201 $actionCollection->ksort();
202 }
203 return $actionCollection;
204 }
205
206 /**
207 * Add the CSRF token to the module URL if a "M" parameter is found
208 *
209 * @param string $contentUrl
210 * @return string
211 */
212 protected function replaceModuleTokenInContentUrl($contentUrl) {
213 $parsedUrl = parse_url($contentUrl);
214 parse_str($parsedUrl['query'], $urlParameters);
215 if (isset($urlParameters['M'])) {
216 $moduleName = $urlParameters['M'];
217 unset($urlParameters['M']);
218 $contentUrl = BackendUtility::getModuleUrl($moduleName, $urlParameters);
219 }
220 return $contentUrl;
221 }
222
223 /**
224 * Returns LanguageService
225 *
226 * @return \TYPO3\CMS\Lang\LanguageService
227 */
228 protected function getLanguageService() {
229 return $GLOBALS['LANG'];
230 }
231
232 /**
233 * Returns the current BE user.
234 *
235 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
236 */
237 protected function getBackendUser() {
238 return $GLOBALS['BE_USER'];
239 }
240
241 }