a440c8ebe8b7b3842f1d4f606bb49588c6db0c4d
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Configuration / BackendConfigurationManager.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Configuration;
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\Core\Database\ConnectionPool;
18 use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
19 use TYPO3\CMS\Core\Database\Query\Restriction\HiddenRestriction;
20 use TYPO3\CMS\Core\Database\QueryGenerator;
21 use TYPO3\CMS\Core\TypoScript\TemplateService;
22 use TYPO3\CMS\Core\Utility\ArrayUtility;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24 use TYPO3\CMS\Extbase\Mvc\Web\BackendRequestHandler;
25 use TYPO3\CMS\Extbase\Mvc\Web\FrontendRequestHandler;
26 use TYPO3\CMS\Frontend\Page\PageRepository;
27
28 /**
29 * A general purpose configuration manager used in backend mode.
30 */
31 class BackendConfigurationManager extends AbstractConfigurationManager
32 {
33 /**
34 * @var array
35 */
36 protected $typoScriptSetupCache = [];
37
38 /**
39 * stores the current page ID
40 * @var int
41 */
42 protected $currentPageId;
43
44 /**
45 * Returns TypoScript Setup array from current Environment.
46 *
47 * @return array the raw TypoScript setup
48 */
49 public function getTypoScriptSetup()
50 {
51 $pageId = $this->getCurrentPageId();
52
53 if (!array_key_exists($pageId, $this->typoScriptSetupCache)) {
54 /** @var $template TemplateService */
55 $template = GeneralUtility::makeInstance(TemplateService::class);
56 // do not log time-performance information
57 $template->tt_track = 0;
58 // Explicitly trigger processing of extension static files
59 $template->setProcessExtensionStatics(true);
60 $template->init();
61 // Get the root line
62 $rootline = [];
63 if ($pageId > 0) {
64 /** @var $sysPage PageRepository */
65 $sysPage = GeneralUtility::makeInstance(PageRepository::class);
66 // Get the rootline for the current page
67 $rootline = $sysPage->getRootLine($pageId, '', true);
68 }
69 // This generates the constants/config + hierarchy info for the template.
70 $template->runThroughTemplates($rootline, 0);
71 $template->generateConfig();
72 $this->typoScriptSetupCache[$pageId] = $template->setup;
73 }
74 return $this->typoScriptSetupCache[$pageId];
75 }
76
77 /**
78 * Returns the TypoScript configuration found in module.tx_yourextension_yourmodule
79 * merged with the global configuration of your extension from module.tx_yourextension
80 *
81 * @param string $extensionName
82 * @param string $pluginName in BE mode this is actually the module signature. But we're using it just like the plugin name in FE
83 * @return array
84 */
85 protected function getPluginConfiguration($extensionName, $pluginName = null)
86 {
87 $setup = $this->getTypoScriptSetup();
88 $pluginConfiguration = [];
89 if (is_array($setup['module.']['tx_' . strtolower($extensionName) . '.'] ?? false)) {
90 $pluginConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['module.']['tx_' . strtolower($extensionName) . '.']);
91 }
92 if ($pluginName !== null) {
93 $pluginSignature = strtolower($extensionName . '_' . $pluginName);
94 if (is_array($setup['module.']['tx_' . $pluginSignature . '.'] ?? false)) {
95 $overruleConfiguration = $this->typoScriptService->convertTypoScriptArrayToPlainArray($setup['module.']['tx_' . $pluginSignature . '.']);
96 ArrayUtility::mergeRecursiveWithOverrule($pluginConfiguration, $overruleConfiguration);
97 }
98 }
99 return $pluginConfiguration;
100 }
101
102 /**
103 * Returns the configured controller/action pairs of the specified module in the format
104 * array(
105 * 'Controller1' => array('action1', 'action2'),
106 * 'Controller2' => array('action3', 'action4')
107 * )
108 *
109 * @param string $extensionName
110 * @param string $pluginName in BE mode this is actually the module signature. But we're using it just like the plugin name in FE
111 * @return array
112 */
113 protected function getSwitchableControllerActions($extensionName, $pluginName)
114 {
115 $switchableControllerActions = $GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['extbase']['extensions'][$extensionName]['modules'][$pluginName]['controllers'] ?? false;
116 if (!is_array($switchableControllerActions)) {
117 $switchableControllerActions = [];
118 }
119 return $switchableControllerActions;
120 }
121
122 /**
123 * Returns the page uid of the current page.
124 * If no page is selected, we'll return the uid of the first root page.
125 *
126 * @return int current page id. If no page is selected current root page id is returned
127 */
128 protected function getCurrentPageId()
129 {
130 if ($this->currentPageId !== null) {
131 return $this->currentPageId;
132 }
133
134 $this->currentPageId = $this->getCurrentPageIdFromGetPostData() ?: $this->getCurrentPageIdFromCurrentSiteRoot();
135 $this->currentPageId = $this->currentPageId ?: $this->getCurrentPageIdFromRootTemplate();
136 $this->currentPageId = $this->currentPageId ?: self::DEFAULT_BACKEND_STORAGE_PID;
137
138 return $this->currentPageId;
139 }
140
141 /**
142 * Gets the current page ID from the GET/POST data.
143 *
144 * @return int the page UID, will be 0 if none has been set
145 */
146 protected function getCurrentPageIdFromGetPostData()
147 {
148 return (int)GeneralUtility::_GP('id');
149 }
150
151 /**
152 * Gets the current page ID from the first site root in tree.
153 *
154 * @return int the page UID, will be 0 if none has been set
155 */
156 protected function getCurrentPageIdFromCurrentSiteRoot()
157 {
158 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
159 ->getQueryBuilderForTable('pages');
160
161 $queryBuilder
162 ->getRestrictions()
163 ->removeAll()
164 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
165 ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
166
167 $rootPage = $queryBuilder
168 ->select('uid')
169 ->from('pages')
170 ->where(
171 $queryBuilder->expr()->eq('is_siteroot', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
172 )
173 ->orderBy('sorting')
174 ->execute()
175 ->fetch();
176
177 if (empty($rootPage)) {
178 return 0;
179 }
180
181 return (int)$rootPage['uid'];
182 }
183
184 /**
185 * Gets the current page ID from the first created root template.
186 *
187 * @return int the page UID, will be 0 if none has been set
188 */
189 protected function getCurrentPageIdFromRootTemplate()
190 {
191 $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
192 ->getQueryBuilderForTable('sys_template');
193
194 $queryBuilder
195 ->getRestrictions()
196 ->removeAll()
197 ->add(GeneralUtility::makeInstance(DeletedRestriction::class))
198 ->add(GeneralUtility::makeInstance(HiddenRestriction::class));
199
200 $rootTemplate = $queryBuilder
201 ->select('pid')
202 ->from('sys_template')
203 ->where(
204 $queryBuilder->expr()->eq('root', $queryBuilder->createNamedParameter(1, \PDO::PARAM_INT))
205 )
206 ->orderBy('crdate')
207 ->execute()
208 ->fetch();
209
210 if (empty($rootTemplate)) {
211 return 0;
212 }
213
214 return (int)$rootTemplate['pid'];
215 }
216
217 /**
218 * Returns the default backend storage pid
219 *
220 * @return string
221 */
222 public function getDefaultBackendStoragePid()
223 {
224 return $this->getCurrentPageId();
225 }
226
227 /**
228 * We need to set some default request handler if the framework configuration
229 * could not be loaded; to make sure Extbase also works in Backend modules
230 * in all contexts.
231 *
232 * @param array $frameworkConfiguration
233 * @return array
234 */
235 protected function getContextSpecificFrameworkConfiguration(array $frameworkConfiguration)
236 {
237 if (!isset($frameworkConfiguration['mvc']['requestHandlers'])) {
238 $frameworkConfiguration['mvc']['requestHandlers'] = [
239 FrontendRequestHandler::class => FrontendRequestHandler::class,
240 BackendRequestHandler::class => BackendRequestHandler::class
241 ];
242 }
243 return $frameworkConfiguration;
244 }
245
246 /**
247 * Returns a comma separated list of storagePid that are below a certain storage pid.
248 *
249 * @param string $storagePid Storage PID to start at; multiple PIDs possible as comma-separated list
250 * @param int $recursionDepth Maximum number of levels to search, 0 to disable recursive lookup
251 * @return string storage PIDs
252 */
253 protected function getRecursiveStoragePids($storagePid, $recursionDepth = 0)
254 {
255 if ($recursionDepth <= 0) {
256 return $storagePid;
257 }
258
259 $recursiveStoragePids = '';
260 $storagePids = GeneralUtility::intExplode(',', $storagePid);
261 $permsClause = $this->getBackendUser()->getPagePermsClause(1);
262 $queryGenerator = GeneralUtility::makeInstance(QueryGenerator::class);
263 foreach ($storagePids as $startPid) {
264 $pids = $queryGenerator->getTreeList($startPid, $recursionDepth, 0, $permsClause);
265 if ((string)$pids !== '') {
266 $recursiveStoragePids .= $pids . ',';
267 }
268 }
269
270 return rtrim($recursiveStoragePids, ',');
271 }
272
273 /**
274 * @return \TYPO3\CMS\Core\Authentication\BackendUserAuthentication
275 */
276 protected function getBackendUser()
277 {
278 return $GLOBALS['BE_USER'];
279 }
280 }