[BUGFIX] Ext Direct API lacks the possibility of adding access control
[Packages/TYPO3.CMS.git] / t3lib / extjs / class.t3lib_extjs_extdirectapi.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2010-2011 Sebastian Kurfürst <sebastian@typo3.org>
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 * Ext Direct API Generator
30 *
31 * @author Sebastian Kurfürst <sebastian@typo3.org>
32 * @author Stefan Galinski <stefan.galinski@gmail.com>
33 * @package TYPO3
34 */
35 class t3lib_extjs_ExtDirectApi {
36 /**
37 * @var array
38 */
39 protected $settings = array();
40
41 /**
42 * Constructs this object.
43 */
44 public function __construct() {
45 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']) && is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'])) {
46 $this->settings = $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect'];
47 }
48 }
49
50 /**
51 * Parses the ExtDirect configuration array "$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']"
52 * and feeds the given typo3ajax instance with the resulting information. The get parameter
53 * "namespace" will be used to filter the configuration.
54 *
55 * This method makes usage of the reflection mechanism to fetch the methods inside the
56 * defined classes together with their amount of parameters. This information are building
57 * the API and are required by ExtDirect. The result is cached to improve the overall
58 * performance.
59 *
60 * @param array $ajaxParams ajax parameters
61 * @param TYPO3AJAX $ajaxObj typo3ajax instance
62 * @return void
63 */
64 public function getAPI($ajaxParams, TYPO3AJAX $ajaxObj) {
65 $ajaxObj->setContent(array());
66 }
67
68 /**
69 * Get the API for a given nameapace
70 *
71 * @throws InvalidArgumentException
72 * @param array $filterNamespaces
73 * @return string
74 */
75 public function getApiPhp(array $filterNamespaces) {
76 $javascriptNamespaces = $this->getExtDirectApi($filterNamespaces);
77 // return the generated javascript API configuration
78 if (count($javascriptNamespaces)) {
79 return '
80 if (!Ext.isObject(Ext.app.ExtDirectAPI)) {
81 Ext.app.ExtDirectAPI = {};
82 }
83 Ext.apply(Ext.app.ExtDirectAPI, ' .
84 json_encode($javascriptNamespaces) . ');
85 ';
86 } else {
87 $errorMessage = $this->getNamespaceError($filterNamespaces);
88 throw new InvalidArgumentException(
89 $errorMessage,
90 1297645190
91 );
92 }
93 }
94
95
96 /**
97 * Generates the API that is configured inside the ExtDirect configuration
98 * array "$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['ExtDirect']".
99 *
100 * @param array $filerNamespace namespace that should be loaded like array('TYPO3.Backend')
101 * @return array javascript API configuration
102 */
103 protected function generateAPI(array $filterNamespaces) {
104 $javascriptNamespaces = array();
105 if (is_array($this->settings)) {
106 foreach ($this->settings as $javascriptName => $configuration) {
107 $splittedJavascriptName = explode('.', $javascriptName);
108 $javascriptObjectName = array_pop($splittedJavascriptName);
109 $javascriptNamespace = implode('.', $splittedJavascriptName);
110
111 // only items inside the wanted namespace
112 if (!$this->findNamespace($javascriptNamespace, $filterNamespaces)) {
113 continue;
114 }
115
116 if (!isset($javascriptNamespaces[$javascriptNamespace])) {
117 $javascriptNamespaces[$javascriptNamespace] = array(
118 'url' => $this->getRoutingUrl($javascriptNamespace),
119 'type' => 'remoting',
120 'actions' => array(),
121 'namespace' => $javascriptNamespace
122 );
123 }
124
125 if (is_array($configuration)) {
126 $className = $configuration['callbackClass'];
127 } else {
128 t3lib_div::deprecationLog('ExtDirect (Namespace: ' . $javascriptName .
129 '): Registration code changed. Use the API method t3lib_extMgm::registerExtDirectComponent(). ' .
130 'More Information: http://wiki.typo3.org/ExtDirect ' .
131 'Will be removed in 4.7.'
132 );
133 $className = $configuration;
134 }
135
136 $serverObject = t3lib_div::getUserObj($className, FALSE);
137 $javascriptNamespaces[$javascriptNamespace]['actions'][$javascriptObjectName] = array();
138 foreach (get_class_methods($serverObject) as $methodName) {
139 $reflectionMethod = new ReflectionMethod($serverObject, $methodName);
140 $numberOfParameters = $reflectionMethod->getNumberOfParameters();
141 $docHeader = $reflectionMethod->getDocComment();
142 $formHandler = (strpos($docHeader, '@formHandler') !== FALSE);
143
144 $javascriptNamespaces[$javascriptNamespace]['actions'][$javascriptObjectName][] = array(
145 'name' => $methodName,
146 'len' => $numberOfParameters,
147 'formHandler' => $formHandler
148 );
149 }
150 }
151 }
152
153 return $javascriptNamespaces;
154 }
155
156 /**
157 * Returns the convenient path for the routing Urls based on the TYPO3 mode.
158 *
159 * @param string $namespace
160 * @return string
161 */
162 public function getRoutingUrl($namespace) {
163 $url = '';
164 if (TYPO3_MODE === 'FE') {
165 $url = t3lib_div::locationHeaderUrl('?eID=ExtDirect&action=route&namespace=');
166 } else {
167 $url = t3lib_div::locationHeaderUrl(
168 t3lib_div::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir .
169 'ajax.php?ajaxID=ExtDirect::route&namespace='
170 );
171 }
172 $url .= rawurlencode($namespace);
173
174 return $url;
175 }
176
177 /**
178 * Generates the API or reads it from cache
179 *
180 * @param array $filterNamespaces
181 * @param bool $checkGetParam
182 * @return string $javascriptNamespaces
183 */
184 protected function getExtDirectApi(array $filterNamespaces) {
185 // Check GET-parameter no_cache and extCache setting
186 $noCache = isset($GLOBALS['TYPO3_CONF_VARS']['SYS']['extCache']) && (
187 $GLOBALS['TYPO3_CONF_VARS']['SYS']['extCache'] === 0 ||
188 $GLOBALS['TYPO3_CONF_VARS']['SYS']['extCache'] === '0'
189 );
190 $noCache = t3lib_div::_GET('no_cache') ? TRUE : $noCache;
191
192 // look up into the cache
193 $cacheIdentifier = 'ExtDirectApi';
194 $cacheHash = md5($cacheIdentifier . implode(',', $filterNamespaces) . t3lib_div::getIndpEnv('TYPO3_SSL') .
195 serialize($this->settings) . TYPO3_MODE . t3lib_div::getIndpEnv('HTTP_HOST'));
196
197 // with no_cache always generate the javascript content
198 $cacheContent = $noCache ? '' : t3lib_pageSelect::getHash($cacheHash);
199
200 // generate the javascript content if it wasn't found inside the cache and cache it!
201 if (!$cacheContent) {
202 $javascriptNamespaces = $this->generateAPI($filterNamespaces);
203 if (count($javascriptNamespaces)) {
204 t3lib_pageSelect::storeHash(
205 $cacheHash,
206 serialize($javascriptNamespaces),
207 $cacheIdentifier
208 );
209 }
210 } else {
211 $javascriptNamespaces = unserialize($cacheContent);
212 }
213
214 return $javascriptNamespaces;
215 }
216
217 /**
218 * Generates the error message
219 *
220 * @param array $filterNamespaces
221 * @return string $errorMessage
222 */
223 protected function getNamespaceError(array $filterNamespaces) {
224 if (count($filterNamespaces)) {
225 // namespace error
226 $errorMessage = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:ExtDirect.namespaceError'),
227 __CLASS__, implode(',', $filterNamespaces)
228 );
229 }
230 else {
231 // no namespace given
232 $errorMessage = sprintf($GLOBALS['LANG']->sL('LLL:EXT:lang/locallang_core.xml:ExtDirect.noNamespace'),
233 __CLASS__
234 );
235 }
236
237 return $errorMessage;
238 }
239
240 /**
241 * Looks if the given namespace is present in $filterNamespaces
242 *
243 * @param string $namespace
244 * @param array $filterNamespaces
245 * @return bool
246 */
247 protected function findNamespace($namespace, array $filterNamespaces) {
248 if ($filterNamespaces === array('TYPO3')) {
249 return TRUE;
250 }
251 $found = FALSE;
252 foreach ($filterNamespaces as $filter) {
253 if (t3lib_div::isFirstPartOfStr($filter, $namespace)) {
254 $found = TRUE;
255 break;
256 }
257 }
258 return $found;
259 }
260 }
261
262 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/extjs/class.t3lib_extjs_extdirectapi.php'])) {
263 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/extjs/class.t3lib_extjs_extdirectapi.php']);
264 }
265
266 ?>