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
Pull Request — master (#715)
by Alexander
03:36
created

BaseCommand::getParentDocumentUidForSaving()   A

Complexity

Conditions 6
Paths 7

Size

Total Lines 38
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 19
c 0
b 0
f 0
nc 7
nop 1
dl 0
loc 38
rs 9.0111
1
<?php
2
3
/**
4
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
5
 *
6
 * This file is part of the Kitodo and TYPO3 projects.
7
 *
8
 * @license GNU General Public License version 3 or later.
9
 * For the full copyright and license information, please read the
10
 * LICENSE.txt file that was distributed with this source code.
11
 */
12
13
namespace Kitodo\Dlf\Command;
14
15
use Kitodo\Dlf\Common\Doc;
16
use Kitodo\Dlf\Common\Helper;
17
use Kitodo\Dlf\Common\Indexer;
18
use Kitodo\Dlf\Domain\Repository\CollectionRepository;
19
use Kitodo\Dlf\Domain\Repository\DocumentRepository;
20
use Kitodo\Dlf\Domain\Repository\LibraryRepository;
21
use Kitodo\Dlf\Domain\Model\Document;
22
use Kitodo\Dlf\Domain\Model\Library;
23
use Symfony\Component\Console\Command\Command;
24
use TYPO3\CMS\Core\Utility\GeneralUtility;
25
use TYPO3\CMS\Core\Utility\MathUtility;
26
use TYPO3\CMS\Core\Database\ConnectionPool;
27
use TYPO3\CMS\Core\Database\Connection;
28
use TYPO3\CMS\Extbase\Configuration\ConfigurationManager;
29
use TYPO3\CMS\Extbase\Object\ObjectManager;
30
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
31
32
/**
33
 * Base class for CLI Command classes.
34
 *
35
 * @author Beatrycze Volk <[email protected]>
36
 * @package TYPO3
37
 * @subpackage dlf
38
 * @access public
39
 */
40
class BaseCommand extends Command
41
{
42
    /**
43
     * @var CollectionRepository
44
     */
45
    protected $collectionRepository;
46
47
    /**
48
     * @var DocumentRepository
49
     */
50
    protected $documentRepository;
51
52
    /**
53
     * @var LibraryRepository
54
     */
55
    protected $libraryRepository;
56
57
    /**
58
     * @var int
59
     */
60
    protected $storagePid;
61
62
    /**
63
     * @var \Kitodo\Dlf\Domain\Model\Library
64
     */
65
    protected $owner;
66
67
    /**
68
     * Initialize the extbase repository based on the given storagePid.
69
     *
70
     * TYPO3 10+: Find a better solution e.g. based on Symfonie Dependancy Injection.
71
     *
72
     * @param int $storagePid The storage pid
73
     *
74
     * @return bool
75
     */
76
    protected function initializeRepositories($storagePid)
77
    {
78
        if (MathUtility::canBeInterpretedAsInteger($storagePid)) {
79
            $configurationManager = GeneralUtility::makeInstance(ConfigurationManager::class);
80
            $frameworkConfiguration = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK);
81
82
            $frameworkConfiguration['persistence']['storagePid'] = MathUtility::forceIntegerInRange((int) $storagePid, 0);
83
            $configurationManager->setConfiguration($frameworkConfiguration);
84
85
            // TODO: When we drop support for TYPO3v9, we needn't/shouldn't use ObjectManager anymore
86
            $objectManager = GeneralUtility::makeInstance(ObjectManager::class);
87
88
            $this->collectionRepository = $objectManager->get(CollectionRepository::class);
89
            $this->documentRepository = $objectManager->get(DocumentRepository::class);
90
            $this->libraryRepository = $objectManager->get(LibraryRepository::class);
91
        } else {
92
            return false;
93
        }
94
        $this->storagePid = MathUtility::forceIntegerInRange((int) $storagePid, 0);
95
96
        return true;
97
    }
98
99
    /**
100
     * Return matching uid of Solr core depending on the input value.
101
     *
102
     * @param array $solrCores array of the valid Solr cores
103
     * @param string|bool|null $inputSolrId possible uid or name of Solr core
104
     *
105
     * @return int matching uid of Solr core
106
     */
107
    protected function getSolrCoreUid(array $solrCores, $inputSolrId): int
108
    {
109
        if (MathUtility::canBeInterpretedAsInteger($inputSolrId)) {
110
            $solrCoreUid = MathUtility::forceIntegerInRange((int) $inputSolrId, 0);
111
        } else {
112
            $solrCoreUid = $solrCores[$inputSolrId];
113
        }
114
        return $solrCoreUid;
115
    }
116
117
    /**
118
     * Fetches all Solr cores on given page.
119
     *
120
     * @param int $pageId The UID of the Solr core or 0 to disable indexing
121
     *
122
     * @return array Array of valid Solr cores
123
     */
124
    protected function getSolrCores(int $pageId): array
125
    {
126
        $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
127
            ->getQueryBuilderForTable('tx_dlf_solrcores');
128
129
        $solrCores = [];
130
        $result = $queryBuilder
131
            ->select('uid', 'index_name')
132
            ->from('tx_dlf_solrcores')
133
            ->where(
134
                $queryBuilder->expr()->eq(
135
                    'pid',
136
                    $queryBuilder->createNamedParameter((int) $pageId, Connection::PARAM_INT)
137
                )
138
            )
139
            ->execute();
140
141
        while ($record = $result->fetch()) {
142
            $solrCores[$record['index_name']] = $record['uid'];
143
        }
144
145
        return $solrCores;
146
    }
147
148
    /**
149
     * Load XML file / IIIF resource from URL
150
     *
151
     * @access protected
152
     *
153
     * @param string $location: The URL of the file to load
154
     *
155
     * @return string|bool the found xml as string or false on failure
156
     */
157
    protected function loadLocation($location)
158
    {
159
        // Load XML / JSON-LD file.
160
        if (GeneralUtility::isValidUrl($location)) {
161
            // Load extension configuration
162
            // $extConf = GeneralUtility::makeInstance(ExtensionConfiguration::class)->get(self::$extKey);
163
            // // Set user-agent to identify self when fetching XML / JSON-LD data.
164
            // if (!empty($extConf['useragent'])) {
165
            //     @ini_set('user_agent', $extConf['useragent']);
166
            // }
167
            $fileResource = GeneralUtility::getUrl($location);
168
            if ($fileResource !== false) {
169
                $xml = Helper::getXmlFileAsString($fileResource);
170
                if ($xml !== false) {
171
                    return $xml;
172
                }
173
            }
174
        } else {
175
            $this->logger->error('Invalid file location "' . $location . '" for document loading');
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on Kitodo\Dlf\Command\BaseCommand. Did you maybe forget to declare it?
Loading history...
176
        }
177
        return false;
178
    }
179
180
    /**
181
     * Update or insert document to database
182
     *
183
     * @param int|string $doc The document uid from DB OR the location of a mets document.
184
     *
185
     * @return bool true on success
186
     */
187
    protected function saveToDatabase(Document $document)
188
    {
189
        $success = false;
190
191
        $doc = $document->getDoc();
192
        if ($doc === null) {
193
            return $success;
194
        }
195
        $doc->cPid = $this->storagePid;
196
197
        $metadata = $doc->getTitledata($this->storagePid);
198
199
        // set title data
200
        $document->setTitle($metadata['title'][0] ? : '');
201
        $document->setTitleSorting($metadata['title_sorting'][0]);
202
        $document->setPlace(implode('; ', $metadata['place']));
203
        $document->setYear(implode('; ', $metadata['year']));
204
205
        // Remove appended "valueURI" from authors' names for storing in database.
206
        foreach ($metadata['author'] as $i => $author) {
207
            $splitName = explode(chr(31), $author);
208
            $metadata['author'][$i] = $splitName[0];
209
        }
210
        $document->setAuthor(implode('; ', $metadata['author']));
211
        $document->setThumbnail($doc->thumbnail ? : '');
212
        $document->setMetsLabel($metadata['mets_label'][0] ? : '');
213
        $document->setMetsOrderlabel($metadata['mets_orderlabel'][0] ? : '');
214
215
        $document->setStructure(Helper::getUidFromIndexName($metadata['type'][0], 'tx_dlf_structures') ? : 0);
0 ignored issues
show
Bug introduced by
Kitodo\Dlf\Common\Helper...x_dlf_structures') ?: 0 of type integer is incompatible with the type Kitodo\Dlf\Domain\Model\Structure expected by parameter $structure of Kitodo\Dlf\Domain\Model\Document::setStructure(). ( Ignorable by Annotation )

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

215
        $document->setStructure(/** @scrutinizer ignore-type */ Helper::getUidFromIndexName($metadata['type'][0], 'tx_dlf_structures') ? : 0);
Loading history...
216
217
        $collections = $this->collectionRepository->findCollectionsBySettings(['index_name' => $metadata['collection']]);
218
        if ($collections) {
0 ignored issues
show
introduced by
$collections is of type TYPO3\CMS\Extbase\Persistence\QueryResultInterface, thus it always evaluated to true.
Loading history...
219
            foreach ($collections as $collection) {
220
                $document->addCollection($collection);
221
            }
222
        }
223
224
        // set identifiers
225
        $document->setProdId($metadata['prod_id'][0] ? : '');
226
        $document->setOpacId($metadata['opac_id'][0] ? : '');
227
        $document->setUnionId($metadata['union_id'][0] ? : '');
228
229
        $document->setRecordId($metadata['record_id'][0] ? : ''); // (?) $doc->recordId
230
        $document->setUrn($metadata['urn'][0] ? : '');
231
        $document->setPurl($metadata['purl'][0] ? : '');
232
        $document->setDocumentFormat($metadata['document_format'][0] ? : '');
233
234
        // set access
235
        $document->setLicense($metadata['license'][0] ? : '');
236
        $document->setTerms($metadata['terms'][0] ? : '');
237
        $document->setRestrictions($metadata['restrictions'][0] ? : '');
238
        $document->setOutOfPrint($metadata['out_of_print'][0] ? : '');
239
        $document->setRightsInfo($metadata['rights_info'][0] ? : '');
240
        $document->setStatus(0);
241
242
        if ($this->owner) {
243
            // library / owner is set by parameter --> take it.
244
            $document->setOwner($this->owner);
245
        } else {
246
            // owner is not set set but found by metadata --> take it or take default library
247
            $owner = $metadata['owner'][0] ? : 'default';
248
            $this->owner = $this->libraryRepository->findOneByIndexName($owner);
0 ignored issues
show
Bug introduced by
The method findOneByIndexName() does not exist on Kitodo\Dlf\Domain\Repository\LibraryRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

248
            /** @scrutinizer ignore-call */ 
249
            $this->owner = $this->libraryRepository->findOneByIndexName($owner);
Loading history...
249
            if ($this->owner) {
250
                $document->setOwner($this->owner);
251
            } else {
252
                // create library
253
                $this->owner = GeneralUtility::makeInstance(Library::class);
254
255
                $this->owner->setLabel($owner);
256
                $this->owner->setIndexName($owner);
257
                $this->libraryRepository->add($this->owner);
258
                $document->setOwner($this->owner);
259
            }
260
        }
261
262
        // to be still (re-) implemented
263
        // 'volume' => $metadata['volume'][0],
264
        // 'volume_sorting' => $metadata['volume_sorting'][0],
265
266
        // Get UID of parent document.
267
        if ($document->getDocumentFormat() === 'METS') {
268
            $document->setPartof($this->getParentDocumentUidForSaving($document));
269
        }
270
271
        if ($document->getUid() === null) {
272
            // new document
273
            $this->documentRepository->add($document);
274
        } else {
275
            // update of existing document
276
            $this->documentRepository->update($document);
277
        }
278
279
        $persistenceManager = GeneralUtility::makeInstance(PersistenceManager::class);
280
        $persistenceManager->persistAll();
281
282
        $success = true;
283
284
        return $success;
285
    }
286
287
    /**
288
     * Get the ID of the parent document if the current document has one.
289
     * Currently only applies to METS documents.
290
     *
291
     * @access protected
292
     *
293
     * @return int The parent document's id.
294
     */
295
    protected function getParentDocumentUidForSaving(Document $document)
296
    {
297
        $doc = $document->getDoc();
298
299
        if ($doc !== null) {
300
            // Get the closest ancestor of the current document which has a MPTR child.
301
            $parentMptr = $doc->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="' . $doc->toplevelId . '"]/ancestor::mets:div[./mets:mptr][1]/mets:mptr');
0 ignored issues
show
Bug introduced by
The method xpath() does not exist on null. ( Ignorable by Annotation )

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

301
            /** @scrutinizer ignore-call */ 
302
            $parentMptr = $doc->mets->xpath('./mets:structMap[@TYPE="LOGICAL"]//mets:div[@ID="' . $doc->toplevelId . '"]/ancestor::mets:div[./mets:mptr][1]/mets:mptr');

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...
Bug Best Practice introduced by
The property mets does not exist on Kitodo\Dlf\Common\Doc. Since you implemented __get, consider adding a @property annotation.
Loading history...
302
            if (!empty($parentMptr)) {
303
                $parentLocation = (string) $parentMptr[0]->attributes('http://www.w3.org/1999/xlink')->href;
304
305
                // find document object by record_id of parent
306
                $parentDoc = Doc::getInstance($parentLocation, ['storagePid' => $this->storagePid]);
307
308
                if ($parentDoc->recordId) {
309
                    $parentDocument = $this->documentRepository->findOneByRecordId($parentDoc->recordId);
0 ignored issues
show
Bug introduced by
The method findOneByRecordId() does not exist on Kitodo\Dlf\Domain\Repository\DocumentRepository. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

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

309
                    /** @scrutinizer ignore-call */ 
310
                    $parentDocument = $this->documentRepository->findOneByRecordId($parentDoc->recordId);
Loading history...
310
311
                    if ($parentDocument === null) {
312
                        // create new Document object
313
                        $parentDocument = GeneralUtility::makeInstance(Document::class);
314
                    }
315
316
                    $parentDocument->setOwner($this->owner);
0 ignored issues
show
Bug introduced by
The method setOwner() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

316
                    $parentDocument->/** @scrutinizer ignore-call */ 
317
                                     setOwner($this->owner);

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...
317
                    $parentDocument->setDoc($parentDoc);
0 ignored issues
show
Bug introduced by
The method setDoc() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

317
                    $parentDocument->/** @scrutinizer ignore-call */ 
318
                                     setDoc($parentDoc);

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...
318
                    $parentDocument->setLocation($parentLocation);
0 ignored issues
show
Bug introduced by
The method setLocation() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

318
                    $parentDocument->/** @scrutinizer ignore-call */ 
319
                                     setLocation($parentLocation);

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...
319
                    $parentDocument->setSolrcore($document->getSolrcore());
0 ignored issues
show
Bug introduced by
The method setSolrcore() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

319
                    $parentDocument->/** @scrutinizer ignore-call */ 
320
                                     setSolrcore($document->getSolrcore());

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...
320
321
                    $success = $this->saveToDatabase($parentDocument);
322
323
                    if ($success === true) {
324
                        // add to index
325
                        Indexer::add($parentDocument);
326
                        return $parentDocument->getUid();
0 ignored issues
show
Bug introduced by
The method getUid() does not exist on TYPO3\CMS\Extbase\Persistence\QueryResultInterface. ( Ignorable by Annotation )

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

326
                        return $parentDocument->/** @scrutinizer ignore-call */ getUid();

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...
327
                    }
328
                }
329
            }
330
        }
331
332
        return 0;
333
    }
334
335
}
336