Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
90.62% |
58 / 64 |
|
50.00% |
4 / 8 |
CRAP | |
0.00% |
0 / 1 |
UndoSubmitAction | |
90.62% |
58 / 64 |
|
50.00% |
4 / 8 |
15.19 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
getName | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
getRestriction | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
show | |
77.78% |
7 / 9 |
|
0.00% |
0 / 1 |
3.10 | |||
checkPermissions | |
92.31% |
12 / 13 |
|
0.00% |
0 / 1 |
4.01 | |||
undo | |
77.78% |
7 / 9 |
|
0.00% |
0 / 1 |
3.10 | |||
storePatchedSchema | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
1 | |||
createSummaryCommentForUndoRev | |
100.00% |
14 / 14 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | |
3 | declare( strict_types = 1 ); |
4 | |
5 | namespace EntitySchema\MediaWiki\Actions; |
6 | |
7 | use EntitySchema\DataAccess\EntitySchemaStatus; |
8 | use EntitySchema\DataAccess\MediaWikiRevisionEntitySchemaUpdater; |
9 | use EntitySchema\Domain\Model\EntitySchemaId; |
10 | use EntitySchema\MediaWiki\EntitySchemaRedirectTrait; |
11 | use EntitySchema\Services\Converter\FullArrayEntitySchemaData; |
12 | use MediaWiki\CommentStore\CommentStoreComment; |
13 | use MediaWiki\Context\IContextSource; |
14 | use MediaWiki\Exception\PermissionsError; |
15 | use MediaWiki\Exception\ReadOnlyError; |
16 | use MediaWiki\Exception\UserBlockedError; |
17 | use MediaWiki\Page\Article; |
18 | use MediaWiki\Permissions\PermissionManager; |
19 | use MediaWiki\Revision\RevisionStore; |
20 | use MediaWiki\Status\Status; |
21 | use Wikimedia\Rdbms\ReadOnlyMode; |
22 | |
23 | /** |
24 | * @license GPL-2.0-or-later |
25 | */ |
26 | class UndoSubmitAction extends AbstractUndoAction { |
27 | |
28 | use EntitySchemaRedirectTrait; |
29 | |
30 | private PermissionManager $permissionManager; |
31 | private ReadOnlyMode $readOnlyMode; |
32 | |
33 | public function __construct( |
34 | Article $article, |
35 | IContextSource $context, |
36 | ReadOnlyMode $readOnlyMode, |
37 | PermissionManager $permissionManager, |
38 | RevisionStore $revisionStore |
39 | ) { |
40 | parent::__construct( $article, $context, $revisionStore ); |
41 | $this->permissionManager = $permissionManager; |
42 | $this->readOnlyMode = $readOnlyMode; |
43 | } |
44 | |
45 | public function getName(): string { |
46 | return 'submit'; |
47 | } |
48 | |
49 | public function getRestriction(): string { |
50 | return 'edit'; |
51 | } |
52 | |
53 | public function show(): void { |
54 | $permStatus = $this->checkPermissions(); |
55 | if ( !$permStatus->isOK() ) { |
56 | $this->showUndoErrorPage( $permStatus ); |
57 | return; |
58 | } |
59 | |
60 | $undoStatus = $this->undo(); |
61 | if ( !$undoStatus->isOK() ) { |
62 | $this->showUndoErrorPage( $undoStatus ); |
63 | return; |
64 | } |
65 | |
66 | $this->redirectToEntitySchema( $undoStatus ); |
67 | } |
68 | |
69 | /** |
70 | * @throws ReadOnlyError |
71 | * @throws UserBlockedError |
72 | * @throws PermissionsError |
73 | */ |
74 | private function checkPermissions(): Status { |
75 | $method = $this->getContext()->getRequest()->getMethod(); |
76 | if ( $method !== 'POST' ) { |
77 | return Status::newFatal( 'entityschema-error-not-post' ); |
78 | } |
79 | |
80 | $permissionErrors = $this->permissionManager->getPermissionErrors( |
81 | $this->getRestriction(), |
82 | $this->getUser(), |
83 | $this->getTitle() |
84 | ); |
85 | if ( $permissionErrors !== [] ) { |
86 | throw new PermissionsError( $this->getRestriction(), $permissionErrors ); |
87 | } |
88 | |
89 | if ( $this->readOnlyMode->isReadOnly() ) { |
90 | throw new ReadOnlyError; |
91 | } |
92 | |
93 | return Status::newGood(); |
94 | } |
95 | |
96 | private function undo(): EntitySchemaStatus { |
97 | $req = $this->getContext()->getRequest(); |
98 | |
99 | $diffStatus = $this->getDiffFromRequest( $req ); |
100 | if ( !$diffStatus->isOK() ) { |
101 | return EntitySchemaStatus::wrap( $diffStatus ); |
102 | } |
103 | |
104 | $patchStatus = $this->tryPatching( $diffStatus->getValue() ); |
105 | if ( !$patchStatus->isOK() ) { |
106 | return EntitySchemaStatus::wrap( $patchStatus ); |
107 | } |
108 | |
109 | [ $patchedSchema, $baseRevId ] = $patchStatus->getValue(); |
110 | return $this->storePatchedSchema( $patchedSchema, $baseRevId ); |
111 | } |
112 | |
113 | private function storePatchedSchema( |
114 | FullArrayEntitySchemaData $patchedSchema, |
115 | int $baseRevId |
116 | ): EntitySchemaStatus { |
117 | $schemaUpdater = MediaWikiRevisionEntitySchemaUpdater::newFromContext( $this->getContext() ); |
118 | |
119 | $summary = $this->createSummaryCommentForUndoRev( |
120 | $this->getContext()->getRequest()->getText( 'wpSummary' ), |
121 | $this->getContext()->getRequest()->getInt( 'undo' ) |
122 | ); |
123 | |
124 | return $schemaUpdater->overwriteWholeSchema( |
125 | new EntitySchemaId( $this->getTitle()->getTitleValue()->getText() ), |
126 | $patchedSchema->data['labels'], |
127 | $patchedSchema->data['descriptions'], |
128 | $patchedSchema->data['aliases'], |
129 | $patchedSchema->data['schemaText'], |
130 | $baseRevId, |
131 | $summary |
132 | ); |
133 | } |
134 | |
135 | private function createSummaryCommentForUndoRev( string $userSummary, int $undoRevId ): CommentStoreComment { |
136 | $revToBeUndone = $this->revisionStore->getRevisionById( $undoRevId ); |
137 | $userName = $revToBeUndone->getUser()->getName(); |
138 | $autoComment = MediaWikiRevisionEntitySchemaUpdater::AUTOCOMMENT_UNDO |
139 | . ':' . $undoRevId |
140 | . ':' . $userName; |
141 | return CommentStoreComment::newUnsavedComment( |
142 | '/* ' . $autoComment . ' */' . $userSummary, |
143 | [ |
144 | 'key' => MediaWikiRevisionEntitySchemaUpdater::AUTOCOMMENT_UNDO, |
145 | 'summary' => $userSummary, |
146 | 'undoRevId' => $undoRevId, |
147 | 'userName' => $userName, |
148 | ] |
149 | ); |
150 | } |
151 | |
152 | } |