Passed
Pull Request — develop (#167)
by Daniel
05:07
created

PagesIndexer::fetchAccess()   B

Complexity

Conditions 7
Paths 8

Size

Total Lines 34
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 0
Metric Value
eloc 21
dl 0
loc 34
ccs 0
cts 21
cp 0
rs 8.6506
c 0
b 0
f 0
cc 7
nc 8
nop 2
crap 56
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 26
    public function __construct(
54
        TcaTableServiceInterface $tcaTableService,
55
        TcaTableServiceInterface $contentTableService,
56
        ConnectionInterface $connection,
57
        ConfigurationContainerInterface $configuration
58
    ) {
59 26
        parent::__construct($tcaTableService, $connection, $configuration);
60 26
        $this->contentTableService = $contentTableService;
61 26
    }
62
63
    protected function prepareRecord(array &$record)
64
    {
65
        parent::prepareRecord($record);
66
67
        // Override access from parent rootline
68
        $record['search_access'] = $this->fetchAccess($record['uid'], (array)$record['search_access']);
69
70
        $possibleTitleFields = ['nav_title', 'tx_tqseo_pagetitle_rel', 'title'];
71
        foreach ($possibleTitleFields as $searchTitleField) {
72
            if (isset($record[$searchTitleField]) && trim($record[$searchTitleField])) {
73
                $record['search_title'] = trim($record[$searchTitleField]);
74
                break;
75
            }
76
        }
77
78
        $record['media'] = $this->fetchMediaForPage($record['uid']);
79
        $content = $this->fetchContentForPage($record['uid']);
80
        if ($content !== []) {
81
            $record['content'] = $content['content'];
82
            $record['media'] = array_values(array_unique(array_merge($record['media'], $content['images'])));
83
        }
84
    }
85
86
    protected function fetchContentForPage(int $uid): array
87
    {
88
        if ($this->contentTableService instanceof TcaTableService) {
89
            $queryBuilder = $this->contentTableService->getQuery();
90
            $queryBuilder->andWhere(
91
                $queryBuilder->expr()->eq(
92
                    $this->contentTableService->getTableName() . '.pid',
93
                    $queryBuilder->createNamedParameter($uid, \PDO::PARAM_INT)
94
                )
95
            );
96
            $contentElements = $queryBuilder->execute()->fetchAll();
97
        } else {
98
            $contentElements = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows(
99
                $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

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

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