2023/06/24: Difference between revisions
(Created page with "{{page/date}} ==Notes== * [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L152 ObjectFactory.php line 152] calls static::getObjectFromSpec( $spec, $options ); * [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L177 ObjectFactory.php line 177] calls static::validateSpec( $spec, $options ); * [https://github.com/wikime...") |
No edit summary |
||
(7 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{page/date}} | {{page/date}} | ||
==Notes== | ==Notes== | ||
* [https://github.com/wikimedia/mediawiki/blob/master/includes/specialpage/SpecialPageFactory.php#L1449 SpecialPageFactory.php line 1449 (was 1318)] calls $this->getPage( $name ); | |||
* [https://github.com/wikimedia/mediawiki/blob/master/includes/specialpage/SpecialPageFactory.php#L1411 SpecialPageFactory.php line 1411 (was 1283)] calls <syntaxhighlight lang=php inline>$this->objectFactory->createObject($rec,['allowClassName' => true,'allowCallable' => true]);</syntaxhighlight> | |||
** This seems to be where the problem comes in: | |||
*** $rec is supposed to be an array or a string that matches certain criteria. | |||
*** <syntaxhighlight lang=php inline>$rec = $specialPageList[$realName];</syntaxhighlight> | |||
*** <syntaxhighlight lang=php inline>[ $realName ] = $this->resolveAlias( $name );</syntaxhighlight> // extracts $realName from the first item returned (the "real name" is always first, I guess... seems a bit sloppy) | |||
* [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L152 ObjectFactory.php line 152] calls static::getObjectFromSpec( $spec, $options ); | * [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L152 ObjectFactory.php line 152] calls static::getObjectFromSpec( $spec, $options ); | ||
* [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L177 ObjectFactory.php line 177] calls static::validateSpec( $spec, $options ); | * [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L177 ObjectFactory.php line 177] calls static::validateSpec( $spec, $options ); | ||
* [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L302 ObjectFactory.php line 302] is in validateSpec( $spec, array $options ), throws exception | * [https://github.com/wikimedia/mediawiki-libs-ObjectFactory/blob/3558d6630cefa60491e468965752651bc5bf3d3e/src/ObjectFactory.php#L302 ObjectFactory.php line 302] is in validateSpec( $spec, array $options ), throws exception | ||
the problem flows like this: in <syntaxhighlight lang=php inline>this->getPage( $name );</syntaxhighlight> we have | |||
<syntaxhighlight lang=php> | |||
if ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) { | |||
$page = $this->objectFactory->createObject( $rec, [ 'allowClassName' => true,'allowCallable' => true ]); | |||
} | |||
</syntaxhighlight> | |||
...which implies that it should be perfectly okay to call createObject() with a string, but then we have <syntaxhighlight lang=php inline>createObject( $spec, array $options = [] )</syntaxhighlight> calling <syntaxhighlight lang=php inline>static::getObjectFromSpec( $spec, $options );</syntaxhighlight> which calls <syntaxhighlight lang=php inline>static::validateSpec( $spec, $options );</syntaxhighlight> which then goes: | |||
<syntaxhighlight lang=php> | |||
if ( is_string( $spec ) && class_exists( $spec ) ) { | |||
if ( empty( $options['allowClassName'] ) ) { | |||
throw new InvalidArgumentException('Passing a raw class name is not allowed here. Use [ \'class\' => $classname ] instead.'); | |||
} | |||
return [ 'class' => $spec ]; | |||
} | |||
if ( !is_array( $spec ) ) { | |||
throw new InvalidArgumentException( 'Provided specification is not an array.' ); | |||
} | |||
</syntaxhighlight> | |||
...so I ''think'' what I'm getting from that is that it's only okay to call <syntaxhighlight lang=php inline>$this->objectFactory->createObject( $rec, /*...*/ )</syntaxhighlight> if <tt>$rec</tt> is ''not'' a class name. | |||
So then we have the questions: | |||
* '''Q1''': From where is the string-value of <tt>$rec</tt> being retrieved? | |||
** The list comes from <syntaxhighlight lang=php inline>$this->getPageList()</syntaxhighlight> | |||
** ...and how that list is generated is... Complicated. | |||
** ...but there's a wide variety of examples, when CORE_LIST is defined near the top of the class, of what the array entries are supposed to look like. | |||
** '''Q1a''': So, somehow our SpecialPage class gets added to the list as just a string. Where does that happen? Presumably in [[SpecialPage]]'s constructor... | |||
*** Nope, not there; that just initializes the SpecialPage object's members. Presumably the class is registered by whatever reads the <tt>extension.json</tt> file. | |||
*** '''Q1a1''': How are extension pages loaded? | |||
* '''Q2''': What is it ''supposed'' to be, if it's not a class name? | |||
I don't know the answer to the above questions, but I did solve the problem: as implied on {{l/mw|Manual:Special_pages}}, the filename ''must'' match the class name -- so it can't be just <tt>Special.php</tt>, it has to be <tt>SpecialClassInspector.php</tt>. (Maybe there's some configuration detail you can put in <tt>extension.json</tt> to override this, but I don't currently know what that is if it exists.) | |||
'''2023-07-09 update''': I got this same error again -- this time because of a namespace change. Fixing the extension.json file to have the correct namespace fixed the problem. I conclude (from these two data-points) that this error indicates that the class of the SpecialPage does not match the class referenced in extension.json. |
Latest revision as of 13:26, 9 July 2023
Saturday, June 24, 2023 (#175)
|
Notes
the problem flows like this: in if ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) {
$page = $this->objectFactory->createObject( $rec, [ 'allowClassName' => true,'allowCallable' => true ]);
}
...which implies that it should be perfectly okay to call createObject() with a string, but then we have if ( is_string( $spec ) && class_exists( $spec ) ) {
if ( empty( $options['allowClassName'] ) ) {
throw new InvalidArgumentException('Passing a raw class name is not allowed here. Use [ \'class\' => $classname ] instead.');
}
return [ 'class' => $spec ];
}
if ( !is_array( $spec ) ) {
throw new InvalidArgumentException( 'Provided specification is not an array.' );
}
...so I think what I'm getting from that is that it's only okay to call So then we have the questions:
I don't know the answer to the above questions, but I did solve the problem: as implied on Manual:Special_pages, the filename must match the class name -- so it can't be just Special.php, it has to be SpecialClassInspector.php. (Maybe there's some configuration detail you can put in extension.json to override this, but I don't currently know what that is if it exists.) 2023-07-09 update: I got this same error again -- this time because of a namespace change. Fixing the extension.json file to have the correct namespace fixed the problem. I conclude (from these two data-points) that this error indicates that the class of the SpecialPage does not match the class referenced in extension.json. |