Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( ac3719...d0e528 )
by Sebastian
04:12 queued 11s
created

ReindexCommand::getSolrCores()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 15
c 1
b 0
f 1
dl 0
loc 24
rs 9.7666
cc 2
nc 2
nop 1
1
<?php
2
namespace Kitodo\Dlf\Command;
3
4
/**
5
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
6
 *
7
 * This file is part of the Kitodo and TYPO3 projects.
8
 *
9
 * @license GNU General Public License version 3 or later.
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 */
13
use Symfony\Component\Console\Command\Command;
14
use Symfony\Component\Console\Input\InputInterface;
15
use Symfony\Component\Console\Input\InputOption;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Console\Style\SymfonyStyle;
18
use TYPO3\CMS\Core\Core\Bootstrap;
19
use TYPO3\CMS\Core\Utility\GeneralUtility;
20
use TYPO3\CMS\Core\Utility\MathUtility;
21
use TYPO3\CMS\Core\Database\ConnectionPool;
22
use TYPO3\CMS\Core\Database\Connection;
23
use Kitodo\Dlf\Common\Document;
24
use Kitodo\Dlf\Common\Helper;
25
26
27
/**
28
 * Reindex a collection into database and solr.
29
 */
30
class ReindexCommand extends Command
31
{
32
    /**
33
     * Configure the command by defining the name, options and arguments
34
     */
35
    public function configure()
36
    {
37
        $this
38
            ->setDescription('Reindex a collection into database and solr.')
39
            ->setHelp('')
40
            ->addOption(
41
                'dry-run',
42
                null,
43
                InputOption::VALUE_NONE,
44
                'If this option is set, the files will not actually be processed but the location URI is shown.'
45
            )
46
            ->addOption(
47
                'coll',
48
                'c',
49
                InputOption::VALUE_REQUIRED,
50
                'UID of the collection.'
51
            )
52
            ->addOption(
53
                'pid',
54
                'p',
55
                InputOption::VALUE_REQUIRED,
56
                'UID of the page the document should be added to.'
57
            )
58
            ->addOption(
59
                'solr',
60
                's',
61
                InputOption::VALUE_REQUIRED,
62
                '[UID|index name] of the Solr core the document should be added to.'
63
            )
64
            ->addOption(
65
                'all',
66
                'a',
67
                InputOption::VALUE_NONE,
68
                'Reindex all documents on the given page.'
69
            );
70
    }
71
72
    /**
73
     * Executes the command to index the given document to db and solr.
74
     *
75
     * @param InputInterface $input
76
     * @param OutputInterface $output
77
     */
78
    protected function execute(InputInterface $input, OutputInterface $output)
79
    {
80
        // Make sure the _cli_ user is loaded
81
        Bootstrap::getInstance()->initializeBackendAuthentication();
82
83
        $dryRun = $input->getOption('dry-run') != false ? true : false;
84
85
        $io = new SymfonyStyle($input, $output);
86
        $io->title($this->getDescription());
87
88
        $startingPoint = 0;
89
        if (MathUtility::canBeInterpretedAsInteger($input->getOption('pid'))) {
90
            $startingPoint = MathUtility::forceIntegerInRange((int)$input->getOption('pid'), 0);
91
        }
92
        if ($startingPoint == 0) {
93
            $io->error('ERROR: No valid PID (' . $startingPoint . ') given.');
94
            exit(1);
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
95
        }
96
97
        if ($input->getOption('solr')) {
98
            $allSolrCores = $this->getSolrCores($startingPoint);
99
            if (MathUtility::canBeInterpretedAsInteger($input->getOption('solr'))) {
100
                $solrCoreUid = MathUtility::forceIntegerInRange((int)$input->getOption('solr'), 0);
101
            } else {
102
                $solrCoreName = $input->getOption('solr');
103
                $solrCoreUid = $allSolrCores[$solrCoreName];
104
            }
105
            // Abort if solrCoreUid is empty or not in the array of allowed solr cores.
106
            if (empty($solrCoreUid) || !in_array($solrCoreUid, $allSolrCores)) {
107
                foreach ($allSolrCores as $index_name => $uid) {
108
                    $output_solrCores .= ' ' . $uid . ' : ' . $index_name ."\n";
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $output_solrCores does not exist. Did you maybe mean $output?
Loading history...
109
                }
110
                if (empty($output_solrCores)) {
111
                    $io->error('ERROR: No valid solr core ("'. $input->getOption('solr') . '") given. ' . "No valid cores found on PID " . $startingPoint .".\n" . $output_solrCores);
112
                    exit(1);
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
113
                } else {
114
                    $io->error('ERROR: No valid solr core ("'. $input->getOption('solr') . '") given. ' . "Valid cores are (<uid>:<index_name>):\n" . $output_solrCores);
115
                    exit(1);
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
116
                }
117
            }
118
        } else {
119
            $io->error('ERROR: Required parameter --solr|-s is missing.');
120
            exit(1);
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
121
        }
122
123
        if ($input->getOption('all')) {
124
            // Get the document...
125
            $documents = $this->getAllDocuments($startingPoint);
126
        } else {
127
            // coll may be a single integer, a list of integer
128
            if (empty(array_filter(GeneralUtility::intExplode(',', $input->getOption('coll'), true)))) {
1 ignored issue
show
Bug introduced by
It seems like $input->getOption('coll') can also be of type string[]; however, parameter $string of TYPO3\CMS\Core\Utility\G...alUtility::intExplode() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

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

128
            if (empty(array_filter(GeneralUtility::intExplode(',', /** @scrutinizer ignore-type */ $input->getOption('coll'), true)))) {
Loading history...
129
                $io->error('ERROR: "' . $input->getOption('coll') . '" is not a valid list of collection UIDs for --coll|-c.');
130
                exit(1);
1 ignored issue
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
131
            }
132
            $documents = $this->getDocumentsToProceed($input->getOption('coll'), $startingPoint);
133
        }
134
135
        foreach ($documents as $id => $document) {
136
            $doc = Document::getInstance($document, $startingPoint, TRUE);
137
            if ($doc->ready) {
0 ignored issues
show
Bug Best Practice introduced by
The property $ready is declared protected in Kitodo\Dlf\Common\Document. Since you implement __get, consider adding a @property or @property-read.
Loading history...
138
                if ($dryRun) {
139
                    $io->writeln('DRY RUN: Would index ' . $id . '/' . count($documents) . ' ' . $doc->uid . ' ' . $doc->location . ' on UID ' . $startingPoint . ' and solr core ' . $solrCoreUid .'.');
0 ignored issues
show
Bug Best Practice introduced by
The property $uid is declared protected in Kitodo\Dlf\Common\Document. Since you implement __get, consider adding a @property or @property-read.
Loading history...
Bug Best Practice introduced by
The property $location is declared protected in Kitodo\Dlf\Common\Document. Since you implement __get, consider adding a @property or @property-read.
Loading history...
140
                } else {
141
                    if ($io->isVerbose()) {
142
                        $io->writeln(date('Y-m-d H:i:s') . ' ' . $id . '/' . count($documents) . ' ' . $doc->uid . ' ' . $doc->location . ' on UID ' . $startingPoint . ' and solr core ' . $solrCoreUid .'.');
143
                    }
144
                    // ...and save it to the database...
145
                    if (!$doc->save($startingPoint, $solrCoreUid)) {
146
                        $io->error('ERROR: Document "'.$id.'" not saved and indexed.');
147
                    }
148
                }
149
            } else {
150
                $io->error('ERROR: Document "'.$id.'" could not be loaded.');
151
            }
152
            // Clear document registry to prevent memory exhaustion.
153
            Document::clearRegistry();
154
        }
155
156
        $io->success('All done!');
157
    }
158
159
160
    /**
161
     * Fetches all records of tx_dlf_solrcores on given page.
162
     *
163
     * @param int $pageId the uid of the solr record (can also be 0)
164
     *
165
     * @return array array of valid solr cores
166
     */
167
    protected function getSolrCores(int $pageId): array
168
    {
169
        /** @var QueryBuilder $queryBuilder */
170
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
171
            ->getQueryBuilderForTable('tx_dlf_solrcores');
172
173
        $solrCores = [];
174
        $pageId = (int)$pageId;
175
        $result = $queryBuilder
176
            ->select('uid', 'index_name')
177
            ->from('tx_dlf_solrcores')
178
            ->where(
179
                $queryBuilder->expr()->eq(
180
                    'pid',
181
                    $queryBuilder->createNamedParameter($pageId, \PDO::PARAM_INT)
182
                )
183
            )
184
            ->execute();
185
186
        while ($record = $result->fetch()) {
187
            $solrCores[$record['index_name']] = $record['uid'];
188
        }
189
190
        return $solrCores;
191
    }
192
193
    /**
194
     * Fetches all documents with given collection.
195
     *
196
     * @param string $collId a comma separated list of collection uids
197
     * @param int $pageId the uid of the solr record
198
     *
199
     * @return array array of valid solr cores
200
     */
201
    protected function getDocumentsToProceed(string $collIds, int $pageId): array
202
    {
203
        /** @var QueryBuilder $queryBuilder */
204
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
205
            ->getQueryBuilderForTable('tx_dlf_documents');
206
207
        $documents = [];
208
        $pageId = (int)$pageId;
209
        $result = $queryBuilder
210
            ->select('tx_dlf_documents.uid')
211
            ->from('tx_dlf_documents')
212
            ->join(
213
                'tx_dlf_documents',
214
                'tx_dlf_relations',
215
                'tx_dlf_relations_joins',
216
                $queryBuilder->expr()->eq(
217
                    'tx_dlf_relations_joins.uid_local',
218
                    'tx_dlf_documents.uid'
219
                )
220
            )
221
            ->join(
222
                'tx_dlf_relations_joins',
223
                'tx_dlf_collections',
224
                'tx_dlf_collections_join',
225
                $queryBuilder->expr()->eq(
226
                    'tx_dlf_relations_joins.uid_foreign',
227
                    'tx_dlf_collections_join.uid'
228
                )
229
            )
230
            -> where(
231
              $queryBuilder->expr()->andX(
232
                  $queryBuilder->expr()->in(
233
                      'tx_dlf_collections_join.uid',
234
                      $queryBuilder->createNamedParameter(
235
                          GeneralUtility::intExplode(',', $collIds, true),
236
                          Connection::PARAM_INT_ARRAY
237
                      )
238
                  ),
239
                  $queryBuilder->expr()->eq(
240
                      'tx_dlf_collections_join.pid',
241
                      $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT)
242
                  ),
243
                  $queryBuilder->expr()->eq(
244
                      'tx_dlf_relations_joins.ident',
245
                      $queryBuilder->createNamedParameter('docs_colls')
246
                  )
247
              )
248
            )
249
            ->groupBy('tx_dlf_documents.uid')
250
            ->orderBy('tx_dlf_documents.uid', 'ASC')
251
            ->execute();
252
253
        while ($record = $result->fetch()) {
254
            $documents[] = $record['uid'];
255
        }
256
257
        return $documents;
258
    }
259
260
    /**
261
     * Fetches all documents of given page.
262
     *
263
     * @param int $pageId the uid of the solr record
264
     *
265
     * @return array array of valid solr cores
266
     */
267
    protected function getAllDocuments(int $pageId): array
268
    {
269
        /** @var QueryBuilder $queryBuilder */
270
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
271
            ->getQueryBuilderForTable('tx_dlf_documents');
272
273
        $documents = [];
274
        $pageId = (int)$pageId;
275
        $result = $queryBuilder
276
            ->select('uid')
277
            ->from('tx_dlf_documents')
278
            -> where(
279
              $queryBuilder->expr()->eq(
280
                  'tx_dlf_documents.pid',
281
                  $queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT)
282
              )
283
            )
284
            ->orderBy('tx_dlf_documents.uid', 'ASC')
285
            ->execute();
286
287
        while ($record = $result->fetch()) {
288
            $documents[] = $record['uid'];
289
        }
290
        return $documents;
291
    }
292
}
293