Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.31% covered (success)
98.31%
58 / 59
75.00% covered (warning)
75.00%
3 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
MediaWikiRevisionEntitySchemaInserter
98.31% covered (success)
98.31%
58 / 59
75.00% covered (warning)
75.00%
3 / 4
7
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 insertSchema
97.50% covered (success)
97.50%
39 / 40
0.00% covered (danger)
0.00%
0 / 1
3
 truncateSchemaTextForCommentData
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 saveRevision
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3declare( strict_types = 1 );
4
5namespace EntitySchema\DataAccess;
6
7use EntitySchema\Domain\Model\EntitySchemaId;
8use EntitySchema\Domain\Storage\IdGenerator;
9use EntitySchema\MediaWiki\Content\EntitySchemaContent;
10use EntitySchema\MediaWiki\HookRunner;
11use EntitySchema\Services\Converter\EntitySchemaConverter;
12use MediaWiki\CommentStore\CommentStoreComment;
13use MediaWiki\Context\IContextSource;
14use MediaWiki\Languages\LanguageFactory;
15use MediaWiki\Revision\SlotRecord;
16use MediaWiki\Storage\PageUpdater;
17
18/**
19 * @license GPL-2.0-or-later
20 */
21class MediaWikiRevisionEntitySchemaInserter implements EntitySchemaInserter {
22    public const AUTOCOMMENT_NEWSCHEMA = 'entityschema-summary-newschema-nolabel';
23
24    private MediaWikiPageUpdaterFactory $pageUpdaterFactory;
25    private IdGenerator $idGenerator;
26    private WatchlistUpdater $watchListUpdater;
27    private IContextSource $context;
28    private LanguageFactory $languageFactory;
29    private HookRunner $hookRunner;
30
31    public function __construct(
32        MediaWikiPageUpdaterFactory $pageUpdaterFactory,
33        WatchlistUpdater $watchListUpdater,
34        IdGenerator $idGenerator,
35        IContextSource $context,
36        LanguageFactory $languageFactory,
37        HookRunner $hookRunner
38    ) {
39        $this->idGenerator = $idGenerator;
40        $this->pageUpdaterFactory = $pageUpdaterFactory;
41        $this->watchListUpdater = $watchListUpdater;
42        $this->context = $context;
43        $this->languageFactory = $languageFactory;
44        $this->hookRunner = $hookRunner;
45    }
46
47    /**
48     * @param string $language
49     * @param string $label
50     * @param string $description
51     * @param string[] $aliases
52     * @param string $schemaText
53     *
54     * @return EntitySchemaStatus
55     */
56    public function insertSchema(
57        string $language,
58        string $label = '',
59        string $description = '',
60        array $aliases = [],
61        string $schemaText = ''
62    ): EntitySchemaStatus {
63        $id = new EntitySchemaId( 'E' . $this->idGenerator->getNewId() );
64        $persistentRepresentation = EntitySchemaEncoder::getPersistentRepresentation(
65            $id,
66            [ $language => $label ],
67            [ $language => $description ],
68            [ $language => $aliases ],
69            $schemaText
70        );
71
72        $schemaConverter = new EntitySchemaConverter();
73        $schemaData = $schemaConverter->getMonolingualNameBadgeData(
74            $persistentRepresentation,
75            $language
76        );
77        $summary = CommentStoreComment::newUnsavedComment(
78            '/* ' . self::AUTOCOMMENT_NEWSCHEMA . ' */' . $schemaData->label,
79            [
80                'key' => 'entityschema-summary-newschema-nolabel',
81                'language' => $language,
82                'label' => $schemaData->label,
83                'description' => $schemaData->description,
84                'aliases' => $schemaData->aliases,
85                'schemaText_truncated' => $this->truncateSchemaTextForCommentData(
86                    $schemaConverter->getSchemaText( $persistentRepresentation )
87                ),
88            ]
89        );
90
91        $updaterStatus = $this->pageUpdaterFactory->getPageUpdater( $id->getId(), $this->context );
92        if ( !$updaterStatus->isOK() ) {
93            return EntitySchemaStatus::wrap( $updaterStatus );
94        }
95        $status = EntitySchemaStatus::newEdit(
96            $id,
97            $updaterStatus->getSavedTempUser(),
98            $updaterStatus->getContext()
99        );
100        $content = new EntitySchemaContent( $persistentRepresentation );
101        $this->saveRevision( $status, $updaterStatus->getPageUpdater(), $content, $summary );
102        if ( !$status->isOK() ) {
103            return $status;
104        }
105
106        $this->watchListUpdater->optionallyWatchNewSchema( $this->context->getUser(), $id );
107
108        return $status;
109    }
110
111    private function truncateSchemaTextForCommentData( string $schemaText ): string {
112        $language = $this->languageFactory->getLanguage( 'en' );
113        return $language->truncateForVisual( $schemaText, 5000 );
114    }
115
116    private function saveRevision(
117        EntitySchemaStatus $status,
118        PageUpdater $updater,
119        EntitySchemaContent $content,
120        CommentStoreComment $summary
121    ): void {
122        $context = $status->getContext();
123        if ( !$this->hookRunner->onEditFilterMergedContent(
124            $context, $content, $status, $summary->text, $context->getUser(), false
125        ) ) {
126            return;
127        }
128
129        $updater->setContent( SlotRecord::MAIN, $content );
130        $updater->saveRevision(
131            $summary,
132            EDIT_NEW | EDIT_INTERNAL
133        );
134        $status->merge( $updater->getStatus() );
135    }
136
137}