This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare( strict_types = 1 ); |
||
4 | |||
5 | namespace Wikibase\Client\Hooks; |
||
6 | |||
7 | use EditPage; |
||
8 | use Html; |
||
9 | use IContextSource; |
||
10 | use MediaWiki\Hook\EditPage__showStandardInputs_optionsHook; |
||
11 | use MessageLocalizer; |
||
12 | use OutputPage; |
||
13 | use Wikibase\Client\RepoLinker; |
||
14 | use Wikibase\Client\Usage\EntityUsage; |
||
15 | use Wikibase\Client\Usage\UsageLookup; |
||
16 | use Wikibase\Client\WikibaseClient; |
||
17 | use Wikibase\DataModel\Entity\EntityIdParser; |
||
18 | use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory; |
||
19 | |||
20 | /** |
||
21 | * Adds the Entity usage data in ActionEdit. |
||
22 | * |
||
23 | * @license GPL-2.0-or-later |
||
24 | * @author Amir Sarabadani < [email protected] > |
||
25 | */ |
||
26 | class EditActionHookHandler implements EditPage__showStandardInputs_optionsHook { |
||
27 | |||
28 | /** |
||
29 | * @var RepoLinker |
||
30 | */ |
||
31 | private $repoLinker; |
||
32 | |||
33 | /** |
||
34 | * @var UsageLookup |
||
35 | */ |
||
36 | private $usageLookup; |
||
37 | |||
38 | /** |
||
39 | * @var LanguageFallbackLabelDescriptionLookupFactory |
||
40 | */ |
||
41 | private $labelDescriptionLookupFactory; |
||
42 | |||
43 | /** |
||
44 | * @var EntityIdParser |
||
45 | */ |
||
46 | private $idParser; |
||
47 | |||
48 | public function __construct( |
||
49 | RepoLinker $repoLinker, |
||
50 | UsageLookup $usageLookup, |
||
51 | LanguageFallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory, |
||
52 | EntityIdParser $idParser |
||
53 | ) { |
||
54 | $this->repoLinker = $repoLinker; |
||
55 | $this->usageLookup = $usageLookup; |
||
56 | $this->labelDescriptionLookupFactory = $labelDescriptionLookupFactory; |
||
57 | $this->idParser = $idParser; |
||
58 | } |
||
59 | |||
60 | public static function factory(): self { |
||
61 | $wikibaseClient = WikibaseClient::getDefaultInstance(); |
||
62 | |||
63 | $usageLookup = $wikibaseClient->getStore()->getUsageLookup(); |
||
64 | $labelDescriptionLookupFactory = new LanguageFallbackLabelDescriptionLookupFactory( |
||
65 | $wikibaseClient->getLanguageFallbackChainFactory(), |
||
66 | $wikibaseClient->getTermLookup(), |
||
67 | $wikibaseClient->getTermBuffer() |
||
68 | ); |
||
69 | $idParser = $wikibaseClient->getEntityIdParser(); |
||
70 | |||
71 | return new self( |
||
72 | $wikibaseClient->newRepoLinker(), |
||
73 | $usageLookup, |
||
74 | $labelDescriptionLookupFactory, |
||
75 | $idParser |
||
76 | ); |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * @param EditPage $editor |
||
81 | * @param OutputPage $out |
||
82 | * @param int $tabindex |
||
83 | */ |
||
84 | // phpcs:ignore MediaWiki.NamingConventions.LowerCamelFunctionsName.FunctionName |
||
85 | public function onEditPage__showStandardInputs_options( $editor, $out, &$tabindex ): void { |
||
86 | if ( $editor->section ) { |
||
87 | // Shorten out, like template transclusion in core |
||
88 | return; |
||
89 | } |
||
90 | |||
91 | // Check if there are usages to show |
||
92 | $title = $editor->getTitle(); |
||
93 | $usages = $this->usageLookup->getUsagesForPage( $title->getArticleID() ); |
||
94 | |||
95 | if ( $usages ) { |
||
0 ignored issues
–
show
|
|||
96 | $header = $this->getHeader( $out ); |
||
97 | $usageOutput = $this->formatEntityUsage( $usages, $out ); |
||
98 | $output = Html::rawElement( |
||
99 | 'div', |
||
100 | [ 'class' => 'wikibase-entity-usage' ], |
||
101 | $header . "\n" . $usageOutput |
||
102 | ); |
||
103 | $editor->editFormTextAfterTools .= $output; |
||
104 | } |
||
105 | |||
106 | $out->addModules( 'wikibase.client.action.edit.collapsibleFooter' ); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * @param string[][] $rowAspects |
||
111 | * @param IContextSource $context |
||
112 | * |
||
113 | * @return string HTML |
||
114 | */ |
||
115 | private function formatAspects( array $rowAspects, IContextSource $context ): string { |
||
116 | $aspects = []; |
||
117 | |||
118 | foreach ( $rowAspects as $aspect ) { |
||
119 | // Possible messages: |
||
120 | // wikibase-pageinfo-entity-usage-L |
||
121 | // wikibase-pageinfo-entity-usage-L-with-modifier |
||
122 | // wikibase-pageinfo-entity-usage-D |
||
123 | // wikibase-pageinfo-entity-usage-D-with-modifier |
||
124 | // wikibase-pageinfo-entity-usage-C |
||
125 | // wikibase-pageinfo-entity-usage-C-with-modifier |
||
126 | // wikibase-pageinfo-entity-usage-S |
||
127 | // wikibase-pageinfo-entity-usage-T |
||
128 | // wikibase-pageinfo-entity-usage-X |
||
129 | // wikibase-pageinfo-entity-usage-O |
||
130 | $msgKey = 'wikibase-pageinfo-entity-usage-' . $aspect[0]; |
||
131 | if ( $aspect[1] !== null ) { |
||
132 | $msgKey .= '-with-modifier'; |
||
133 | } |
||
134 | $aspects[] = $context->msg( $msgKey, $aspect[1] )->parse(); |
||
135 | } |
||
136 | |||
137 | return $context->getLanguage()->commaList( $aspects ); |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * @param EntityUsage[] $usages |
||
142 | * @param IContextSource $context |
||
143 | * @return string HTML |
||
144 | */ |
||
145 | private function formatEntityUsage( array $usages, IContextSource $context ): string { |
||
146 | $usageAspectsByEntity = []; |
||
147 | $entityIds = []; |
||
148 | |||
149 | foreach ( $usages as $entityUsage ) { |
||
150 | $entityId = $entityUsage->getEntityId()->getSerialization(); |
||
151 | $entityIds[$entityId] = $entityUsage->getEntityId(); |
||
152 | $usageAspectsByEntity[$entityId][] = [ |
||
153 | $entityUsage->getAspect(), |
||
154 | $entityUsage->getModifier() |
||
155 | ]; |
||
156 | } |
||
157 | |||
158 | $output = ''; |
||
159 | $labelLookup = $this->labelDescriptionLookupFactory->newLabelDescriptionLookup( |
||
160 | $context->getLanguage(), |
||
161 | array_values( $entityIds ) |
||
162 | ); |
||
163 | |||
164 | foreach ( $usageAspectsByEntity as $entityId => $aspects ) { |
||
165 | $label = $labelLookup->getLabel( $entityIds[$entityId] ); |
||
166 | $text = $label === null ? $entityId : $label->getText(); |
||
167 | |||
168 | $aspectContent = $this->formatAspects( $aspects, $context ); |
||
169 | $colon = $context->msg( 'colon-separator' )->plain(); |
||
170 | $output .= Html::rawElement( |
||
171 | 'li', |
||
172 | [], |
||
173 | $this->repoLinker->buildEntityLink( |
||
174 | $entityIds[$entityId], |
||
175 | [ 'external' ], |
||
176 | $text |
||
177 | ) . $colon . $aspectContent |
||
178 | ); |
||
179 | } |
||
180 | return Html::rawElement( 'ul', [], $output ); |
||
181 | } |
||
182 | |||
183 | /** |
||
184 | * @param MessageLocalizer $context |
||
185 | * @return string HTML |
||
186 | */ |
||
187 | private function getHeader( MessageLocalizer $context ): string { |
||
188 | return Html::rawElement( |
||
189 | 'div', |
||
190 | [ 'class' => 'wikibase-entityusage-explanation' ], |
||
191 | $context->msg( 'wikibase-pageinfo-entity-usage' )->parseAsBlock() |
||
192 | ); |
||
193 | } |
||
194 | |||
195 | } |
||
196 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.