Aude has uploaded a new change for review. https://gerrit.wikimedia.org/r/171528
Change subject: Implement EntityParserOutputGeneratorFactory ...................................................................... Implement EntityParserOutputGeneratorFactory allows removing a lot of cruft from EntityContent attempts to address some of the issues in Ic06639c approach, or perhaps can rebase on top of that. Change-Id: I9453fd95eb7af8f34e7dbe18bd159b8bcb1927f7 --- M lib/includes/LanguageFallbackChainFactory.php A repo/includes/View/EntityParserOutputGeneratorFactory.php M repo/includes/WikibaseRepo.php M repo/includes/content/EntityContent.php M repo/includes/content/ItemContent.php M repo/includes/content/PropertyContent.php 6 files changed, 298 insertions(+), 209 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/28/171528/2 diff --git a/lib/includes/LanguageFallbackChainFactory.php b/lib/includes/LanguageFallbackChainFactory.php index b653da7..eee471f 100644 --- a/lib/includes/LanguageFallbackChainFactory.php +++ b/lib/includes/LanguageFallbackChainFactory.php @@ -349,20 +349,31 @@ * @return LanguageFallbackChain */ public function newFromContextForPageView( IContextSource $context ) { + return $this->newFromUserAndLanguageCodeForPageView( + $context->getUser(), + $context->getLanguage()->getCode() + ); + } + + /** + * @param User $user + * @param string $languageCode + * + * @return LanguageFallbackChain + */ + public function newFromUserAndLanguageCodeForPageView( User $user, $languageCode ) { if ( $this->isExperimentalMode ) { // The generated chain should yield a cacheable result - if ( $this->anonymousPageViewCached && $context->getUser()->isAnon() ) { + if ( $this->anonymousPageViewCached && $user->isAnon() ) { // Anonymous users share the same Squid cache, which is splitted by URL. - // That means we can't do anything except for what completely depends by URL such as &uselang=. - return $this->newFromLanguage( $context->getLanguage() ); + // That means we can't do anything except for what completely depends + // by URL such as &uselang=. + return $this->newFromLanguageCode( $languageCode ); } - return $this->newFromContext( $context ); + return $this->newFromUserAndLanguageCode( $user, $languageCode ); } else { - return $this->newFromLanguage( - $context->getLanguage(), - self::FALLBACK_SELF - ); + return $this->newFromLanguageCode( $languageCode, self::FALLBACK_SELF ); } } diff --git a/repo/includes/View/EntityParserOutputGeneratorFactory.php b/repo/includes/View/EntityParserOutputGeneratorFactory.php new file mode 100644 index 0000000..455d435 --- /dev/null +++ b/repo/includes/View/EntityParserOutputGeneratorFactory.php @@ -0,0 +1,242 @@ +<?php + +namespace Wikibase; + +use IContextSource; +use Language; +use ParserOptions; +use ParserOutput; +use RequestContext; +use User; +use ValueFormatters\FormatterOptions; +use ValueFormatters\ValueFormatter; +use Wikibase\DataModel\Entity\Entity; +use Wikibase\DataModel\Entity\EntityId; +use Wikibase\DataModel\Entity\EntityIdParser; +use Wikibase\DataModel\Entity\PropertyDataTypeLookup; +use Wikibase\LanguageFallbackChainFactory; +use Wikibase\Lib\OutputFormatSnakFormatterFactory; +use Wikibase\Lib\Serializers\SerializationOptions; +use Wikibase\Lib\SnakFormatter; +use Wikibase\Lib\Store\EntityInfoBuilderFactory; +use Wikibase\Lib\Store\EntityTitleLookup; +use Wikibase\Repo\View\ClaimsView; +use Wikibase\Repo\View\FingerprintView; +use Wikibase\Repo\View\SectionEditLinkGenerator; +use Wikibase\Repo\View\SnakHtmlGenerator; +use Wikibase\Repo\WikibaseRepo; + +/** + * @since 0.5 + * + * @licence GNU GPL v2+ + * @author Katie Filbert < aude.w...@gmail.com > + */ +class EntityParserOutputGeneratorFactory { + + /** + * @var OutputFormatSnakFormatterFactory + */ + private $snakFormatterFactory; + + /** + * @var EntityInfoBuilderFactory + */ + private $entityInfoBuilderFactory; + + /** + * @var EntityTitleLookup + */ + private $entityTitleLookup; + + /** + * @var EntityIdParser + */ + private $entityIdParser; + + /** + * @var PropertyDataTypeLookup + */ + private $propertyDataTypeLookup; + + /** + * @var LanguageFallbackChainFactory + */ + private $languageFallbackChainFactory; + + /** + * @var ReferencedEntitiesFinder + */ + private $referencedEntitiesFinder; + + /** + * @var SectionEditLinkGenerator + */ + private $sectionEditLinkGenerator; + + public function __construct( + OutputFormatSnakFormatterFactory $snakFormatterFactory, + EntityInfoBuilderFactory $entityInfoBuilderFactory, + EntityTitleLookup $entityTitleLookup, + EntityIdParser $entityIdParser, + PropertyDataTypeLookup $propertyDataTypeLookup, + LanguageFallbackChainFactory $languageFallbackChainFactory, + ReferencedEntitiesFinder $referencedEntitiesFinder + ) { + $this->snakFormatterFactory = $snakFormatterFactory; + $this->entityInfoBuilderFactory = $entityInfoBuilderFactory; + $this->entityTitleLookup = $entityTitleLookup; + $this->entityIdParser = $entityIdParser; + $this->propertyDataTypeLookup = $propertyDataTypeLookup; + $this->languageFallbackChainFactory = $languageFallbackChainFactory; + $this->referencedEntitiesFinder = $referencedEntitiesFinder; + $this->sectionEditLinkGenerator = new SectionEditLinkGenerator(); + } + + /** + * Creates an EntityParserOutputGenerator to create the ParserOutput for the entity + * + * @param EntityRevision $entityRevision + * @param LanguageFallbackChain $languageFallbackChain + * @param ParserOptions|null $options + * + * @return EntityParserOutputGenerator + */ + public function getEntityParserOutputGenerator( + EntityRevision $entityRevision, + ParserOptions $options = null + ) { + $languageCode = $this->getLanguageCode( $options ); + + return $this->newEntityParserOutputGenerator( $entityRevision, $languageCode ); + } + + private function getSnakFormatter( $languageCode ) { + $formatterOptions = new FormatterOptions(); + $formatterOptions->setOption( ValueFormatter::OPT_LANG, $languageCode ); + + // @fixme don't get fallback chain twice and it's also probably not needed here. + $languageFallbackChain = $this->getLanguageFallbackChain( $languageCode ); + $formatterOptions->setOption( 'languages', $languageFallbackChain ); + + return $this->snakFormatterFactory->getSnakFormatter( + SnakFormatter::FORMAT_HTML_WIDGET, + $formatterOptions + ); + } + + private function newParserOutputJsConfigBuilder( $languageCode ) { + return new ParserOutputJsConfigBuilder( + $this->entityInfoBuilderFactory, + $this->entityIdParser, + $this->entityTitleLookup, + $this->referencedEntitiesFinder, + $languageCode + ); + } + + private function newEntityParserOutputGenerator( + EntityRevision $entityRevision, + $languageCode + ) { + return new EntityParserOutputGenerator( + $this->newEntityView( $entityRevision, $languageCode ), + $this->newParserOutputJsConfigBuilder( $languageCode ), + $this->makeSerializationOptions( $languageCode ), + $this->entityTitleLookup, + $this->propertyDataTypeLookup + ); + } + + private function getLanguageCode( ParserOptions $options = null ) { + $context = RequestContext::getMain(); + + // NOTE: Parser Options language overrides context language! + if ( $options !== null ) { + $languageCode = $options->getUserLang(); + } else { + $languageCode = $context->getLanguage()->getCode(); + } + + return $languageCode; + } + + private function newClaimsView( $languageCode ) { + $snakHtmlGenerator = new SnakHtmlGenerator( + $this->getSnakFormatter( $languageCode ), + $this->entityTitleLookup + ); + + $claimHtmlGenerator = new ClaimHtmlGenerator( + $snakHtmlGenerator, + $this->entityTitleLookup + ); + + return new ClaimsView( + $this->entityInfoBuilderFactory, + $this->entityTitleLookup, + $this->sectionEditLinkGenerator, + $claimHtmlGenerator, + $languageCode + ); + } + + private function newFingerprintView( $languageCode ) { + return new FingerprintView( + $this->sectionEditLinkGenerator, + $languageCode + ); + } + + /** + * Creates an EntityView suitable for rendering the entity. + * + * @param EntityRevision $entityRevision + * @param string $languageCode + * + * @return EntityView + */ + private function newEntityView( EntityRevision $entityRevision, $languageCode ) { + $fingerprintView = $this->newFingerprintView( $languageCode ); + $claimsView = $this->newClaimsView( $languageCode ); + $entityType = $entityRevision->getEntity()->getType(); + + // @fixme all that seems needed in EntityView is language code and dir. + $language = Language::factory( $languageCode ); + + // @fixme support more entity types + if ( $entityType === 'item' ) { + return new ItemView( $fingerprintView, $claimsView, $language ); + } elseif ( $entityType === 'property' ) { + return new PropertyView( $fingerprintView, $claimsView, $language ); + } + + throw new InvalidArgumentException( 'No EntityView for entity type: ' . $entityType ); + } + + private function getLanguageFallbackChain( $languageCode ) { + // @fixme inject User + $context = RequestContext::getMain(); + + return $this->languageFallbackChainFactory->newFromUserAndLanguageCodeForPageView( + $context->getUser(), + $languageCode + ); + } + + /** + * @param string $languageCode + * + * @return SerializationOptions + */ + private function makeSerializationOptions( $languageCode ) { + $fallbackChain = $this->getLanguageFallbackChain( $languageCode ); + $languageCodes = Utils::getLanguageCodes() + array( $languageCode => $fallbackChain ); + + $options = new SerializationOptions(); + $options->setLanguages( $languageCodes ); + + return $options; + } + +} diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php index 0933a16..654eee5 100644 --- a/repo/includes/WikibaseRepo.php +++ b/repo/includes/WikibaseRepo.php @@ -23,6 +23,7 @@ use Wikibase\DataModel\Entity\Item; use Wikibase\DataModel\Entity\Property; use Wikibase\EntityFactory; +use Wikibase\EntityParserOutputGeneratorFactory; use Wikibase\InternalSerialization\DeserializerFactory; use Wikibase\InternalSerialization\SerializerFactory; use Wikibase\LabelDescriptionDuplicateDetector; @@ -944,4 +945,19 @@ return $this->entityNamespaceLookup; } + /** + * @return EntityParserOutputGeneratorFactory + */ + public function getEntityParserOutputGeneratorFactory() { + return new EntityParserOutputGeneratorFactory( + $this->getSnakFormatterFactory(), + $this->getStore()->getEntityInfoBuilderFactory(), + $this->getEntityContentFactory(), + $this->getEntityIdParser(), + $this->getPropertyDataTypeLookup(), + $this->getLanguageFallbackChainFactory(), + new ReferencedEntitiesFinder() + ); + } + } diff --git a/repo/includes/content/EntityContent.php b/repo/includes/content/EntityContent.php index 2d6073e..80e7741 100644 --- a/repo/includes/content/EntityContent.php +++ b/repo/includes/content/EntityContent.php @@ -268,17 +268,23 @@ protected function getParserOutputFromEntityView( Title $title, $revId = null, ParserOptions $options = null, $generateHtml = true ) { - $editable = !$options? true : $options->getEditSection(); + $wikibaseRepo = WikibaseRepo::getDefaultInstance(); + $entityParserOutputGeneratorFactory = $wikibaseRepo->getEntityParserOutputGeneratorFactory(); - if ( $revId === null || $revId === 0 ) { - $revId = $title->getLatestRevID(); - } + $entityRevision = $this->getEntityRevision( $title, $revId ); - $revision = new EntityRevision( $this->getEntity(), $revId ); + $outputGenerator = $entityParserOutputGeneratorFactory->getEntityParserOutputGenerator( + $entityRevision, + $options + ); - // generate parser output - $outputGenerator = $this->getEntityParserOutputGenerator( null, $options, null ); - $output = $outputGenerator->getParserOutput( $revision, $editable, $generateHtml ); + $editable = !$options ? true : $options->getEditSection(); + + $output = $outputGenerator->getParserOutput( + $entityRevision, + $editable, + $generateHtml + ); // Since the output depends on the user language, we must make sure // ParserCache::getKey() includes it in the cache key. @@ -291,155 +297,18 @@ } /** - * Creates an EntityParserOutputGenerator to create the ParserOutput for the entity + * @param Title $title + * @param int|null $revId * - * @param IContextSource|null $context - * @param ParserOptions|null $options - * @param LanguageFallbackChain|null $uiLanguageFallbackChain - * - * @note: this uses global state to access the services needed for - * displaying the entity. - * - * @return EntityParserOutputGenerator + * @return EntityRevision */ - private function getEntityParserOutputGenerator( - IContextSource $context = null, - ParserOptions $options = null, - LanguageFallbackChain $uiLanguageFallbackChain = null - ) { - if ( $context === null ) { - $context = RequestContext::getMain(); + private function getEntityRevision( Title $title, $revId = null ) { + if ( $revId === null || $revId === 0 ) { + $revId = $title->getLatestRevID(); } - $languageCode = $context->getLanguage()->getCode(); - - if ( $options !== null ) { - // NOTE: Parser Options language overrides context language! - $languageCode = $options->getUserLang(); - } - - $formatterOptions = new FormatterOptions(); - $formatterOptions->setOption( ValueFormatter::OPT_LANG, $languageCode ); - - // Force the context's language to be the one specified by the parser options. - if ( $context && $context->getLanguage()->getCode() !== $languageCode ) { - $context = clone $context; - $context->setLanguage( $languageCode ); - } - - $wikibaseRepo = WikibaseRepo::getDefaultInstance(); - - if ( !$uiLanguageFallbackChain ) { - $factory = $wikibaseRepo->getLanguageFallbackChainFactory(); - $uiLanguageFallbackChain = $factory->newFromContextForPageView( $context ); - } - - $formatterOptions->setOption( 'languages', $uiLanguageFallbackChain ); - - // get all the necessary services ---- - $snakFormatter = $wikibaseRepo->getSnakFormatterFactory() - ->getSnakFormatter( SnakFormatter::FORMAT_HTML_WIDGET, $formatterOptions ); - - $entityInfoBuilderFactory = $wikibaseRepo->getStore()->getEntityInfoBuilderFactory(); - $entityContentFactory = $wikibaseRepo->getEntityContentFactory(); - - $serializationOptions = $this->makeSerializationOptions( $languageCode, $uiLanguageFallbackChain ); - - $entityView = $this->getEntityView( - $snakFormatter, - $entityContentFactory, - $entityInfoBuilderFactory, - $context->getLanguage() - ); - - // --------------------------------------------------------------------- - - $configBuilder = new ParserOutputJsConfigBuilder( - $entityInfoBuilderFactory, - $wikibaseRepo->getEntityIdParser(), - $entityContentFactory, - new ReferencedEntitiesFinder(), - $context->getLanguage()->getCode() - ); - - $dataTypeLookup = $wikibaseRepo->getPropertyDataTypeLookup(); - - return new EntityParserOutputGenerator( - $entityView, - $configBuilder, - $serializationOptions, - $entityContentFactory, - $dataTypeLookup - ); + return new EntityRevision( $this->getEntity(), $revId ); } - - /** - * Creates an EntityView suitable for rendering the entity. - * - * @since 0.5 - * - * @param SnakFormatter $snakFormatter - * @param EntityTitleLookup $entityTitleLookup - * @param EntityInfoBuilderFactory $entityInfoBuilderFactory - * @param Language $language - * - * @return EntityView - */ - private function getEntityView( - SnakFormatter $snakFormatter, - EntityTitleLookup $entityTitleLookup, - EntityInfoBuilderFactory $entityInfoBuilderFactory, - Language $language - ) { - //TODO: cache last used entity view - $sectionEditLinkGenerator = new SectionEditLinkGenerator(); - - $snakHtmlGenerator = new SnakHtmlGenerator( - $snakFormatter, - $entityTitleLookup - ); - - $claimHtmlGenerator = new ClaimHtmlGenerator( - $snakHtmlGenerator, - $entityTitleLookup - ); - - $claimsView = new ClaimsView( - $entityInfoBuilderFactory, - $entityTitleLookup, - $sectionEditLinkGenerator, - $claimHtmlGenerator, - $language->getCode() - ); - - $fingerprintView = new FingerprintView( - $sectionEditLinkGenerator, - $language->getCode() - ); - - return $this->newEntityView( - $fingerprintView, - $claimsView, - $language - ); - } - - /** - * Instantiates an EntityView. - * - * @see getEntityView() - * - * @param FingerprintView $fingerprintView - * @param ClaimsView $claimsView - * @param Language $language - * - * @return EntityView - */ - protected abstract function newEntityView( - FingerprintView $fingerprintView, - ClaimsView $claimsView, - Language $language - ); /** * @return String a string representing the content in a way useful for building a full text @@ -849,21 +718,6 @@ $handler = $this->getContentHandler(); $status = $handler->getValidationErrorLocalizer()->getResultStatus( $result ); return $status; - } - - /** - * @param string $languageCode - * @param LanguageFallbackChain $fallbackChain - * - * @return SerializationOptions - */ - private function makeSerializationOptions( $languageCode, LanguageFallbackChain $fallbackChain ) { - $languageCodes = Utils::getLanguageCodes() + array( $languageCode => $fallbackChain ); - - $options = new SerializationOptions(); - $options->setLanguages( $languageCodes ); - - return $options; } /** diff --git a/repo/includes/content/ItemContent.php b/repo/includes/content/ItemContent.php index 11359d0..46cd222 100644 --- a/repo/includes/content/ItemContent.php +++ b/repo/includes/content/ItemContent.php @@ -198,23 +198,6 @@ } /** - * @see getEntityView() - * - * @param FingerprintView $fingerprintView - * @param ClaimsView $claimsView - * @param Language $language - * - * @return ItemView - */ - protected function newEntityView( - FingerprintView $fingerprintView, - ClaimsView $claimsView, - Language $language - ) { - return new ItemView( $fingerprintView, $claimsView, $language ); - } - - /** * @see EntityContent::getEntityPageProperties * * Records the number of sitelinks in the 'wb-sitelinks' key. diff --git a/repo/includes/content/PropertyContent.php b/repo/includes/content/PropertyContent.php index 7a35fcc..78b094c 100644 --- a/repo/includes/content/PropertyContent.php +++ b/repo/includes/content/PropertyContent.php @@ -104,21 +104,4 @@ return true; } - /** - * @see getEntityView() - * - * @param FingerprintView $fingerprintView - * @param ClaimsView $claimsView - * @param Language $language - * - * @return PropertyView - */ - protected function newEntityView( - FingerprintView $fingerprintView, - ClaimsView $claimsView, - Language $language - ) { - return new PropertyView( $fingerprintView, $claimsView, $language ); - } - } -- To view, visit https://gerrit.wikimedia.org/r/171528 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9453fd95eb7af8f34e7dbe18bd159b8bcb1927f7 Gerrit-PatchSet: 2 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: Aude <aude.w...@gmail.com> Gerrit-Reviewer: Daniel Kinzler <daniel.kinz...@wikimedia.de> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits