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 | namespace Wikibase\Repo\Specials; |
||
| 4 | |||
| 5 | use Html; |
||
| 6 | use HTMLForm; |
||
| 7 | use InvalidArgumentException; |
||
| 8 | use OutOfBoundsException; |
||
| 9 | use SiteLookup; |
||
| 10 | use Status; |
||
| 11 | use Wikibase\DataModel\Entity\EntityDocument; |
||
| 12 | use Wikibase\DataModel\Entity\Item; |
||
| 13 | use Wikibase\DataModel\Entity\ItemId; |
||
| 14 | use Wikibase\Lib\Store\EntityTitleLookup; |
||
| 15 | use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookupFactory; |
||
| 16 | use Wikibase\Lib\Summary; |
||
| 17 | use Wikibase\Repo\ChangeOp\ChangeOpException; |
||
| 18 | use Wikibase\Repo\ChangeOp\SiteLinkChangeOpFactory; |
||
| 19 | use Wikibase\Repo\CopyrightMessageBuilder; |
||
| 20 | use Wikibase\Repo\EditEntity\MediawikiEditEntityFactory; |
||
| 21 | use Wikibase\Repo\SiteLinkTargetProvider; |
||
| 22 | use Wikibase\Repo\SummaryFormatter; |
||
| 23 | use Wikibase\Repo\WikibaseRepo; |
||
| 24 | |||
| 25 | /** |
||
| 26 | * Special page for setting the sitepage of a Wikibase entity. |
||
| 27 | * |
||
| 28 | * @license GPL-2.0-or-later |
||
| 29 | * @author Bene* < [email protected] > |
||
| 30 | */ |
||
| 31 | class SpecialSetSiteLink extends SpecialModifyEntity { |
||
| 32 | |||
| 33 | /** |
||
| 34 | * @var SiteLookup |
||
| 35 | */ |
||
| 36 | private $siteLookup; |
||
| 37 | |||
| 38 | /** |
||
| 39 | * @var SiteLinkTargetProvider |
||
| 40 | */ |
||
| 41 | private $siteLinkTargetProvider; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * @var string[] |
||
| 45 | */ |
||
| 46 | private $siteLinkGroups; |
||
| 47 | |||
| 48 | /** |
||
| 49 | * @var string[] |
||
| 50 | */ |
||
| 51 | private $badgeItems; |
||
| 52 | |||
| 53 | /** |
||
| 54 | * @var LanguageFallbackLabelDescriptionLookupFactory |
||
| 55 | */ |
||
| 56 | private $labelDescriptionLookupFactory; |
||
| 57 | |||
| 58 | /** |
||
| 59 | * @var SiteLinkChangeOpFactory |
||
| 60 | */ |
||
| 61 | private $siteLinkChangeOpFactory; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * The site of the site link. |
||
| 65 | * |
||
| 66 | * @var string|null |
||
| 67 | */ |
||
| 68 | private $site; |
||
| 69 | |||
| 70 | /** |
||
| 71 | * The page of the site link. |
||
| 72 | * |
||
| 73 | * @var string |
||
| 74 | */ |
||
| 75 | private $page; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * The badges of the site link. |
||
| 79 | * |
||
| 80 | * @var string[] |
||
| 81 | */ |
||
| 82 | private $badges; |
||
| 83 | |||
| 84 | /** |
||
| 85 | * @param SpecialPageCopyrightView $copyrightView |
||
| 86 | * @param SummaryFormatter $summaryFormatter |
||
| 87 | * @param EntityTitleLookup $entityTitleLookup |
||
| 88 | * @param MediawikiEditEntityFactory $editEntityFactory |
||
| 89 | * @param SiteLookup $siteLookup |
||
| 90 | * @param SiteLinkTargetProvider $siteLinkTargetProvider |
||
| 91 | * @param string[] $siteLinkGroups |
||
| 92 | * @param string[] $badgeItems |
||
| 93 | * @param LanguageFallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory |
||
| 94 | * @param SiteLinkChangeOpFactory $siteLinkChangeOpFactory |
||
| 95 | */ |
||
| 96 | public function __construct( |
||
| 97 | SpecialPageCopyrightView $copyrightView, |
||
| 98 | SummaryFormatter $summaryFormatter, |
||
| 99 | EntityTitleLookup $entityTitleLookup, |
||
| 100 | MediawikiEditEntityFactory $editEntityFactory, |
||
| 101 | SiteLookup $siteLookup, |
||
| 102 | SiteLinkTargetProvider $siteLinkTargetProvider, |
||
| 103 | array $siteLinkGroups, |
||
| 104 | array $badgeItems, |
||
| 105 | LanguageFallbackLabelDescriptionLookupFactory $labelDescriptionLookupFactory, |
||
| 106 | SiteLinkChangeOpFactory $siteLinkChangeOpFactory |
||
| 107 | ) { |
||
| 108 | parent::__construct( |
||
| 109 | 'SetSiteLink', |
||
| 110 | $copyrightView, |
||
| 111 | $summaryFormatter, |
||
| 112 | $entityTitleLookup, |
||
| 113 | $editEntityFactory |
||
| 114 | ); |
||
| 115 | |||
| 116 | $this->siteLookup = $siteLookup; |
||
| 117 | $this->siteLinkTargetProvider = $siteLinkTargetProvider; |
||
| 118 | $this->siteLinkGroups = $siteLinkGroups; |
||
| 119 | $this->badgeItems = $badgeItems; |
||
| 120 | $this->labelDescriptionLookupFactory = $labelDescriptionLookupFactory; |
||
| 121 | $this->siteLinkChangeOpFactory = $siteLinkChangeOpFactory; |
||
| 122 | } |
||
| 123 | |||
| 124 | public static function factory(): self { |
||
| 125 | $wikibaseRepo = WikibaseRepo::getDefaultInstance(); |
||
| 126 | $siteLookup = $wikibaseRepo->getSiteLookup(); |
||
| 127 | $settings = $wikibaseRepo->getSettings(); |
||
| 128 | |||
| 129 | $siteLinkChangeOpFactory = $wikibaseRepo->getChangeOpFactoryProvider()->getSiteLinkChangeOpFactory(); |
||
| 130 | $siteLinkTargetProvider = new SiteLinkTargetProvider( |
||
| 131 | $siteLookup, |
||
| 132 | $settings->getSetting( 'specialSiteLinkGroups' ) |
||
| 133 | ); |
||
| 134 | |||
| 135 | $copyrightView = new SpecialPageCopyrightView( |
||
| 136 | new CopyrightMessageBuilder(), |
||
| 137 | $settings->getSetting( 'dataRightsUrl' ), |
||
| 138 | $settings->getSetting( 'dataRightsText' ) |
||
| 139 | ); |
||
| 140 | |||
| 141 | $labelDescriptionLookupFactory = $wikibaseRepo->getLanguageFallbackLabelDescriptionLookupFactory(); |
||
| 142 | return new self( |
||
| 143 | $copyrightView, |
||
| 144 | $wikibaseRepo->getSummaryFormatter(), |
||
| 145 | $wikibaseRepo->getEntityTitleLookup(), |
||
| 146 | $wikibaseRepo->newEditEntityFactory(), |
||
| 147 | $siteLookup, |
||
| 148 | $siteLinkTargetProvider, |
||
| 149 | $settings->getSetting( 'siteLinkGroups' ), |
||
| 150 | $settings->getSetting( 'badgeItems' ), |
||
| 151 | $labelDescriptionLookupFactory, |
||
| 152 | $siteLinkChangeOpFactory |
||
| 153 | ); |
||
| 154 | } |
||
| 155 | |||
| 156 | public function doesWrites() { |
||
| 157 | return true; |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * @see SpecialModifyEntity::processArguments() |
||
| 162 | * |
||
| 163 | * @param string|null $subPage |
||
| 164 | */ |
||
| 165 | protected function processArguments( $subPage ) { |
||
| 166 | parent::processArguments( $subPage ); |
||
| 167 | |||
| 168 | $request = $this->getRequest(); |
||
| 169 | // explode the sub page from the format Special:SetSitelink/q123/enwiki |
||
| 170 | $parts = ( $subPage === '' ) ? [] : explode( '/', $subPage, 2 ); |
||
| 171 | |||
| 172 | $entityId = $this->getEntityId(); |
||
| 173 | |||
| 174 | // check if id belongs to an item |
||
| 175 | if ( $entityId !== null |
||
| 176 | && $entityId->getEntityType() !== Item::ENTITY_TYPE |
||
| 177 | ) { |
||
| 178 | $msg = $this->msg( 'wikibase-setsitelink-not-item', $entityId->getSerialization() ); |
||
| 179 | $this->showErrorHTML( $msg->parse() ); |
||
| 180 | } |
||
| 181 | |||
| 182 | $this->site = trim( $request->getVal( 'site', $parts[1] ?? '' ) ); |
||
| 183 | |||
| 184 | if ( $this->site === '' ) { |
||
| 185 | $this->site = null; |
||
| 186 | } |
||
| 187 | |||
| 188 | if ( $this->site !== null && !$this->isValidSiteId( $this->site ) ) { |
||
| 189 | $this->showErrorHTML( $this->msg( |
||
| 190 | 'wikibase-setsitelink-invalid-site', |
||
| 191 | wfEscapeWikiText( $this->site ) |
||
| 192 | )->parse() ); |
||
| 193 | } |
||
| 194 | |||
| 195 | $this->page = $request->getVal( 'page' ); |
||
| 196 | |||
| 197 | // If the user just enters an item id and a site, dont remove the site link. |
||
| 198 | // The user can remove the site link in the second form where it has to be |
||
| 199 | // actually removed. This prevents users from removing site links accidentally. |
||
| 200 | if ( !$request->getCheck( 'remove' ) && $this->page === '' ) { |
||
| 201 | $this->page = null; |
||
| 202 | } |
||
| 203 | |||
| 204 | $this->badges = array_intersect( |
||
|
0 ignored issues
–
show
|
|||
| 205 | array_keys( $this->badgeItems ), |
||
| 206 | $request->getArray( 'badges', [] ) |
||
| 207 | ); |
||
| 208 | } |
||
| 209 | |||
| 210 | /** |
||
| 211 | * @see SpecialModifyEntity::validateInput() |
||
| 212 | * |
||
| 213 | * @return bool |
||
| 214 | */ |
||
| 215 | protected function validateInput() { |
||
| 216 | if ( !$this->isValidSiteId( $this->site ) ) { |
||
| 217 | return false; |
||
| 218 | } |
||
| 219 | |||
| 220 | if ( $this->page === null ) { |
||
| 221 | return false; |
||
| 222 | } |
||
| 223 | |||
| 224 | if ( !parent::validateInput() ) { |
||
| 225 | return false; |
||
| 226 | } |
||
| 227 | |||
| 228 | return true; |
||
| 229 | } |
||
| 230 | |||
| 231 | /** |
||
| 232 | * @see SpecialModifyEntity::modifyEntity() |
||
| 233 | * |
||
| 234 | * @param EntityDocument $entity |
||
| 235 | * |
||
| 236 | * @return Summary|bool The summary or false |
||
| 237 | */ |
||
| 238 | protected function modifyEntity( EntityDocument $entity ) { |
||
| 239 | try { |
||
| 240 | $status = $this->setSiteLink( $entity, $this->site, $this->page, $this->badges, $summary ); |
||
| 241 | } catch ( ChangeOpException $e ) { |
||
| 242 | $this->showErrorHTML( $e->getMessage() ); |
||
| 243 | return false; |
||
| 244 | } |
||
| 245 | |||
| 246 | if ( !$status->isGood() ) { |
||
| 247 | $this->showErrorHTML( $status->getMessage()->parse() ); |
||
| 248 | return false; |
||
| 249 | } |
||
| 250 | |||
| 251 | return $summary; |
||
| 252 | } |
||
| 253 | |||
| 254 | /** |
||
| 255 | * Checks if the site id is valid. |
||
| 256 | * |
||
| 257 | * @param string $siteId the site id |
||
| 258 | * |
||
| 259 | * @return bool |
||
| 260 | */ |
||
| 261 | private function isValidSiteId( $siteId ) { |
||
| 262 | return $siteId !== null |
||
| 263 | && $this->siteLinkTargetProvider->getSiteList( $this->siteLinkGroups )->hasSite( $siteId ); |
||
| 264 | } |
||
| 265 | |||
| 266 | /** |
||
| 267 | * @see SpecialModifyEntity::getForm() |
||
| 268 | * |
||
| 269 | * @param EntityDocument|null $entity |
||
| 270 | * |
||
| 271 | * @return HTMLForm |
||
| 272 | */ |
||
| 273 | protected function getForm( EntityDocument $entity = null ) { |
||
| 274 | if ( $this->page === null ) { |
||
| 275 | $this->page = $this->site === null ? '' : $this->getSiteLink( $entity, $this->site ); |
||
| 276 | } |
||
| 277 | if ( empty( $this->badges ) ) { |
||
| 278 | $this->badges = $this->site === null ? [] : $this->getBadges( $entity, $this->site ); |
||
| 279 | } |
||
| 280 | $pageinput = [ |
||
| 281 | 'page' => [ |
||
| 282 | 'name' => 'page', |
||
| 283 | 'label-message' => 'wikibase-setsitelink-label', |
||
| 284 | 'type' => 'text', |
||
| 285 | 'default' => $this->getRequest()->getVal( 'page' ) ?: $this->page, |
||
| 286 | 'nodata' => true, |
||
| 287 | 'cssclass' => 'wb-input wb-input-text', |
||
| 288 | 'id' => 'wb-setsitelink-page' |
||
| 289 | ] |
||
| 290 | ]; |
||
| 291 | |||
| 292 | if ( !empty( $this->badgeItems ) ) { |
||
| 293 | $pageinput['badges'] = $this->getMultiSelectForBadges(); |
||
| 294 | } |
||
| 295 | |||
| 296 | $site = $this->siteLookup->getSite( $this->site ); |
||
| 297 | |||
| 298 | if ( $entity !== null && $this->site !== null && $site !== null ) { |
||
| 299 | // show the detailed form which also allows users to remove site links |
||
| 300 | $intro = $this->msg( |
||
| 301 | 'wikibase-setsitelink-introfull', |
||
| 302 | $this->getEntityTitle( $entity->getId() )->getPrefixedText(), |
||
| 303 | '[' . $site->getPageUrl( '' ) . ' ' . $this->site . ']' |
||
| 304 | )->parse(); |
||
| 305 | $formDescriptor = [ |
||
| 306 | 'site' => [ |
||
| 307 | 'name' => 'site', |
||
| 308 | 'type' => 'hidden', |
||
| 309 | 'default' => $this->site |
||
| 310 | ], |
||
| 311 | 'id' => [ |
||
| 312 | 'name' => 'id', |
||
| 313 | 'type' => 'hidden', |
||
| 314 | 'default' => $this->getEntityId()->getSerialization() |
||
| 315 | ], |
||
| 316 | 'remove' => [ |
||
| 317 | 'name' => 'remove', |
||
| 318 | 'type' => 'hidden', |
||
| 319 | 'default' => 'remove' |
||
| 320 | ], |
||
| 321 | 'revid' => [ |
||
| 322 | 'name' => 'revid', |
||
| 323 | 'type' => 'hidden', |
||
| 324 | 'default' => $this->getBaseRevision()->getRevisionId(), |
||
| 325 | ] |
||
| 326 | ]; |
||
| 327 | } else { |
||
| 328 | $intro = $this->msg( 'wikibase-setsitelink-intro' )->text(); |
||
| 329 | |||
| 330 | if ( !empty( $this->badgeItems ) ) { |
||
| 331 | $intro .= $this->msg( 'word-separator' )->text() . $this->msg( 'wikibase-setsitelink-intro-badges' )->text(); |
||
| 332 | } |
||
| 333 | |||
| 334 | $formDescriptor = $this->getFormElements( $entity ); |
||
| 335 | $formDescriptor['site'] = [ |
||
| 336 | 'name' => 'site', |
||
| 337 | 'label-message' => 'wikibase-setsitelink-site', |
||
| 338 | 'type' => 'text', |
||
| 339 | 'default' => $this->getRequest()->getVal( 'site' ) ?: $this->site, |
||
| 340 | 'cssclass' => 'wb-input', |
||
| 341 | 'id' => 'wb-setsitelink-site' |
||
| 342 | ]; |
||
| 343 | } |
||
| 344 | $formDescriptor = array_merge( $formDescriptor, $pageinput ); |
||
| 345 | |||
| 346 | return HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() ) |
||
| 347 | ->setHeaderText( Html::rawElement( 'p', [], $intro ) ); |
||
| 348 | } |
||
| 349 | |||
| 350 | /** |
||
| 351 | * Returns an array for generating a checkbox for each badge. |
||
| 352 | * |
||
| 353 | * @return array |
||
| 354 | */ |
||
| 355 | private function getMultiSelectForBadges() { |
||
| 356 | $options = []; |
||
| 357 | $default = []; |
||
| 358 | |||
| 359 | /** @var ItemId[] $badgeItemIds */ |
||
| 360 | $badgeItemIds = array_map( |
||
| 361 | function( $badgeId ) { |
||
| 362 | return new ItemId( $badgeId ); |
||
| 363 | }, |
||
| 364 | array_keys( $this->badgeItems ) |
||
| 365 | ); |
||
| 366 | |||
| 367 | $labelLookup = $this->labelDescriptionLookupFactory->newLabelDescriptionLookup( |
||
| 368 | $this->getLanguage(), |
||
| 369 | $badgeItemIds |
||
| 370 | ); |
||
| 371 | |||
| 372 | foreach ( $badgeItemIds as $badgeId ) { |
||
| 373 | $idSerialization = $badgeId->getSerialization(); |
||
| 374 | |||
| 375 | $label = $labelLookup->getLabel( $badgeId ); |
||
| 376 | $label = $label === null ? $idSerialization : $label->getText(); |
||
| 377 | |||
| 378 | $options[$label] = $idSerialization; |
||
| 379 | if ( in_array( $idSerialization, $this->badges ) ) { |
||
| 380 | $default[] = $idSerialization; |
||
| 381 | } |
||
| 382 | } |
||
| 383 | |||
| 384 | return [ |
||
| 385 | 'name' => 'badges', |
||
| 386 | 'type' => 'multiselect', |
||
| 387 | 'label-message' => 'wikibase-setsitelink-badges', |
||
| 388 | 'options' => $options, |
||
| 389 | 'default' => $default |
||
| 390 | ]; |
||
| 391 | } |
||
| 392 | |||
| 393 | /** |
||
| 394 | * Returning the site page of the entity. |
||
| 395 | * |
||
| 396 | * @param Item|null $item |
||
| 397 | * @param string $siteId |
||
| 398 | * |
||
| 399 | * @throws OutOfBoundsException |
||
| 400 | * @return string |
||
| 401 | */ |
||
| 402 | private function getSiteLink( ?Item $item, $siteId ) { |
||
| 403 | if ( $item === null || !$item->hasLinkToSite( $siteId ) ) { |
||
| 404 | return ''; |
||
| 405 | } |
||
| 406 | |||
| 407 | return $item->getSiteLink( $siteId )->getPageName(); |
||
| 408 | } |
||
| 409 | |||
| 410 | /** |
||
| 411 | * Returning the badges of the entity. |
||
| 412 | * |
||
| 413 | * @param Item|null $item |
||
| 414 | * @param string $siteId |
||
| 415 | * |
||
| 416 | * @throws OutOfBoundsException |
||
| 417 | * @return string[] |
||
| 418 | */ |
||
| 419 | private function getBadges( ?Item $item, $siteId ) { |
||
| 420 | if ( $item === null || !$item->getSiteLinkList()->hasLinkWithSiteId( $siteId ) ) { |
||
| 421 | return []; |
||
| 422 | } |
||
| 423 | |||
| 424 | return array_map( |
||
| 425 | function( ItemId $badge ) { |
||
| 426 | return $badge->getSerialization(); |
||
| 427 | }, |
||
| 428 | $item->getSiteLinkList()->getBySiteId( $siteId )->getBadges() |
||
| 429 | ); |
||
| 430 | } |
||
| 431 | |||
| 432 | /** |
||
| 433 | * Validates badges from params and turns them into an array of ItemIds. |
||
| 434 | * |
||
| 435 | * @param string[] $badges |
||
| 436 | * @param Status $status |
||
| 437 | * |
||
| 438 | * @return ItemId[]|boolean |
||
| 439 | */ |
||
| 440 | private function parseBadges( array $badges, Status $status ) { |
||
| 441 | $badgesObjects = []; |
||
| 442 | |||
| 443 | foreach ( $badges as $badge ) { |
||
| 444 | try { |
||
| 445 | $badgeId = new ItemId( $badge ); |
||
| 446 | } catch ( InvalidArgumentException $ex ) { |
||
| 447 | $status->fatal( 'wikibase-wikibaserepopage-not-itemid', $badge ); |
||
| 448 | return false; |
||
| 449 | } |
||
| 450 | |||
| 451 | if ( !array_key_exists( $badgeId->getSerialization(), $this->badgeItems ) ) { |
||
| 452 | $status->fatal( 'wikibase-setsitelink-not-badge', $badgeId->getSerialization() ); |
||
| 453 | return false; |
||
| 454 | } |
||
| 455 | |||
| 456 | $itemTitle = $this->getEntityTitle( $badgeId ); |
||
| 457 | |||
| 458 | if ( $itemTitle === null || !$itemTitle->exists() ) { |
||
| 459 | $status->fatal( 'wikibase-wikibaserepopage-invalid-id', $badgeId ); |
||
| 460 | return false; |
||
| 461 | } |
||
| 462 | |||
| 463 | $badgesObjects[] = $badgeId; |
||
| 464 | } |
||
| 465 | |||
| 466 | return $badgesObjects; |
||
| 467 | } |
||
| 468 | |||
| 469 | /** |
||
| 470 | * Setting the sitepage of the entity. |
||
| 471 | * |
||
| 472 | * @param EntityDocument $item |
||
| 473 | * @param string $siteId |
||
| 474 | * @param string $pageName |
||
| 475 | * @param string[] $badgeIds |
||
| 476 | * @param Summary|null &$summary The summary for this edit will be saved here. |
||
| 477 | * |
||
| 478 | * @throws InvalidArgumentException |
||
| 479 | * @return Status |
||
| 480 | */ |
||
| 481 | private function setSiteLink( EntityDocument $item, $siteId, $pageName, array $badgeIds, Summary &$summary = null ) { |
||
| 482 | if ( !( $item instanceof Item ) ) { |
||
| 483 | throw new InvalidArgumentException( '$entity must be an Item' ); |
||
| 484 | } |
||
| 485 | |||
| 486 | $status = Status::newGood(); |
||
| 487 | $site = $this->siteLookup->getSite( $siteId ); |
||
| 488 | |||
| 489 | if ( $site === null ) { |
||
| 490 | $status->fatal( 'wikibase-setsitelink-invalid-site', $siteId ); |
||
| 491 | return $status; |
||
| 492 | } |
||
| 493 | |||
| 494 | $summary = new Summary( 'wbsetsitelink' ); |
||
| 495 | |||
| 496 | // when $pageName is an empty string, we want to remove the site link |
||
| 497 | if ( $pageName === '' ) { |
||
| 498 | if ( !$item->hasLinkToSite( $siteId ) ) { |
||
| 499 | $status->fatal( 'wikibase-setsitelink-remove-failed' ); |
||
| 500 | return $status; |
||
| 501 | } |
||
| 502 | } else { |
||
| 503 | $pageName = $site->normalizePageName( $pageName ); |
||
| 504 | |||
| 505 | if ( $pageName === false ) { |
||
| 506 | $status->fatal( 'wikibase-error-ui-no-external-page', $siteId, $this->page ); |
||
| 507 | return $status; |
||
| 508 | } |
||
| 509 | } |
||
| 510 | |||
| 511 | $badges = $this->parseBadges( $badgeIds, $status ); |
||
| 512 | |||
| 513 | if ( !$status->isGood() ) { |
||
| 514 | return $status; |
||
| 515 | } |
||
| 516 | |||
| 517 | $changeOp = $this->siteLinkChangeOpFactory->newSetSiteLinkOp( $siteId, $pageName, $badges ); |
||
|
0 ignored issues
–
show
$badges is of type false|array, but the function expects a null|array<integer,objec...taModel\Entity\ItemId>>.
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
Loading history...
|
|||
| 518 | $this->applyChangeOp( $changeOp, $item, $summary ); |
||
| 519 | |||
| 520 | return $status; |
||
| 521 | } |
||
| 522 | |||
| 523 | } |
||
| 524 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..