Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
74.68% |
59 / 79 |
|
80.00% |
4 / 5 |
CRAP | |
0.00% |
0 / 1 |
SourceWikiCleanupSnippet | |
74.68% |
59 / 79 |
|
80.00% |
4 / 5 |
15.74 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
getHtml | |
67.74% |
42 / 62 |
|
0.00% |
0 / 1 |
7.21 | |||
isFreshImport | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
isSourceEditAllowed | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
isSourceDeleteAllowed | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | namespace FileImporter\Html; |
4 | |
5 | use FileImporter\Data\ImportPlan; |
6 | use FileImporter\Data\ImportRequest; |
7 | use FileImporter\Data\SourceUrl; |
8 | use FileImporter\Remote\MediaWiki\RemoteApiActionExecutor; |
9 | use FileImporter\Services\WikidataTemplateLookup; |
10 | use MediaWiki\Context\IContextSource; |
11 | use MediaWiki\Context\RequestContext; |
12 | use MediaWiki\Html\Html; |
13 | use MediaWiki\MediaWikiServices; |
14 | use MediaWiki\User\User; |
15 | use OOUI\CheckboxInputWidget; |
16 | use OOUI\FieldLayout; |
17 | use Psr\Log\LoggerInterface; |
18 | use Psr\Log\NullLogger; |
19 | |
20 | /** |
21 | * @license GPL-2.0-or-later |
22 | */ |
23 | class SourceWikiCleanupSnippet { |
24 | |
25 | public const ACTION_OFFERED_SOURCE_DELETE = 'offeredSourceDelete'; |
26 | public const ACTION_OFFERED_SOURCE_EDIT = 'offeredSourceEdit'; |
27 | |
28 | /** @var bool */ |
29 | private $sourceEditingEnabled; |
30 | /** @var bool */ |
31 | private $sourceDeletionEnabled; |
32 | private WikidataTemplateLookup $lookup; |
33 | private RemoteApiActionExecutor $remoteActionApi; |
34 | private LoggerInterface $logger; |
35 | |
36 | /** |
37 | * @param bool $sourceEditingEnabled |
38 | * @param bool $sourceDeletionEnabled |
39 | * @param LoggerInterface|null $logger |
40 | */ |
41 | public function __construct( |
42 | $sourceEditingEnabled = true, |
43 | $sourceDeletionEnabled = true, |
44 | LoggerInterface $logger = null |
45 | ) { |
46 | $this->sourceEditingEnabled = $sourceEditingEnabled; |
47 | $this->sourceDeletionEnabled = $sourceDeletionEnabled; |
48 | $this->logger = $logger ?? new NullLogger(); |
49 | |
50 | // TODO: Inject |
51 | $this->lookup = MediaWikiServices::getInstance()->getService( |
52 | 'FileImporterTemplateLookup' ); |
53 | $this->remoteActionApi = MediaWikiServices::getInstance()->getService( |
54 | 'FileImporterMediaWikiRemoteApiActionExecutor' ); |
55 | } |
56 | |
57 | /** |
58 | * @return string |
59 | */ |
60 | public function getHtml( ImportPlan $importPlan, User $user ) { |
61 | /** @var IContextSource $context */ |
62 | $context = RequestContext::getMain(); |
63 | $sourceUrl = $importPlan->getRequest()->getUrl(); |
64 | |
65 | $canAutomateEdit = $this->isSourceEditAllowed( |
66 | $sourceUrl, |
67 | $user, |
68 | $importPlan->getOriginalTitle()->getPrefixedText() |
69 | ); |
70 | $canAutomateDelete = $this->isSourceDeleteAllowed( $sourceUrl, $user ); |
71 | |
72 | if ( !$canAutomateEdit && !$canAutomateDelete ) { |
73 | return ''; |
74 | } |
75 | |
76 | $html = Html::element( |
77 | 'h2', |
78 | [], |
79 | $context->msg( 'fileimporter-heading-cleanup' )->plain() |
80 | ); |
81 | |
82 | if ( $canAutomateDelete ) { |
83 | $automateDeleteSelected = $importPlan->getAutomateSourceWikiDelete(); |
84 | $importPlan->setActionIsPerformed( self::ACTION_OFFERED_SOURCE_DELETE ); |
85 | |
86 | $html .= Html::rawElement( |
87 | 'p', |
88 | [], |
89 | $context->msg( 'fileimporter-delete-text' )->parse() |
90 | ) . |
91 | new FieldLayout( |
92 | new CheckboxInputWidget( |
93 | [ |
94 | 'name' => 'automateSourceWikiDelete', |
95 | 'selected' => $automateDeleteSelected, |
96 | 'value' => true |
97 | ] |
98 | ), |
99 | [ |
100 | 'label' => $context->msg( 'fileimporter-delete-checkboxlabel' )->parse(), |
101 | 'align' => 'inline' |
102 | ] |
103 | ); |
104 | } elseif ( $canAutomateEdit ) { |
105 | $automateEditSelected = $importPlan->getAutomateSourceWikiCleanUp() || |
106 | $this->isFreshImport( $importPlan->getRequest() ); |
107 | $importPlan->setActionIsPerformed( self::ACTION_OFFERED_SOURCE_EDIT ); |
108 | |
109 | $html .= Html::rawElement( |
110 | 'p', |
111 | [], |
112 | $context->msg( |
113 | 'fileimporter-cleanup-text', |
114 | $this->lookup->fetchNowCommonsLocalTitle( $sourceUrl ) |
115 | )->parse() |
116 | ) . |
117 | new FieldLayout( |
118 | new CheckboxInputWidget( |
119 | [ |
120 | 'name' => 'automateSourceWikiCleanup', |
121 | 'selected' => $automateEditSelected, |
122 | 'value' => true |
123 | ] |
124 | ), |
125 | [ |
126 | 'label' => $context->msg( 'fileimporter-cleanup-checkboxlabel' )->parse(), |
127 | 'align' => 'inline' |
128 | ] |
129 | ); |
130 | } |
131 | |
132 | return $html; |
133 | } |
134 | |
135 | /** |
136 | * @return bool |
137 | */ |
138 | private function isFreshImport( ImportRequest $importRequest ) { |
139 | return $importRequest->getImportDetailsHash() === ''; |
140 | } |
141 | |
142 | /** |
143 | * Warning, contrary to the method name this currently doesn't check if the user is allowed to |
144 | * edit the page! |
145 | * |
146 | * @return bool True if source wiki editing is enabled and a localized {{Now Commons}} template |
147 | * can be found. |
148 | */ |
149 | private function isSourceEditAllowed( SourceUrl $sourceUrl, User $user, string $title ) { |
150 | if ( !$this->sourceEditingEnabled || |
151 | // Note: This intentionally doesn't allow a template with the name "0". |
152 | !$this->lookup->fetchNowCommonsLocalTitle( $sourceUrl ) |
153 | ) { |
154 | return false; |
155 | } |
156 | |
157 | return $this->remoteActionApi->executeTestEditActionQuery( $sourceUrl, $user, $title ) |
158 | ->isGood(); |
159 | } |
160 | |
161 | /** |
162 | * @return bool True if source wiki deletions are enabled and the user does have the right to |
163 | * delete pages. Also returns false if querying the user rights failed. |
164 | */ |
165 | private function isSourceDeleteAllowed( SourceUrl $sourceUrl, User $user ) { |
166 | if ( !$this->sourceDeletionEnabled ) { |
167 | return false; |
168 | } |
169 | |
170 | return $this->remoteActionApi->executeUserRightsQuery( $sourceUrl, $user ) |
171 | ->isGood(); |
172 | } |
173 | |
174 | } |