Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
3 / 3
CRAP
100.00% covered (success)
100.00%
1 / 1
NullRevisionCreator
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
3 / 3
5
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createForLinkTarget
100.00% covered (success)
100.00%
32 / 32
100.00% covered (success)
100.00%
1 / 1
3
 publishLogEntry
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace FileImporter\Services;
4
5use FileImporter\Data\FileRevision;
6use FileImporter\Exceptions\ImportException;
7use MediaWiki\CommentStore\CommentStoreComment;
8use MediaWiki\Logging\ManualLogEntry;
9use MediaWiki\Revision\MutableRevisionRecord;
10use MediaWiki\Revision\RevisionRecord;
11use MediaWiki\Revision\RevisionStore;
12use MediaWiki\Title\Title;
13use MediaWiki\User\UserIdentity;
14use Wikimedia\Rdbms\IConnectionProvider;
15use Wikimedia\Rdbms\IDatabase;
16use Wikimedia\Timestamp\ConvertibleTimestamp;
17
18/**
19 * @license GPL-2.0-or-later
20 */
21class NullRevisionCreator {
22
23    private const ERROR_REVISION_CREATE = 'noNullRevisionCreated';
24
25    public function __construct(
26        private readonly RevisionStore $revisionStore,
27        private readonly IConnectionProvider $connectionProvider,
28    ) {
29    }
30
31    /**
32     * @param Title $title
33     * @param FileRevision $fileRevision
34     * @param UserIdentity $user
35     * @param string $summary
36     *
37     * @throws ImportException e.g. when the $title was not created before
38     */
39    public function createForLinkTarget(
40        Title $title,
41        FileRevision $fileRevision,
42        UserIdentity $user,
43        $summary
44    ) {
45        $db = $this->connectionProvider->getPrimaryDatabase();
46        $nullRevision = $this->revisionStore->newNullRevision(
47            $db,
48            $title,
49            CommentStoreComment::newUnsavedComment( $summary ),
50            true,
51            $user
52        );
53
54        if ( !$nullRevision ) {
55            throw new ImportException(
56                'Failed to create import revision', self::ERROR_REVISION_CREATE );
57        }
58
59        if ( $nullRevision instanceof MutableRevisionRecord ) {
60            $now = new ConvertibleTimestamp();
61            // Place the null revision (along with the import log entry that mirrors the same
62            // information) 1 second in the past, to guarantee it's listed before the later "post
63            // import edit".
64            $now->timestamp->sub( new \DateInterval( 'PT1S' ) );
65            $nullRevision->setTimestamp( $now->getTimestamp( TS_MW ) );
66        }
67
68        $nullRevision = $this->revisionStore->insertRevisionOn( $nullRevision, $db );
69
70        /** @see \ImportReporter::reportPage */
71        $this->publishLogEntry(
72            $db,
73            'import',
74            'interwiki',
75            $nullRevision
76        );
77
78        /** @see \LocalFile::recordUpload2 */
79        $this->publishLogEntry(
80            $db,
81            'upload',
82            'upload',
83            $nullRevision,
84            [
85                'img_sha1' => $fileRevision->getField( 'sha1' ),
86                'img_timestamp' => $fileRevision->getField( 'timestamp' ),
87            ]
88        );
89    }
90
91    private function publishLogEntry(
92        IDatabase $db,
93        string $type,
94        string $subtype,
95        RevisionRecord $revision,
96        array $parameters = []
97    ): void {
98        $logEntry = new ManualLogEntry( $type, $subtype );
99
100        $logEntry->setParameters( $parameters );
101        $logEntry->setPerformer( $revision->getUser() );
102        $logEntry->setTarget( $revision->getPage() );
103        $logEntry->setTimestamp( $revision->getTimestamp() );
104        $logEntry->setComment( $revision->getComment()->text );
105        $logEntry->setAssociatedRevId( $revision->getId() );
106        $logEntry->addTags( 'fileimporter' );
107
108        $logEntryId = $logEntry->insert( $db );
109        $logEntry->publish( $logEntryId );
110    }
111
112}