Daniel Kinzler has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/358423 )
Change subject: Add Title::isValid method. ...................................................................... Add Title::isValid method. Make the notion of Title objects representing invalid titles explicit. Bug: T165149 Change-Id: I89aaabdff9614fe63bd1244784a1d677dbc26f9e --- M includes/Title.php M tests/phpunit/includes/TitleTest.php 2 files changed, 78 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core refs/changes/23/358423/1 diff --git a/includes/Title.php b/includes/Title.php index d34da7d..6e9c32c 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -253,6 +253,9 @@ * Create a new Title from text, such as what one would find in a link. De- * codes any HTML entities in the text. * + * Title objects returned by this method are guaranteed to be valid, and + * thus return true from the isValid() method. + * * @param string|int|null $text The link text; spaces, prefixes, and an * initial ':' indicating the main namespace are accepted. * @param int $defaultNamespace The namespace to use if none is specified @@ -283,6 +286,9 @@ * rather than returning null. * * The exception subclasses encode detailed information about why the title is invalid. + * + * Title objects returned by this method are guaranteed to be valid, and + * thus return true from the isValid() method. * * @see Title::newFromText * @@ -500,10 +506,19 @@ /** * Create a new Title from a namespace index and a DB key. - * It's assumed that $ns and $title are *valid*, for instance when - * they came directly from the database or a special page name. - * For convenience, spaces are converted to underscores so that - * eg user_text fields can be used directly. + * + * It's assumed that $ns and $title are safe, for instance when + * they came directly from the database or a special page name, + * not from user input. + * + * To validation is applied. For convenience, spaces are normalized + * to underscores, so that e.g. user_text fields can be used directly. + * + * @note This method may return Title objects that are "invalid" + * according to the isValid() method. This is usually caused by + * configuration changes: e.g. a namespace that was once defined is + * no longer configured, or a character that was once allowed in + * titles is now forbidden. * * @param int $ns The namespace of the article * @param string $title The unprefixed database key form @@ -529,6 +544,10 @@ * The parameters will be checked for validity, which is a bit slower * than makeTitle() but safer for user-provided data. * + * Title objects returned by makeTitleSafe() are guaranteed to be valid, + * that is, they return true from the isValid() method. If no valid Title + * can be constructed from the input, this method returns null. + * * @param int $ns The namespace of the article * @param string $title Database key form * @param string $fragment The link fragment (after the "#") @@ -536,6 +555,9 @@ * @return Title|null The new object, or null on an error */ public static function makeTitleSafe( $ns, $title, $fragment = '', $interwiki = '' ) { + // NOTE: ideally, this would just call makeTitle() and then isValid(), + // but presently, that means more overhead on a potential performance hotspot. + if ( !MWNamespace::exists( $ns ) ) { return null; } @@ -776,6 +798,36 @@ } /** + * Returns true if the title is valid, false if it is invalid. + * + * Valid titles can be round-tripped via makeTitleSafe() and newFromText(). + * Invalid titles may get returned from makeTitle(), and it may be useful to + * allow them to exist, e.g. in order to process log entries about pages in + * namespaces that belong to extensions that are no longer installed. + * + * @note that this method is relatively expensive. When constructing Title + * objects that need to be valid, use an instantiator method that is guaranteed + * to return valid titles, such as makeTitleSafe() or newFromText(). + * + * @return bool + */ + public function isValid() { + $ns = $this->getNamespace(); + + if ( !MWNamespace::exists( $ns ) ) { + return false; + } + + try { + $parser = MediaWikiServices::getInstance()->getTitleParser(); + $parser->parseTitle( $this->getDBkey(), $ns ); + return true; + } catch ( MalformedTitleException $ex ) { + return false; + } + } + + /** * Determine whether the object refers to a page within * this project (either this wiki or a wiki with a local * interwiki, see https://www.mediawiki.org/wiki/Manual:Interwiki_table#iw_local ) diff --git a/tests/phpunit/includes/TitleTest.php b/tests/phpunit/includes/TitleTest.php index 6c44999..1dc5205 100644 --- a/tests/phpunit/includes/TitleTest.php +++ b/tests/phpunit/includes/TitleTest.php @@ -638,6 +638,28 @@ } /** + * @covers Title::isValid + * @dataProvider provideIsValid + * @param Title $title + * @param bool $isValid + */ + public function testIsValid( Title $title, $isValid ) { + $this->assertEquals( $isValid, $title->isValid(), $title->getPrefixedText() ); + } + + public static function provideIsValid() { + return [ + [ Title::makeTitle( NS_MAIN, '' ), false ], + [ Title::makeTitle( NS_MAIN, '<>' ), false ], + [ Title::makeTitle( NS_MAIN, '|' ), false ], + [ Title::makeTitle( NS_MAIN, '#' ), false ], + [ Title::makeTitle( NS_MAIN, 'Test' ), true ], + [ Title::makeTitle( -33, 'Test' ), false ], + [ Title::makeTitle( 77663399, 'Test' ), false ], + ]; + } + + /** * @covers Title::isAlwaysKnown */ public function testIsAlwaysKnownOnInterwiki() { -- To view, visit https://gerrit.wikimedia.org/r/358423 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I89aaabdff9614fe63bd1244784a1d677dbc26f9e Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/core Gerrit-Branch: master Gerrit-Owner: Daniel Kinzler <daniel.kinz...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits