Completed
Pull Request — develop (#167)
by
unknown
05:23
created

PagesIndexer::fetchAccess()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 33
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 13.125

Importance

Changes 0
Metric Value
eloc 20
dl 0
loc 33
ccs 10
cts 20
cp 0.5
rs 8.6666
c 0
b 0
f 0
cc 7
nc 7
nop 2
crap 13.125
1
<?php
2
3
namespace Codappix\SearchCore\Domain\Index\TcaIndexer;
4
5
/*
6
 * Copyright (C) 2017  Daniel Siepmann <[email protected]>
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
 * 02110-1301, USA.
22
 */
23
24
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
25
use Codappix\SearchCore\Connection\ConnectionInterface;
26
use Codappix\SearchCore\Domain\Index\TcaIndexer;
27
use TYPO3\CMS\Core\Utility\GeneralUtility;
28
use TYPO3\CMS\Core\Utility\RootlineUtility;
29
use TYPO3\CMS\Extbase\Object\ObjectManager;
30
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
31
32
/**
33
 * Specific indexer for Pages, will basically add content of page.
34
 */
35
class PagesIndexer extends TcaIndexer
36
{
37
    /**
38
     * @var ObjectManagerInterface
39
     */
40
    protected $objectManager;
41
42
    /**
43
     * @var TcaTableServiceInterface
44
     */
45
    protected $contentTableService;
46
47
    /**
48
     * @var \TYPO3\CMS\Core\Resource\FileRepository
49
     * @inject
50
     */
51
    protected $fileRepository;
52
53 34
    public function __construct(
54
        TcaTableServiceInterface $tcaTableService,
55
        TcaTableServiceInterface $contentTableService,
56
        ConnectionInterface $connection,
57
        ConfigurationContainerInterface $configuration,
58
        ObjectManagerInterface $objectManager
59
    ) {
60 34
        parent::__construct($tcaTableService, $connection, $configuration);
61 34
        $this->contentTableService = $contentTableService;
62 34
        $this->objectManager = $objectManager;
63 34
    }
64
65 10
    protected function prepareRecord(array &$record)
66
    {
67 10
        parent::prepareRecord($record);
68
69
        // Override access from parent rootline
70 10
        $record['search_access'] = $this->fetchAccess($record['uid'], (array)$record['search_access']);
71
72 10
        $possibleTitleFields = ['nav_title', 'tx_tqseo_pagetitle_rel', 'title'];
73 10
        foreach ($possibleTitleFields as $searchTitleField) {
74 10
            if (isset($record[$searchTitleField]) && trim($record[$searchTitleField])) {
75 10
                $record['search_title'] = trim($record[$searchTitleField]);
76 10
                break;
77
            }
78
        }
79
80 10
        $record['media'] = $this->fetchMediaForPage($record['uid']);
81 10
        $content = $this->fetchContentForPage($record['uid']);
82 10
        if ($content !== []) {
83 10
            $record['content'] = $content['content'];
84 10
            $record['media'] = array_values(array_unique(array_merge($record['media'], $content['images'])));
85
        }
86 10
    }
87
88 10
    protected function fetchContentForPage(int $uid): array
89
    {
90 10
        if ($this->contentTableService instanceof TcaTableService) {
91 10
            $queryBuilder = $this->contentTableService->getQuery();
92 10
            $queryBuilder->andWhere(
93 10
                $queryBuilder->expr()->eq(
94 10
                    $this->contentTableService->getTableName() . '.pid',
95 10
                    $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
96
                )
97
            );
98 10
            $contentElements = $queryBuilder->execute()->fetchAll();
99
        } else {
100
            $contentElements = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
101
                $this->contentTableService->getFields(),
0 ignored issues
show
Bug introduced by
The method getFields() does not exist on Codappix\SearchCore\Doma...caTableServiceInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Codappix\SearchCore\Doma...caTableServiceInterface. ( Ignorable by Annotation )

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

101
                $this->contentTableService->/** @scrutinizer ignore-call */ 
102
                                            getFields(),
Loading history...
102
                $this->contentTableService->getTableClause(),
103
                $this->contentTableService->getWhereClause() .
0 ignored issues
show
Bug introduced by
The method getWhereClause() does not exist on Codappix\SearchCore\Doma...caTableServiceInterface. Since it exists in all sub-types, consider adding an abstract or default implementation to Codappix\SearchCore\Doma...caTableServiceInterface. ( Ignorable by Annotation )

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

103
                $this->contentTableService->/** @scrutinizer ignore-call */ 
104
                                            getWhereClause() .
Loading history...
104
                sprintf(' AND %s.pid = %u', $this->contentTableService->getTableName(), $uid)
105
            );
106
        }
107
108 10
        if ($contentElements === null) {
109
            $this->logger->debug('No content for page ' . $uid);
110
            return [];
111
        }
112
113 10
        $this->logger->debug('Fetched content for page ' . $uid);
114 10
        $images = [];
115 10
        $content = [];
116 10
        foreach ($contentElements as $contentElement) {
117 4
            $images = array_merge(
118 4
                $images,
119 4
                $this->getContentElementImages($contentElement['uid'])
120
            );
121 4
            $content[] = $this->getContentFromContentElement($contentElement);
122
        }
123
124
        return [
125
            // Remove Tags.
126
            // Interpret escaped new lines and special chars.
127
            // Trim, e.g. trailing or leading new lines.
128 10
            'content' => trim(stripcslashes(strip_tags(implode(' ', $content)))),
129 10
            'images' => $images,
130
        ];
131
    }
132
133 4
    protected function getContentElementImages(int $uidOfContentElement): array
134
    {
135 4
        return $this->fetchSysFileReferenceUids($uidOfContentElement, 'tt_content', 'image');
136
    }
137
138 10
    protected function fetchMediaForPage(int $uid): array
139
    {
140 10
        return $this->fetchSysFileReferenceUids($uid, 'pages', 'media');
141
    }
142
143 10
    protected function fetchAccess(int $uid, array $pageAccess): array
144
    {
145
        try {
146 10
            $rootline = $this->objectManager->get(RootlineUtility::class, $uid)->get();
0 ignored issues
show
Unused Code introduced by
The call to TYPO3\CMS\Extbase\Object...ManagerInterface::get() has too many arguments starting with $uid. ( Ignorable by Annotation )

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

146
            $rootline = $this->objectManager->/** @scrutinizer ignore-call */ get(RootlineUtility::class, $uid)->get();

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...
147
        } catch (\RuntimeException $e) {
148
            $this->logger->notice(
149
                sprintf('Could not fetch rootline for page %u, because: %s', $uid, $e->getMessage()),
150
                [$pageAccess, $e]
151
            );
152
            return $pageAccess;
153
        }
154
155 10
        $access = [$pageAccess];
156 10
        $extended = false;
157 10
        foreach ($rootline as $pageInRootLine) {
158 10
            if ($pageInRootLine['extendToSubpages'] && (!empty($pageInRootLine['fe_group']))) {
159
                $extended = true;
160
                $access[] = GeneralUtility::intExplode(
161
                    ',',
162
                    $pageInRootLine['fe_group'],
163 10
                    true
164
                );
165
            }
166
        }
167
168
        // Return combined rootline extended access and return unique id's
169 10
        $access = array_unique(array_merge(...$access));
170
171
        // Remove public value if fe_group is extended to this page
172 10
        if ($extended && ($key = array_search(0, $access, true)) !== false) {
173
            unset($access[$key]);
174
        }
175 10
        return array_values($access);
176
    }
177
178 10
    protected function fetchSysFileReferenceUids(int $uid, string $tablename, string $fieldname): array
179
    {
180 10
        $imageRelationUids = [];
181 10
        $imageRelations = $this->fileRepository->findByRelation($tablename, $fieldname, $uid);
182
183 10
        foreach ($imageRelations as $relation) {
184
            $imageRelationUids[] = $relation->getUid();
185
        }
186
187 10
        return $imageRelationUids;
188
    }
189
190 4
    protected function getContentFromContentElement(array $contentElement): string
191
    {
192 4
        $content = '';
193
194 4
        $fieldsWithContent = GeneralUtility::trimExplode(
195 4
            ',',
196 4
            $this->configuration->get('indexing.' . $this->identifier . '.contentFields'),
197 4
            true
198
        );
199 4
        foreach ($fieldsWithContent as $fieldWithContent) {
200 4
            if (isset($contentElement[$fieldWithContent]) && trim($contentElement[$fieldWithContent])) {
201 4
                $content .= trim($contentElement[$fieldWithContent]) . ' ';
202
            }
203
        }
204
205 4
        return trim($content);
206
    }
207
}
208