Passed
Pull Request — develop (#167)
by Daniel
04:48
created

PagesIndexer::fetchAccess()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 12.2913

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 34
ccs 11
cts 21
cp 0.5238
rs 8.6506
c 0
b 0
f 0
cc 7
nc 8
nop 2
crap 12.2913
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
31
/**
32
 * Specific indexer for Pages, will basically add content of page.
33
 */
34
class PagesIndexer extends TcaIndexer
35
{
36
    /**
37
     * @var TcaTableServiceInterface
38
     */
39
    protected $contentTableService;
40
41
    /**
42
     * @var \TYPO3\CMS\Core\Resource\FileRepository
43
     * @inject
44
     */
45
    protected $fileRepository;
46
47
    /**
48
     * @param TcaTableServiceInterface $tcaTableService
49
     * @param TcaTableServiceInterface $contentTableService
50
     * @param ConnectionInterface $connection
51
     * @param ConfigurationContainerInterface $configuration
52
     */
53 34
    public function __construct(
54
        TcaTableServiceInterface $tcaTableService,
55
        TcaTableServiceInterface $contentTableService,
56
        ConnectionInterface $connection,
57
        ConfigurationContainerInterface $configuration
58
    ) {
59 34
        parent::__construct($tcaTableService, $connection, $configuration);
60 34
        $this->contentTableService = $contentTableService;
61 34
    }
62
63
    /**
64
     * @param array $record
65
     */
66 10
    protected function prepareRecord(array &$record)
67
    {
68 10
        parent::prepareRecord($record);
69
70
        // Override access from parent rootline
71 10
        $record['search_access'] = $this->fetchAccess($record['uid'], (array)$record['search_access']);
72
73 10
        $possibleTitleFields = ['nav_title', 'tx_tqseo_pagetitle_rel', 'title'];
74 10
        foreach ($possibleTitleFields as $searchTitleField) {
75 10
            if (isset($record[$searchTitleField]) && trim($record[$searchTitleField])) {
76 10
                $record['search_title'] = trim($record[$searchTitleField]);
77 10
                break;
78
            }
79
        }
80
81 10
        $record['media'] = $this->fetchMediaForPage($record['uid']);
82 10
        $content = $this->fetchContentForPage($record['uid']);
83 10
        if ($content !== []) {
84 10
            $record['content'] = $content['content'];
85 10
            $record['media'] = array_values(array_unique(array_merge($record['media'], $content['images'])));
86
        }
87 10
    }
88
89
    /**
90
     * @param integer $uid
91
     * @return array
92
     */
93 10
    protected function fetchContentForPage(int $uid): array
94
    {
95 10
        if ($this->contentTableService instanceof TcaTableService) {
96 10
            $queryBuilder = $this->contentTableService->getQuery();
97 10
            $queryBuilder->andWhere(
98 10
                $queryBuilder->expr()->eq(
99 10
                    $this->contentTableService->getTableName() . '.pid',
100 10
                    $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
101
                )
102
            );
103 10
            $contentElements = $queryBuilder->execute()->fetchAll();
104
        } else {
105
            $contentElements = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
106
                $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

106
                $this->contentTableService->/** @scrutinizer ignore-call */ 
107
                                            getFields(),
Loading history...
107
                $this->contentTableService->getTableClause(),
108
                $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

108
                $this->contentTableService->/** @scrutinizer ignore-call */ 
109
                                            getWhereClause() .
Loading history...
109
                sprintf(' AND %s.pid = %u', $this->contentTableService->getTableName(), $uid)
110
            );
111
        }
112
113 10
        if ($contentElements === null) {
114
            $this->logger->debug('No content for page ' . $uid);
115
            return [];
116
        }
117
118 10
        $this->logger->debug('Fetched content for page ' . $uid);
119 10
        $images = [];
120 10
        $content = [];
121 10
        foreach ($contentElements as $contentElement) {
122 4
            $images = array_merge(
123 4
                $images,
124 4
                $this->getContentElementImages($contentElement['uid'])
125
            );
126 4
            $content[] = $this->getContentFromContentElement($contentElement);
127
        }
128
129
        return [
130
            // Remove Tags.
131
            // Interpret escaped new lines and special chars.
132
            // Trim, e.g. trailing or leading new lines.
133 10
            'content' => trim(stripcslashes(strip_tags(implode(' ', $content)))),
134 10
            'images' => $images,
135
        ];
136
    }
137
138
    /**
139
     * @param integer $uidOfContentElement
140
     * @return array
141
     */
142 4
    protected function getContentElementImages(int $uidOfContentElement): array
143
    {
144 4
        return $this->fetchSysFileReferenceUids($uidOfContentElement, 'tt_content', 'image');
145
    }
146
147
    /**
148
     * @param integer $uid
149
     * @return array
150
     */
151 10
    protected function fetchMediaForPage(int $uid): array
152
    {
153 10
        return $this->fetchSysFileReferenceUids($uid, 'pages', 'media');
154
    }
155
156
    /**
157
     * @param integer $uid
158
     * @param array $pageAccess
159
     * @return array
160
     */
161 10
    protected function fetchAccess(int $uid, array $pageAccess): array
162
    {
163
        try {
164 10
            $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
165 10
            $rootline = $objectManager->get(RootlineUtility::class, $uid)->get();
166
        } catch (\RuntimeException $e) {
167
            $this->logger->notice(
168
                sprintf('Could not fetch rootline for page %u, because: %s', $uid, $e->getMessage()),
169
                [$pageAccess, $e]
170
            );
171
            return $pageAccess;
172
        }
173
174 10
        $access = [$pageAccess];
175 10
        $extended = false;
176 10
        foreach ($rootline as $pageInRootLine) {
177 10
            if ($pageInRootLine['extendToSubpages'] && (!empty($pageInRootLine['fe_group']))) {
178
                $extended = true;
179
                $access[] = GeneralUtility::intExplode(
180
                    ',',
181
                    $pageInRootLine['fe_group'],
182 10
                    true
183
                );
184
            }
185
        }
186
187
        // Return combined rootline extended access and return unique id's
188 10
        $access = array_unique(array_merge(...$access));
189
190
        // Remove public value if fe_group is extended to this page
191 10
        if ($extended && ($key = array_search(0, $access, true)) !== false) {
192
            unset($access[$key]);
193
        }
194 10
        return array_values($access);
195
    }
196
197
    /**
198
     * @param integer $uid
199
     * @param string $tablename
200
     * @param string $fieldname
201
     * @return array
202
     */
203 10
    protected function fetchSysFileReferenceUids(int $uid, string $tablename, string $fieldname): array
204
    {
205 10
        $imageRelationUids = [];
206 10
        $imageRelations = $this->fileRepository->findByRelation($tablename, $fieldname, $uid);
207
208 10
        foreach ($imageRelations as $relation) {
209
            $imageRelationUids[] = $relation->getUid();
210
        }
211
212 10
        return $imageRelationUids;
213
    }
214
215
    /**
216
     * @param array $contentElement
217
     * @return string
218
     */
219 4
    protected function getContentFromContentElement(array $contentElement): string
220
    {
221 4
        $content = '';
222
223 4
        $fieldsWithContent = GeneralUtility::trimExplode(
224 4
            ',',
225 4
            $this->configuration->get('indexing.' . $this->identifier . '.contentFields'),
226 4
            true
227
        );
228 4
        foreach ($fieldsWithContent as $fieldWithContent) {
229 4
            if (isset($contentElement[$fieldWithContent]) && trim($contentElement[$fieldWithContent])) {
230 4
                $content .= trim($contentElement[$fieldWithContent]) . ' ';
231
            }
232
        }
233
234 4
        return trim($content);
235
    }
236
}
237