[!!!][FEATURE] Introduce PSR-7-based Routing for Backend AJAX Requests
[Packages/TYPO3.CMS.git] / typo3 / sysext / t3editor / Classes / CodeCompletion.php
1 <?php
2 namespace TYPO3\CMS\T3editor;
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 use Psr\Http\Message\ResponseInterface;
17 use Psr\Http\Message\ServerRequestInterface;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Code completion for t3editor
22 */
23 class CodeCompletion {
24
25 /**
26 * @var \TYPO3\CMS\Core\Http\AjaxRequestHandler
27 */
28 protected $ajaxObj;
29
30 /**
31 * Default constructor
32 */
33 public function __construct() {
34 $GLOBALS['LANG']->includeLLFile('EXT:t3editor/Resources/Private/Language/locallang.xlf');
35 }
36
37 /**
38 * General processor for AJAX requests.
39 * (called by typo3/ajax.php)
40 *
41 * @param ServerRequestInterface $request
42 * @param ResponseInterface $response
43 * @return ResponseInterface
44 */
45 public function processAjaxRequest(ServerRequestInterface $request, ResponseInterface $response) {
46 $pageId = (int)(isset($request->getParsedBody()['pageId']) ? $request->getParsedBody()['pageId'] : $request->getQueryParams()['pageId']);
47 return $this->loadTemplates($pageId);
48 }
49
50 /**
51 * Loads all templates up to a given page id (walking the rootline) and
52 * cleans parts that are not required for the t3editor codecompletion.
53 *
54 * @param int $pageId ID of the page
55 * @return ResponseInterface
56 */
57 protected function loadTemplates($pageId) {
58 /** @var \TYPO3\CMS\Core\Http\Response $response */
59 $response = GeneralUtility::makeInstance(\TYPO3\CMS\Core\Http\Response::class);
60
61 // Check whether access is granted (only admin have access to sys_template records):
62 if ($GLOBALS['BE_USER']->isAdmin()) {
63 // Check whether there is a pageId given:
64 if ($pageId) {
65 $response->getBody()->write(json_encode($this->getMergedTemplates($pageId)));
66 } else {
67 $response->getBody()->write($GLOBALS['LANG']->getLL('pageIDInteger'));
68 $response = $response->withStatus(500);
69 }
70 } else {
71 $response->getBody()->write($GLOBALS['LANG']->getLL('noPermission'));
72 $response = $response->withStatus(500);
73 }
74 return $response;
75 }
76
77 /**
78 * Gets merged templates by walking the rootline to a given page id.
79 *
80 * @todo oliver@typo3.org: Refactor this method and comment what's going on there
81 * @param int $pageId
82 * @param int $templateId
83 * @return array Setup part of merged template records
84 */
85 protected function getMergedTemplates($pageId, $templateId = 0) {
86 $result = array();
87 /** @var $tsParser \TYPO3\CMS\Core\TypoScript\ExtendedTemplateService */
88 $tsParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\TypoScript\ExtendedTemplateService::class);
89 $tsParser->tt_track = 0;
90 $tsParser->init();
91 // Gets the rootLine
92 $page = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Page\PageRepository::class);
93 $rootLine = $page->getRootLine($pageId);
94 // This generates the constants/config + hierarchy info for the template.
95 $tsParser->runThroughTemplates($rootLine);
96 // ts-setup & ts-constants of the currently edited template should not be included
97 // therefor we have to delete the last template from the stack
98 array_pop($tsParser->config);
99 array_pop($tsParser->constants);
100 $tsParser->linkObjects = TRUE;
101 $tsParser->ext_regLinenumbers = FALSE;
102 $tsParser->bType = $bType;
103 $tsParser->generateConfig();
104 $result = $this->treeWalkCleanup($tsParser->setup);
105 return $result;
106 }
107
108 /**
109 * Walks through a tree of TypoScript configuration an cleans it up.
110 *
111 * @TODO oliver@typo3.org: Define and comment why this is necessary and exactly happens below
112 * @param array $treeBranch TypoScript configuration or sub branch of it
113 * @return array Cleaned TypoScript branch
114 */
115 private function treeWalkCleanup(array $treeBranch) {
116 $cleanedTreeBranch = array();
117 foreach ($treeBranch as $key => $value) {
118 $dotCount = substr_count($key, '.');
119 //type definition or value-assignment
120 if ($dotCount == 0) {
121 if ($value != '') {
122 if (strlen($value) > 20) {
123 $value = substr($value, 0, 20);
124 }
125 if (!isset($cleanedTreeBranch[$key])) {
126 $cleanedTreeBranch[$key] = array();
127 }
128 $cleanedTreeBranch[$key]['v'] = $value;
129 }
130 } elseif ($dotCount == 1) {
131 // subtree (definition of properties)
132 $subBranch = $this->treeWalkCleanup($value);
133 if ($subBranch) {
134 $key = str_replace('.', '', $key);
135 if (!isset($cleanedTreeBranch[$key])) {
136 $cleanedTreeBranch[$key] = array();
137 }
138 $cleanedTreeBranch[$key]['c'] = $subBranch;
139 }
140 }
141 }
142 return $cleanedTreeBranch;
143 }
144
145 }