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