Sumit has uploaded a new change for review. https://gerrit.wikimedia.org/r/229389
Change subject: WikidataPageBanner hygiene - move non-hook methods ...................................................................... WikidataPageBanner hygiene - move non-hook methods Move non-hook functions from WikidataPageBanner.hooks.php to WikidataPageBanner.functions.php. Add a static variable $wpbFunctionsObj which stores the classname of functions class and which is used to call functions of that class. This variable is being added to facilitate injecting a mock classname while performing tests. Modify tests. Bug: T107755 Change-Id: I16ef2db74f34f122f83b3ace86c8b5edd17c3674 --- M includes/WikidataPageBanner.functions.php M includes/WikidataPageBanner.hooks.php M tests/phpunit/BannerOptionsTest.php M tests/phpunit/BannerTest.php 4 files changed, 210 insertions(+), 170 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikidataPageBanner refs/changes/89/229389/1 diff --git a/includes/WikidataPageBanner.functions.php b/includes/WikidataPageBanner.functions.php index fd059c2..f510189 100644 --- a/includes/WikidataPageBanner.functions.php +++ b/includes/WikidataPageBanner.functions.php @@ -44,4 +44,161 @@ } } } + + /** + * Converts an array of values in form [0] => "name=value" into a real + * associative array in form [name] => value + * + * @param array string[] $options + * @return array $results + */ + public static function extractOptions( array $options ) { + $results = array(); + foreach ( $options as $option ) { + $pair = explode( '=', $option, 2 ); + if ( count( $pair ) == 2 ) { + $name = trim( $pair[0] ); + $value = trim( $pair[1] ); + $results[$name] = $value; + } + } + return $results; + } + + /** + * WikidataPageBanner::getBannerHtml + * Returns the html code for the pagebanner + * + * @param string $bannername FileName of banner image + * @param array $options additional parameters passed to template + * @return string|null Html code of the banner or null if invalid bannername + */ + public static function getBannerHtml( $bannername, $options = array() ) { + global $wgWPBStandardSizes; + $urls = static::getStandardSizeUrls( $bannername ); + $banner = null; + /** @var String srcset attribute for <img> element of banner image */ + $srcset = array(); + // if a valid bannername given, set banner + if ( !empty( $urls ) ) { + // @var int index variable + $i = 0; + foreach ( $urls as $url ) { + $size = $wgWPBStandardSizes[$i]; + // add url with width and a comma if not adding the last url + if ( $i < count( $urls ) ) { + $srcset[] = "$url {$size}w"; + } + $i++; + } + // create full src set from individual urls, separated by comma + $srcset = implode( ',', $srcset ); + // use largest image url as src attribute + $bannerurl = $urls[count( $urls ) - 1]; + $bannerfile = Title::newFromText( "File:$bannername" ); + $templateParser = new TemplateParser( __DIR__ . '/../templates' ); + $options['bannerfile'] = $bannerfile->getLocalUrl(); + $options['banner'] = $bannerurl; + $options['srcset'] = $srcset; + $banner = $templateParser->processTemplate( + 'banner', + $options + ); + } + return $banner; + } + + /** + * WikidataPageBanner::getImageUrl + * Return the full url of the banner image, stored on the wiki, given the + * image name. Additionally, if a width parameter is specified, it creates + * and returns url of an image of specified width. + * + * @param string $filename Filename of the banner image + * @return string|null Full url of the banner image on the wiki or null + */ + public static function getImageUrl( $filename, $imagewidth = null ) { + // make title object from image name + $title = Title::makeTitleSafe( NS_IMAGE, $filename ); + $file = wfFindFile( $title ); + $options = array( + 'options' => array( 'min_range' => 0, 'max_range' => 3000 ) + ); + // if file not found, return null + if ( $file == null ) { + return null; + } + // validate $bannerwidth to be a width within 3000 + elseif ( filter_var( $imagewidth, FILTER_VALIDATE_INT, $options ) !== false ) { + $mto = $file->transform( array( 'width' => $imagewidth ) ); + $url = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT ); + return $url; + } else { + // return image without transforming, if width not valid + return $file->getFullUrl(); + } + } + + /** + * WikidataPageBanner::getStandardSizeUrls + * returns an array of urls of standard image sizes defined by $wgWPBStandardSizes + * + * @param String $filename Name of Image file + * @return array + */ + public static function getStandardSizeUrls( $filename ) { + global $wgWPBStandardSizes; + $urlSet = array(); + foreach ( $wgWPBStandardSizes as $size ) { + $url = static::getImageUrl( $filename, $size ); + // prevent duplication in urlSet + if ( $url !== null && !in_array( $url, $urlSet, true ) ) { + $urlSet[] = $url; + } + } + return $urlSet; + } + + /** + * WikidataPageBanner::getWikidataBanner Fetches banner from wikidata for the specified page + * + * @param Title $title Title of the page + * @return String|null file name of the banner from wikidata + * or null if none found + */ + public static function getWikidataBanner( $title ) { + global $wgWPBBannerProperty; + $banner = null; + if ( empty( $wgWPBBannerProperty ) ) { + return null; + } + // Ensure Wikibase client is installed + if ( class_exists( 'Wikibase\Client\WikibaseClient' ) ) { + $entityIdLookup = Wikibase\Client\WikibaseClient::getDefaultInstance() + ->getStore() + ->getEntityIdLookup(); + $itemId = $entityIdLookup->getEntityIdForTitle( $title ); + // check if this page has an associated item page + $entityLookup = Wikibase\Client\WikibaseClient::getDefaultInstance() + ->getStore() + ->getEntityLookup(); + /** @var Wikibase\DataModel\Entity\Item $item */ + if ( $itemId != null ) { + $item = $entityLookup->getEntity( $itemId ); + $statements = $item->getStatements()->getByPropertyId( + new Wikibase\DataModel\Entity\PropertyId( + $wgWPBBannerProperty + ) + )->getBestStatements(); + if ( !$statements->isEmpty() ) { + $statements = $statements->toArray(); + $snak = $statements[0]->getMainSnak(); + if ( $snak instanceof Wikibase\DataModel\Snak\PropertyValueSnak ) { + $banner = $snak->getDataValue()->getValue(); + } + } + } + } + return $banner; + } } diff --git a/includes/WikidataPageBanner.hooks.php b/includes/WikidataPageBanner.hooks.php index 6465701..f57c3b9 100644 --- a/includes/WikidataPageBanner.hooks.php +++ b/includes/WikidataPageBanner.hooks.php @@ -1,6 +1,16 @@ <?php class WikidataPageBanner { /** + * Singleton instance for helper class functions + * This variable holds the class name for helper functions and is used to make calls to those + * functions + * Note that this variable is also used by tests to store a mock object of helper functions + * in it externally + * @var Object WikidataPageBannerFunctions + */ + static $wpbFunctionsObj; + + /** * WikidataPageBanner::addBanner Generates banner from given options and adds it and its styles * to Output Page. If no options defined through {{PAGEBANNER}}, tries to add a wikidata banner * or a default one. @@ -17,11 +27,12 @@ $params = $out->getProperty( 'wpb-banner-options' ); $bannername = $params['name']; $out->enableOOUI(); - $banner = static::getBannerHtml( $bannername, $params ); + $WPBFunctionsInstance = self::getWPBFunctionsInstance(); + $banner = $WPBFunctionsInstance::getBannerHtml( $bannername, $params ); // attempt to get WikidataBanner if ( $banner === null ) { - $bannername = static::getWikidataBanner( $title ); - $banner = static::getBannerHtml( $bannername, $params ); + $bannername = $WPBFunctionsInstance::getWikidataBanner( $title ); + $banner = $WPBFunctionsInstance::getBannerHtml( $bannername, $params ); } // only add banner and styling if valid banner generated if ( $banner !== null ) { @@ -45,14 +56,16 @@ if ( in_array( $ns, $wgWPBNamespaces ) && !$title->isMainPage() ) { // first try to obtain bannername from Wikidata - $bannername = static::getWikidataBanner( $title ); + $WPBFunctionsInstance = self::getWPBFunctionsInstance(); + $bannername = $WPBFunctionsInstance::getWikidataBanner( $title ); if ( $bannername === null ) { // if Wikidata banner not found, set bannername to default banner $bannername = $wgWPBImage; } // add title to template parameters $paramsForBannerTemplate = array( 'title' => $title ); - $banner = static::getBannerHtml( $bannername, $paramsForBannerTemplate ); + $banner = $WPBFunctionsInstance:: + getBannerHtml( $bannername, $paramsForBannerTemplate ); // only add banner and styling if valid banner generated if ( $banner !== null ) { $out->addModuleStyles( 'ext.WikidataPageBanner' ); @@ -117,7 +130,9 @@ // skip parser function name and bannername in arguments $argumentsFromParserFunction = array_slice( func_get_args(), 2 ); // Convert $argumentsFromParserFunction into an associative array - $argumentsFromParserFunction = self::extractOptions( $argumentsFromParserFunction ); + $WPBFunctionsInstance = self::getWPBFunctionsInstance(); + $argumentsFromParserFunction = $WPBFunctionsInstance:: + extractOptions( $argumentsFromParserFunction ); // if given banner does not exist, return $banner = ''; $title = $parser->getTitle(); @@ -151,79 +166,7 @@ } } - /** - * WikidataPageBanner::getImageUrl - * Return the full url of the banner image, stored on the wiki, given the - * image name. Additionally, if a width parameter is specified, it creates - * and returns url of an image of specified width. - * - * @param string $filename Filename of the banner image - * @return string|null Full url of the banner image on the wiki or null - */ - public static function getImageUrl( $filename, $imagewidth = null ) { - // make title object from image name - $title = Title::makeTitleSafe( NS_IMAGE, $filename ); - $file = wfFindFile( $title ); - $options = array( - 'options' => array( 'min_range' => 0, 'max_range' => 3000 ) - ); - // if file not found, return null - if ( $file == null ) { - return null; - } - // validate $bannerwidth to be a width within 3000 - elseif ( filter_var( $imagewidth, FILTER_VALIDATE_INT, $options ) !== false ) { - $mto = $file->transform( array( 'width' => $imagewidth ) ); - $url = wfExpandUrl( $mto->getUrl(), PROTO_CURRENT ); - return $url; - } else { - // return image without transforming, if width not valid - return $file->getFullUrl(); - } - } - /** - * WikidataPageBanner::getBannerHtml - * Returns the html code for the pagebanner - * - * @param string $bannername FileName of banner image - * @param array $options additional parameters passed to template - * @return string|null Html code of the banner or null if invalid bannername - */ - public static function getBannerHtml( $bannername, $options = array() ) { - global $wgWPBStandardSizes; - $urls = static::getStandardSizeUrls( $bannername ); - $banner = null; - /** @var String srcset attribute for <img> element of banner image */ - $srcset = array(); - // if a valid bannername given, set banner - if ( !empty( $urls ) ) { - // @var int index variable - $i = 0; - foreach ( $urls as $url ) { - $size = $wgWPBStandardSizes[$i]; - // add url with width and a comma if not adding the last url - if ( $i < count( $urls ) ) { - $srcset[] = "$url {$size}w"; - } - $i++; - } - // create full src set from individual urls, separated by comma - $srcset = implode( ',', $srcset ); - // use largest image url as src attribute - $bannerurl = $urls[count( $urls ) - 1]; - $bannerfile = Title::newFromText( "File:$bannername" ); - $templateParser = new TemplateParser( __DIR__ . '/../templates' ); - $options['bannerfile'] = $bannerfile->getLocalUrl(); - $options['banner'] = $bannerurl; - $options['srcset'] = $srcset; - $banner = $templateParser->processTemplate( - 'banner', - $options - ); - } - return $banner; - } /** * WikidataPageBanner::onParserFirstCallInit @@ -235,89 +178,6 @@ public static function onParserFirstCallInit( $parser ) { $parser->setFunctionHook( 'PAGEBANNER', 'WikidataPageBanner::addCustomBanner', SFH_NO_HASH ); return true; - } - - /** - * WikidataPageBanner::getStandardSizeUrls - * returns an array of urls of standard image sizes defined by $wgWPBStandardSizes - * - * @param String $filename Name of Image file - * @return array - */ - public static function getStandardSizeUrls( $filename ) { - global $wgWPBStandardSizes; - $urlSet = array(); - foreach ( $wgWPBStandardSizes as $size ) { - $url = static::getImageUrl( $filename, $size ); - // prevent duplication in urlSet - if ( $url !== null && !in_array( $url, $urlSet, true ) ) { - $urlSet[] = $url; - } - } - return $urlSet; - } - - /** - * WikidataPageBanner::getWikidataBanner Fetches banner from wikidata for the specified page - * - * @param Title $title Title of the page - * @return String|null file name of the banner from wikidata - * or null if none found - */ - public static function getWikidataBanner( $title ) { - global $wgWPBBannerProperty; - $banner = null; - if ( empty( $wgWPBBannerProperty ) ) { - return null; - } - // Ensure Wikibase client is installed - if ( class_exists( 'Wikibase\Client\WikibaseClient' ) ) { - $entityIdLookup = Wikibase\Client\WikibaseClient::getDefaultInstance() - ->getStore() - ->getEntityIdLookup(); - $itemId = $entityIdLookup->getEntityIdForTitle( $title ); - // check if this page has an associated item page - $entityLookup = Wikibase\Client\WikibaseClient::getDefaultInstance() - ->getStore() - ->getEntityLookup(); - /** @var Wikibase\DataModel\Entity\Item $item */ - if ( $itemId != null ) { - $item = $entityLookup->getEntity( $itemId ); - $statements = $item->getStatements()->getByPropertyId( - new Wikibase\DataModel\Entity\PropertyId( - $wgWPBBannerProperty - ) - )->getBestStatements(); - if ( !$statements->isEmpty() ) { - $statements = $statements->toArray(); - $snak = $statements[0]->getMainSnak(); - if ( $snak instanceof Wikibase\DataModel\Snak\PropertyValueSnak ) { - $banner = $snak->getDataValue()->getValue(); - } - } - } - } - return $banner; - } - - /** - * Converts an array of values in form [0] => "name=value" into a real - * associative array in form [name] => value - * - * @param array string[] $options - * @return array $results - */ - public static function extractOptions( array $options ) { - $results = array(); - foreach ( $options as $option ) { - $pair = explode( '=', $option, 2 ); - if ( count( $pair ) == 2 ) { - $name = trim( $pair[0] ); - $value = trim( $pair[1] ); - $results[$name] = $value; - } - } - return $results; } /* @@ -338,4 +198,17 @@ } return true; } + + /** + * Sets the WikidataPageBannerFunctions class name on $wpbFunctionsObj if not set and returns it + * @return string Class name of helper functions + */ + public static function getWPBFunctionsInstance() { + if ( !isset( self::$wpbFunctionsObj ) ) { + // assign classname WikidataPageBannerFunctions + // Note that this varaible is assigned a mock classname inside tests externally + self::$wpbFunctionsObj = "WikidataPageBannerFunctions"; + } + return self::$wpbFunctionsObj; + } } diff --git a/tests/phpunit/BannerOptionsTest.php b/tests/phpunit/BannerOptionsTest.php index d90e636..8c0a046 100644 --- a/tests/phpunit/BannerOptionsTest.php +++ b/tests/phpunit/BannerOptionsTest.php @@ -7,7 +7,7 @@ * Test for validating options passed to {{PAGEBANNER}} function * Mock class for WikidataPageBannerOptions */ -class MockWikidataPageBannerOptions extends WikidataPageBanner { +class MockWikidataPageBannerOptions extends WikidataPageBannerFunctions { public static function getBannerHtml( $bannername, $options = array() ) { return $options; } @@ -38,9 +38,12 @@ * @covers addCustomBanner(...) */ public function testBannerOptions() { + // store a mock class name in $wpbFunctionsObj static variable so that hooks call mock + // functions through this variable when performing tests + WikidataPageBanner::$wpbFunctionsObj = "MockWikidataPageBannerOptions"; $parser = $this->createParser( 'BannerWithOptions', NS_MAIN ); - MockWikidataPageBannerOptions::addCustomBanner( $parser, 'Banner1' ); + WikidataPageBanner::addCustomBanner( $parser, 'Banner1' ); $pOut = $parser->getOutput(); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertEquals( $bannerparams['title'], 'BannerWithOptions', @@ -49,7 +52,7 @@ 'tooltip must be set to title' ); $pOut->setProperty( 'wpb-banner-options', null ); - MockWikidataPageBannerOptions::addCustomBanner( $parser, 'Banner1', + WikidataPageBanner::addCustomBanner( $parser, 'Banner1', 'pgname=Banner2' ); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertEquals( $bannerparams['title'], 'Banner2', @@ -58,7 +61,7 @@ 'tooltip must be set to pgname' ); $pOut->setProperty( 'wpb-banner-options', null ); - MockWikidataPageBannerOptions::addCustomBanner( $parser, 'Banner1', + WikidataPageBanner::addCustomBanner( $parser, 'Banner1', 'pgname=Banner2', 'tooltip=hovertext' ); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertEquals( $bannerparams['title'], 'Banner2', @@ -67,7 +70,7 @@ 'pgname must be set' ); $pOut->setProperty( 'wpb-banner-options', null ); - $output = MockWikidataPageBannerOptions::addCustomBanner( $parser, 'Banner1', + $output = WikidataPageBanner::addCustomBanner( $parser, 'Banner1', 'pgname=Banner2', 'icons=unesco,star' ); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertEquals( $bannerparams['title'], 'Banner2', diff --git a/tests/phpunit/BannerTest.php b/tests/phpunit/BannerTest.php index 0b62ac5..637242c 100644 --- a/tests/phpunit/BannerTest.php +++ b/tests/phpunit/BannerTest.php @@ -6,7 +6,7 @@ /** * Mock class for WikidataPageBanner */ -class MockWikidataPageBanner extends WikidataPageBanner { +class MockWikidataPageBannerFunctions extends WikidataPageBannerFunctions { public static function getBannerHtml( $bannername, $options = array() ) { if ( $bannername == 'NoBanner' ) { return null; @@ -70,7 +70,10 @@ */ public function testDefaultBanner( $title, $ns, $customBanner, $expected ) { $out = $this->createPage( $title, $ns, $customBanner ); - MockWikidataPageBanner::addBanner( $out, null ); + // store a mock object in $wpbFunctionsObj static variable so that hooks call mock functions + // through this variable when performing tests + WikidataPageBanner::$wpbFunctionsObj = "MockWikidataPageBannerFunctions"; + WikidataPageBanner::addBanner( $out, null ); $this->assertEquals( $out->getProperty( 'articlebanner' ), $expected, 'articlebanner property must only be set when a valid banner is added' ); } @@ -80,14 +83,18 @@ */ public function testCustomBanner() { $parser = $this->createParser( 'PageWithCustomBanner', NS_MAIN ); - $output = MockWikidataPageBanner::addCustomBanner( $parser, 'Banner' ); + // store a mock class name in $wpbFunctionsObj static variable so that hooks call mock + // functions through this variable when performing tests + WikidataPageBanner::$wpbFunctionsObj = "MockWikidataPageBannerFunctions"; + $output = WikidataPageBanner::addCustomBanner( $parser, 'Banner' ); $pOut = $parser->getOutput(); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertEquals( $bannerparams['name'], 'Banner', 'banner parameters must be set on valid namespaces' ); $parser = $this->createParser( 'PageInTalkNamespace', NS_TALK ); - $output = MockWikidataPageBanner::addCustomBanner( $parser, 'Banner' ); + WikidataPageBanner::$wpbFunctionsObj = "MockWikidataPageBannerFunctions"; + $output = WikidataPageBanner::addCustomBanner( $parser, 'Banner' ); $pOut = $parser->getOutput(); $bannerparams = $pOut->getProperty( 'wpb-banner-options' ); $this->assertFalse( $bannerparams, 'Banner', -- To view, visit https://gerrit.wikimedia.org/r/229389 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I16ef2db74f34f122f83b3ace86c8b5edd17c3674 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/WikidataPageBanner Gerrit-Branch: master Gerrit-Owner: Sumit <asthana.sumi...@gmail.com> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits