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