[BUGFIX] Fix negative pid when doing a positioned insert
[Packages/TYPO3.CMS.git] / typo3 / sysext / backend / Classes / Controller / LinkBrowserController.php
1 <?php
2 namespace TYPO3\CMS\Backend\Controller;
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 Psr\Http\Message\ResponseInterface;
18 use Psr\Http\Message\ServerRequestInterface;
19 use TYPO3\CMS\Backend\Utility\BackendUtility;
20 use TYPO3\CMS\Core\Page\PageRenderer;
21 use TYPO3\CMS\Core\Utility\GeneralUtility;
22 use TYPO3\CMS\Frontend\Service\TypoLinkCodecService;
23 use TYPO3\CMS\Recordlist\Controller\AbstractLinkBrowserController;
24
25 /**
26 * Extended controller for link browser
27 */
28 class LinkBrowserController extends AbstractLinkBrowserController
29 {
30 /**
31 * Initialize $this->currentLinkParts
32 *
33 * @return void
34 */
35 protected function initCurrentUrl()
36 {
37 $currentLink = isset($this->parameters['currentValue']) ? trim($this->parameters['currentValue']) : '';
38 $currentLinkParts = GeneralUtility::makeInstance(TypoLinkCodecService::class)->decode($currentLink);
39 $currentLinkParts['params'] = $currentLinkParts['additionalParams'];
40 unset($currentLinkParts['additionalParams']);
41
42 $this->currentLinkParts = $currentLinkParts;
43
44 parent::initCurrentUrl();
45 }
46
47 /**
48 * Initialize document template object
49 *
50 * @return void
51 */
52 protected function initDocumentTemplate()
53 {
54 parent::initDocumentTemplate();
55
56 if (!$this->areFieldChangeFunctionsValid() && !$this->areFieldChangeFunctionsValid(true)) {
57 $this->parameters['fieldChangeFunc'] = [];
58 }
59 unset($this->parameters['fieldChangeFunc']['alert']);
60 $update = [];
61 foreach ($this->parameters['fieldChangeFunc'] as $v) {
62 $update[] = 'parent.opener.' . $v;
63 }
64 $inlineJS = implode(LF, $update);
65
66 $pageRenderer = GeneralUtility::makeInstance(PageRenderer::class);
67 $pageRenderer->loadJquery();
68 $pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/FormEngineLinkBrowserAdapter', 'function(FormEngineLinkBrowserAdapter) {
69 FormEngineLinkBrowserAdapter.updateFunctions = function() {' . $inlineJS . '};
70 }');
71 }
72
73 /**
74 * Encode a typolink via ajax
75 *
76 * This avoids to implement the encoding functionality again in JS for the browser.
77 *
78 * @param ServerRequestInterface $request
79 * @param ResponseInterface $response
80 * @return ResponseInterface
81 */
82 public function encodeTypoLink(ServerRequestInterface $request, ResponseInterface $response)
83 {
84 $typoLinkParts = $request->getQueryParams();
85 if (isset($typoLinkParts['params'])) {
86 $typoLinkParts['additionalParams'] = $typoLinkParts['params'];
87 unset($typoLinkParts['params']);
88 }
89
90 $typoLink = GeneralUtility::makeInstance(TypoLinkCodecService::class)->encode($typoLinkParts);
91
92 $response->getBody()->write(json_encode(['typoLink' => $typoLink]));
93 return $response;
94 }
95
96 /**
97 * Determines whether submitted field change functions are valid
98 * and are coming from the system and not from an external abuse.
99 *
100 * @param bool $handleFlexformSections Whether to handle flexform sections differently
101 * @return bool Whether the submitted field change functions are valid
102 */
103 protected function areFieldChangeFunctionsValid($handleFlexformSections = false)
104 {
105 $result = false;
106 if (isset($this->parameters['fieldChangeFunc']) && is_array($this->parameters['fieldChangeFunc']) && isset($this->parameters['fieldChangeFuncHash'])) {
107 $matches = [];
108 $pattern = '#\\[el\\]\\[(([^]-]+-[^]-]+-)(idx\\d+-)([^]]+))\\]#i';
109 $fieldChangeFunctions = $this->parameters['fieldChangeFunc'];
110 // Special handling of flexform sections:
111 // Field change functions are modified in JavaScript, thus the hash is always invalid
112 if ($handleFlexformSections && preg_match($pattern, $this->parameters['itemName'], $matches)) {
113 $originalName = $matches[1];
114 $cleanedName = $matches[2] . $matches[4];
115 foreach ($fieldChangeFunctions as &$value) {
116 $value = str_replace($originalName, $cleanedName, $value);
117 }
118 unset($value);
119 }
120 $result = $this->parameters['fieldChangeFuncHash'] === GeneralUtility::hmac(serialize($fieldChangeFunctions));
121 }
122 return $result;
123 }
124
125 /**
126 * Get attributes for the body tag
127 *
128 * @return string[] Array of body-tag attributes
129 */
130 protected function getBodyTagAttributes()
131 {
132 $parameters = parent::getBodyTagAttributes();
133
134 $formEngineParameters['fieldChangeFunc'] = $this->parameters['fieldChangeFunc'];
135 $formEngineParameters['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($this->parameters['fieldChangeFunc']));
136
137 $parameters['data-add-on-params'] .= GeneralUtility::implodeArrayForUrl('P', $formEngineParameters);
138
139 return $parameters;
140 }
141
142 /**
143 * Return the ID of current page
144 *
145 * @return int
146 */
147 protected function getCurrentPageId()
148 {
149 $pageId = 0;
150 $browserParameters = $this->parameters;
151 if (isset($browserParameters['pid'])) {
152 $pageId = $browserParameters['pid'];
153 } elseif (isset($browserParameters['itemName'])) {
154 // parse data[<table>][<uid>]
155 if (preg_match('~data\[([^]]*)\]\[([^]]*)\]~', $browserParameters['itemName'], $matches)) {
156 $recordArray = BackendUtility::getRecord($matches['1'], $matches['2']);
157 if (is_array($recordArray)) {
158 $pageId = $recordArray['pid'];
159 }
160 }
161 }
162 return (int)BackendUtility::getTSCpidCached($browserParameters['table'], $browserParameters['uid'], $pageId)[0];
163 }
164 }