Passed
Push — main ( ae6137...e5543e )
by
unknown
03:02
created

HappyFeetLinkWizzard::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 6
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace AOE\HappyFeet\Typo3\Hook;
19
20
use Psr\Http\Message\ServerRequestInterface;
21
use TYPO3\CMS\Backend\Controller\AbstractLinkBrowserController;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Contro...ctLinkBrowserController was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
22
use TYPO3\CMS\Backend\LinkHandler\AbstractLinkHandler;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\LinkHandler\AbstractLinkHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use TYPO3\CMS\Backend\LinkHandler\LinkHandlerInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\LinkHandler\LinkHandlerInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use TYPO3\CMS\Backend\RecordList\ElementBrowserRecordList;
25
use TYPO3\CMS\Backend\Tree\View\LinkParameterProviderInterface;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\Tree\V...ameterProviderInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
use TYPO3\CMS\Backend\Utility\BackendUtility;
27
use TYPO3\CMS\Backend\View\RecordSearchBoxComponent;
0 ignored issues
show
Bug introduced by
The type TYPO3\CMS\Backend\View\RecordSearchBoxComponent was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
use TYPO3\CMS\Core\Imaging\Icon;
29
use TYPO3\CMS\Core\LinkHandling\LinkService;
30
use TYPO3\CMS\Core\Type\Bitmask\Permission;
31
use TYPO3\CMS\Core\Utility\GeneralUtility;
32
use TYPO3\CMS\Core\Utility\MathUtility;
33
34
final class HappyFeetLinkWizzard extends AbstractLinkHandler implements LinkHandlerInterface, LinkParameterProviderInterface
35
{
36
    /**
37
     * @var string
38
     */
39
    public $identifier;
40
41
    /**
42
     * Specific TSconfig for the current instance (corresponds to TCEMAIN.linkHandler.record.<identifier>.configuration)
43
     */
44
    private array $configuration = [];
45
46
    /**
47
     * Parts of the current link
48
     */
49
    private array $linkParts = [];
50
51
    private int $expandPage = 0;
52
53
    public function __construct(
54
        private readonly ElementBrowserRecordList $elementBrowserRecordList,
55
        private readonly RecordSearchBoxComponent $recordSearchBoxComponent,
56
        private readonly LinkService $linkService,
57
    ) {
58
        parent::__construct();
59
    }
60
61
    public function initialize(AbstractLinkBrowserController $linkBrowser, $identifier, array $configuration): void
62
    {
63
        parent::initialize($linkBrowser, $identifier, $configuration);
64
        $this->identifier = $identifier;
65
        if (empty($configuration['table'])) {
66
            throw new \LogicException(
67
                'Page TSconfig TCEMAIN.linkHandler.' . $identifier . '.configuration.table is mandatory and must be set to a table name.',
68
                1657960610
69
            );
70
        }
71
72
        $this->configuration = $configuration;
73
    }
74
75
    /**
76
     * Checks if this is the right handler for the given link.
77
     * Also stores information locally about currently linked record.
78
     *
79
     * @param array $linkParts Link parts as returned from TypoLinkCodecService
80
     */
81
    public function canHandleLink(array $linkParts): bool
82
    {
83
        if (isset($linkParts['type']) && ($linkParts['type'] == null || strcmp($linkParts['type'], 'happy_feet') !== 0)) {
84
            return false;
85
        }
86
87
        if (!$linkParts['url']) {
88
            return false;
89
        }
90
91
        $data = $linkParts['url'];
92
93
        // Get the related record
94
        $table = $this->configuration['table'];
95
        $record = BackendUtility::getRecord($table, $data['uid']);
96
        if ($record === null) {
97
            $linkParts['title'] = $this->getLanguageService()->sL(
98
                'LLL:EXT:backend/Resources/Private/Language/locallang_browse_links.xlf:recordNotFound'
99
            );
100
        } else {
101
            $linkParts['pid'] = (int) $record['pid'];
102
            $linkParts['title'] = empty($linkParts['title']) ? BackendUtility::getRecordTitle($table, $record) : $linkParts['title'];
103
        }
104
105
        $linkParts['tableName'] = $this->getLanguageService()->sL($GLOBALS['TCA'][$table]['ctrl']['title']);
106
        $linkParts['url']['type'] = $linkParts['type'];
107
        $this->linkParts = $linkParts;
108
109
        return true;
110
    }
111
112
    /**
113
     * Formats information for the current record for HTML output.
114
     */
115
    public function formatCurrentUrl(): string
116
    {
117
        return sprintf(
118
            '%s: %s [uid: %d]',
119
            $this->linkParts['tableName'],
120
            $this->linkParts['title'],
121
            $this->linkParts['url']['uid']
122
        );
123
    }
124
125
    /**
126
     * Renders the link handler.
127
     */
128
    public function render(ServerRequestInterface $request): string
129
    {
130
        $this->pageRenderer->loadJavaScriptModule('@typo3/backend/record-link-handler.js');
131
        $this->pageRenderer->loadJavaScriptModule('@typo3/backend/record-search.js');
132
        $this->pageRenderer->loadJavaScriptModule('@typo3/backend/viewport/resizable-navigation.js');
133
        $this->pageRenderer->loadJavaScriptModule('@typo3/backend/column-selector-button.js');
134
        $this->pageRenderer->loadJavaScriptModule('@typo3/backend/tree/page-browser.js');
135
        $this->getBackendUser()
136
            ->initializeWebmountsForElementBrowser();
137
138
        // Define the current page
139
        if (isset($request->getQueryParams()['expandPage'])) {
140
            $this->expandPage = (int) $request->getQueryParams()['expandPage'];
141
        } elseif (isset($this->configuration['storagePid'])) {
142
            $this->expandPage = (int) $this->configuration['storagePid'];
143
        } elseif (isset($this->linkParts['pid'])) {
144
            $this->expandPage = (int) $this->linkParts['pid'];
145
        }
146
147
        $pageTreeMountPoints = (string) ($this->configuration['pageTreeMountPoints'] ?? '');
148
        $this->view->assignMultiple([
149
            'treeEnabled' => (bool) ($this->configuration['hidePageTree'] ?? false) === false,
150
            'pageTreeMountPoints' => GeneralUtility::intExplode(',', $pageTreeMountPoints, true),
151
            'recordList' => $this->renderTableRecords($request),
152
            'initialNavigationWidth' => $this->getBackendUser()
153
                    ->uc['selector']['navigation']['width'] ?? 250,
154
            'treeActions' => ['link'],
155
        ]);
156
157
        return $this->view->render('LinkBrowser/Record');
158
    }
159
160
    /**
161
     * Returns attributes for the body tag.
162
     *
163
     * @return string[] Array of body-tag attributes
164
     */
165
    public function getBodyTagAttributes(): array
166
    {
167
        $attributes = [
168
            'data-linkbrowser-identifier' => 't3://happy_feet?uid=',
169
        ];
170
        if ($this->linkParts !== []) {
171
            $attributes['data-linkbrowser-current-link'] = $this->linkService->asString($this->linkParts['url']);
172
        }
173
174
        return $attributes;
175
    }
176
177
    /**
178
     * Returns all parameters needed to build a URL with all the necessary information.
179
     *
180
     * @param array $values Array of values to include into the parameters or which might influence the parameters
181
     * @return string[] Array of parameters which have to be added to URLs
182
     */
183
    public function getUrlParameters(array $values): array
184
    {
185
        $pid = isset($values['pid']) ? (int) $values['pid'] : $this->expandPage;
186
        $parameters = [
187
            'expandPage' => $pid,
188
        ];
189
190
        return array_merge(
191
            $this->linkBrowser->getUrlParameters($values),
192
            ['P' => $this->linkBrowser->getParameters()],
193
            $parameters
194
        );
195
    }
196
197
    /**
198
     * Checks if the submitted page matches the current page.
199
     *
200
     * @param array $values Values to be checked
201
     * @return bool Returns TRUE if the given values match the currently selected item
202
     */
203
    public function isCurrentlySelectedItem(array $values): bool
204
    {
205
        return $this->linkParts !== [] && (int) $this->linkParts['pid'] === (int) $values['pid'];
206
    }
207
208
    /**
209
     * Returns the URL of the current script
210
     */
211
    public function getScriptUrl(): string
212
    {
213
        return $this->linkBrowser->getScriptUrl();
214
    }
215
216
    /**
217
     * Render elements of configured table
218
     */
219
    private function renderTableRecords(ServerRequestInterface $request): string
220
    {
221
        $html = [];
222
        $backendUser = $this->getBackendUser();
223
        $selectedPage = $this->expandPage;
224
        if ($selectedPage < 0 || !$backendUser->isInWebMount($selectedPage)) {
225
            return '';
226
        }
227
228
        $table = $this->configuration['table'];
229
        $permsClause = $backendUser->getPagePermsClause(Permission::PAGE_SHOW);
230
        $pageInfo = BackendUtility::readPageAccess($selectedPage, $permsClause);
231
        $selectedTable = (string) ($request->getParsedBody()['table'] ?? $request->getQueryParams()['table'] ?? '');
232
        $searchWord = (string) ($request->getParsedBody()['searchTerm'] ?? $request->getQueryParams()['searchTerm'] ?? '');
233
        $pointer = (int) ($request->getParsedBody()['pointer'] ?? $request->getQueryParams()['pointer'] ?? 0);
234
235
        // If table is 'pages', add a pre-entry to make selected page selectable directly.
236
        $titleLen = (int) $backendUser->uc['titleLen'];
237
        $mainPageRecord = BackendUtility::getRecordWSOL('pages', $selectedPage);
238
        if (is_array($mainPageRecord)) {
239
            $pText = htmlspecialchars(GeneralUtility::fixed_lgd_cs($mainPageRecord['title'], $titleLen));
240
            $html[] = '<p>' . $this->iconFactory->getIconForRecord('pages', $mainPageRecord, Icon::SIZE_SMALL)->render() . '&nbsp;';
241
            if ($table === 'pages') {
242
                $html[] = '<span data-uid="' . htmlspecialchars(
243
                    (string) $mainPageRecord['uid']
244
                ) . '" data-table="pages" data-title="' . htmlspecialchars(
245
                    $mainPageRecord['title']
246
                ) . '">';
247
                $html[] = '<a href="#" data-close="0">' . $this->iconFactory->getIcon(
248
                    'actions-plus',
249
                    Icon::SIZE_SMALL
250
                )->render() . '</a>';
251
                $html[] = '<a href="#" data-close="1">' . $pText . '</a>';
252
                $html[] = '</span>';
253
            } else {
254
                $html[] = $pText;
255
            }
256
257
            $html[] = '</p>';
258
        }
259
260
        $dbList = $this->elementBrowserRecordList;
261
        $dbList->setRequest($request);
0 ignored issues
show
Bug introduced by
The method setRequest() does not exist on TYPO3\CMS\Backend\Record...lementBrowserRecordList. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

261
        $dbList->/** @scrutinizer ignore-call */ 
262
                 setRequest($request);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
262
        $dbList->setOverrideUrlParameters(
263
            array_merge($this->getUrlParameters([]), ['mode' => 'db', 'expandPage' => $selectedPage]),
264
            $request
0 ignored issues
show
Unused Code introduced by
The call to TYPO3\CMS\Recordlist\Rec...OverrideUrlParameters() has too many arguments starting with $request. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

264
        $dbList->/** @scrutinizer ignore-call */ 
265
                 setOverrideUrlParameters(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
265
        );
266
        $dbList->setIsEditable(false);
267
268
        $dbList->calcPerms = new Permission($backendUser->calcPerms($pageInfo));
269
        $dbList->noControlPanels = true;
270
        $dbList->clickMenuEnabled = false;
271
        $dbList->displayRecordDownload = false;
272
        $dbList->tableList = $table;
273
        $dbList->start($selectedPage, $selectedTable, MathUtility::forceIntegerInRange($pointer, 0, 100000), $searchWord);
274
275
        $html[] = $this->recordSearchBoxComponent
276
            ->setSearchWord($searchWord)
277
            ->render($request, $dbList->listURL('', '-1', 'pointer,searchTerm'));
278
        $html[] = $dbList->generateList();
279
280
        return implode("\n", $html);
281
    }
282
}
283