diff --git a/WikibaseLexeme.entitytypes.php b/WikibaseLexeme.entitytypes.php index 17143c9b..1818a968 100644 --- a/WikibaseLexeme.entitytypes.php +++ b/WikibaseLexeme.entitytypes.php @@ -1,297 +1,320 @@ */ use MediaWiki\MediaWikiServices; use Wikibase\DataModel\DeserializerFactory; use Wikibase\DataModel\Entity\EntityId; use Wikibase\DataModel\SerializerFactory; use Wikibase\DataModel\Services\EntityId\EntityIdFormatter; use Wikibase\DataModel\Services\Lookup\LabelDescriptionLookup; use Wikibase\LanguageFallbackChain; use Wikibase\Lexeme\ChangeOp\Deserialization\FormChangeOpDeserializer; use Wikibase\Lexeme\ChangeOp\Deserialization\LanguageChangeOpDeserializer; use Wikibase\Lexeme\ChangeOp\Deserialization\LemmaChangeOpDeserializer; use Wikibase\Lexeme\ChangeOp\Deserialization\LexemeChangeOpDeserializer; use Wikibase\Lexeme\ChangeOp\Deserialization\LexicalCategoryChangeOpDeserializer; use Wikibase\Lexeme\Content\LexemeContent; use Wikibase\Lexeme\Content\LexemeHandler; use Wikibase\Lexeme\DataModel\FormId; use Wikibase\Lexeme\DataModel\Lexeme; use Wikibase\Lexeme\DataModel\LexemeId; use Wikibase\Lexeme\DataModel\Serialization\ExternalLexemeSerializer; use Wikibase\Lexeme\DataModel\Serialization\LexemeDeserializer; use Wikibase\Lexeme\DataModel\Serialization\StorageLexemeSerializer; use Wikibase\Lexeme\DataModel\Services\Diff\FormDiffer; use Wikibase\Lexeme\DataModel\Services\Diff\FormPatcher; use Wikibase\Lexeme\DataModel\Services\Diff\LexemeDiffer; use Wikibase\Lexeme\DataModel\Services\Diff\LexemePatcher; use Wikibase\Lexeme\Diff\LexemeDiffVisualizer; use Wikibase\Lexeme\Diff\ItemReferenceDifferenceVisualizer; use Wikibase\Lexeme\Rdf\LexemeRdfBuilder; use Wikibase\Lexeme\Search\LexemeFieldDefinitions; use Wikibase\Lexeme\Store\FormRevisionLookup; use Wikibase\Lexeme\Store\FormStore; use Wikibase\Lexeme\Store\FormTitleStoreLookup; use Wikibase\Lexeme\Validators\LexemeValidatorFactory; use Wikibase\Lexeme\View\LexemeViewFactory; use Wikibase\Lib\Store\EntityRevisionLookup; use Wikibase\Lib\Store\EntityStore; use Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookup; use Wikibase\Rdf\RdfVocabulary; use Wikibase\Repo\ChangeOp\Deserialization\ClaimsChangeOpDeserializer; use Wikibase\Repo\ChangeOp\Deserialization\TermChangeOpSerializationValidator; use Wikibase\Repo\Diff\BasicEntityDiffVisualizer; use Wikibase\Repo\Diff\ClaimDiffer; use Wikibase\Repo\Diff\ClaimDifferenceVisualizer; use Wikibase\Repo\Store\EntityTitleStoreLookup; use Wikibase\Repo\WikibaseRepo; use Wikibase\View\EditSectionGenerator; use Wikibase\View\EntityTermsView; use Wikimedia\Purtle\RdfWriter; return [ 'lexeme' => [ 'serializer-factory-callback' => function ( SerializerFactory $serializerFactory ) { return new ExternalLexemeSerializer( new StorageLexemeSerializer( $serializerFactory->newTermListSerializer(), $serializerFactory->newStatementListSerializer() ) ); }, 'storage-serializer-factory-callback' => function ( SerializerFactory $serializerFactory ) { return new StorageLexemeSerializer( $serializerFactory->newTermListSerializer(), $serializerFactory->newStatementListSerializer() ); }, 'deserializer-factory-callback' => function ( DeserializerFactory $deserializerFactory ) { return new LexemeDeserializer( $deserializerFactory->newEntityIdDeserializer(), $deserializerFactory->newStatementListDeserializer() ); }, 'view-factory-callback' => function ( $languageCode, LabelDescriptionLookup $labelDescriptionLookup, LanguageFallbackChain $fallbackChain, EditSectionGenerator $editSectionGenerator, EntityTermsView $entityTermsView ) { $factory = new LexemeViewFactory( $languageCode, $labelDescriptionLookup, $fallbackChain, $editSectionGenerator, $entityTermsView, WikibaseRepo::getDefaultInstance()->getEntityIdHtmlLinkFormatterFactory() ); return $factory->newLexemeView(); }, 'content-model-id' => LexemeContent::CONTENT_MODEL_ID, 'content-handler-factory-callback' => function () { $wikibaseRepo = WikibaseRepo::getDefaultInstance(); $config = MediaWikiServices::getInstance()->getMainConfig(); if ( $config->has( 'LexemeLanguageCodePropertyId' ) ) { $lcID = $config->get( 'LexemeLanguageCodePropertyId' ); } else { $lcID = null; } return new LexemeHandler( $wikibaseRepo->getStore()->getTermIndex(), $wikibaseRepo->getEntityContentDataCodec(), $wikibaseRepo->getEntityConstraintProvider(), $wikibaseRepo->getValidatorErrorLocalizer(), $wikibaseRepo->getEntityIdParser(), $wikibaseRepo->getEntityIdLookup(), $wikibaseRepo->getEntityLookup(), $wikibaseRepo->getLanguageFallbackLabelDescriptionLookupFactory(), new LexemeFieldDefinitions( $wikibaseRepo->getStatementProviderDefinitions(), $wikibaseRepo->getEntityLookup(), $lcID ? $wikibaseRepo->getEntityIdParser()->parse( $lcID ) : null ) ); }, 'entity-id-pattern' => LexemeId::PATTERN, 'entity-id-builder' => function ( $serialization ) { return new LexemeId( $serialization ); }, 'entity-id-composer-callback' => function ( $repositoryName, $uniquePart ) { return new LexemeId( EntityId::joinSerialization( [ $repositoryName, '', 'L' . $uniquePart ] ) ); }, 'entity-differ-strategy-builder' => function () { return new LexemeDiffer(); }, 'entity-patcher-strategy-builder' => function () { return new LexemePatcher(); }, 'entity-factory-callback' => function () { return new Lexeme(); }, // Identifier of a resource loader module that, when `require`d, returns a function // returning a deserializer 'js-deserializer-factory-function' => 'wikibase.lexeme.getDeserializer', 'changeop-deserializer-callback' => function () { $wikibaseRepo = WikibaseRepo::getDefaultInstance(); $lexemeValidatorFactory = new LexemeValidatorFactory( 1000, // TODO: move to setting, at least change to some reasonable hard-coded value $wikibaseRepo->getTermValidatorFactory(), // FIXME: What does belong here? [] ); return new LexemeChangeOpDeserializer( new LemmaChangeOpDeserializer( // TODO: WikibaseRepo should probably provide this validator? // TODO: WikibaseRepo::getTermsLanguage is not necessarily the list of language codes // that should be allowed as "languages" of lemma terms new TermChangeOpSerializationValidator( $wikibaseRepo->getTermsLanguages() ), $lexemeValidatorFactory, $wikibaseRepo->getStringNormalizer() ), new LexicalCategoryChangeOpDeserializer( $lexemeValidatorFactory, $wikibaseRepo->getStringNormalizer() ), new LanguageChangeOpDeserializer( $lexemeValidatorFactory, $wikibaseRepo->getStringNormalizer() ), new ClaimsChangeOpDeserializer( $wikibaseRepo->getExternalFormatStatementDeserializer(), $wikibaseRepo->getChangeOpFactoryProvider()->getStatementChangeOpFactory() ), new FormChangeOpDeserializer() ); }, 'rdf-builder-factory-callback' => function ( $flavorFlags, RdfVocabulary $vocabulary, RdfWriter $writer, $mentionedEntityTracker, $dedupe ) { return new LexemeRdfBuilder( $vocabulary, $writer ); }, 'entity-diff-visualizer-callback' => function ( MessageLocalizer $messageLocalizer, ClaimDiffer $claimDiffer, ClaimDifferenceVisualizer $claimDiffView, SiteLookup $siteLookup, EntityIdFormatter $entityIdFormatter ) { $basicEntityDiffVisualizer = new BasicEntityDiffVisualizer( $messageLocalizer, $claimDiffer, $claimDiffView, $siteLookup, $entityIdFormatter ); $wikibaseRepo = WikibaseRepo::getDefaultInstance(); $prefetchingTermLookup = $wikibaseRepo->getPrefetchingTermLookup(); $labelDescriptionLookup = new LanguageFallbackLabelDescriptionLookup( $prefetchingTermLookup, $wikibaseRepo->getLanguageFallbackChainFactory() ->newFromLanguage( $wikibaseRepo->getUserLanguage() ) ); $entityIdFormatter = $wikibaseRepo->getEntityIdHtmlLinkFormatterFactory() ->getEntityIdFormatter( $labelDescriptionLookup ); return new LexemeDiffVisualizer( $messageLocalizer, $basicEntityDiffVisualizer, $claimDiffer, $claimDiffView, new ItemReferenceDifferenceVisualizer( $entityIdFormatter ) ); }, 'entity-search-callback' => function ( WebRequest $request ) { + // FIXME: this code should be split into extension for T190022 $repo = WikibaseRepo::getDefaultInstance(); - return new \Wikibase\Lexeme\Search\LexemeSearchEntity( - $repo->getEntityIdParser(), - $request, - $repo->getUserLanguage(), - $repo->getLanguageFallbackChainFactory(), - $repo->getPrefetchingTermLookup() + + $idSearchHelper = new Wikibase\Repo\Api\EntityIdSearchHelper( + $repo->getEntityLookup(), + $repo->getEntityIdParser(), + new Wikibase\Lib\Store\LanguageFallbackLabelDescriptionLookup( + $repo->getTermLookup(), + $repo->getLanguageFallbackChainFactory()->newFromLanguage( $repo->getUserLanguage() ) + ), + $repo->getEntityTypeToRepositoryMapping() + ); + + $repoSettings = $repo->getSettings(); + $searchSettings = $repoSettings->getSetting( 'entitySearch' ); + if ( $searchSettings['useCirrus'] ) { + return new Wikibase\Repo\Api\CombinedEntitySearchHelper( + [ + $idSearchHelper, + new \Wikibase\Lexeme\Search\LexemeSearchEntity( + $repo->getEntityIdParser(), + $request, + $repo->getUserLanguage(), + $repo->getLanguageFallbackChainFactory(), + $repo->getPrefetchingTermLookup() + ) + ] ); + } + + return $idSearchHelper; }, 'sub-entity-types' => [ 'form' ], ], 'form' => [ 'entity-store-factory-callback' => function ( EntityStore $defaultStore, EntityRevisionLookup $lookup ) { return new FormStore( $defaultStore, $lookup ); }, 'entity-revision-lookup-factory-callback' => function ( EntityRevisionLookup $defaultLookup ) { return new FormRevisionLookup( $defaultLookup ); }, 'entity-title-store-lookup-factory-callback' => function ( EntityTitleStoreLookup $defaultLookup ) { return new FormTitleStoreLookup( $defaultLookup ); }, 'entity-id-pattern' => FormId::PATTERN, 'entity-id-builder' => function ( $serialization ) { return new FormId( $serialization ); }, 'entity-differ-strategy-builder' => function () { return new FormDiffer(); }, 'entity-patcher-strategy-builder' => function () { return new FormPatcher(); }, 'content-handler-factory-callback' => function () { $wikibaseRepo = WikibaseRepo::getDefaultInstance(); $config = MediaWikiServices::getInstance()->getMainConfig(); if ( $config->has( 'LexemeLanguageCodePropertyId' ) ) { $lcID = $config->get( 'LexemeLanguageCodePropertyId' ); } else { $lcID = null; } return new LexemeHandler( $wikibaseRepo->getStore()->getTermIndex(), $wikibaseRepo->getEntityContentDataCodec(), $wikibaseRepo->getEntityConstraintProvider(), $wikibaseRepo->getValidatorErrorLocalizer(), $wikibaseRepo->getEntityIdParser(), $wikibaseRepo->getEntityIdLookup(), $wikibaseRepo->getEntityLookup(), $wikibaseRepo->getLanguageFallbackLabelDescriptionLookupFactory(), new LexemeFieldDefinitions( $wikibaseRepo->getStatementProviderDefinitions(), $wikibaseRepo->getEntityLookup(), $lcID ? $wikibaseRepo->getEntityIdParser()->parse( $lcID ) : null ) ); }, ], ]; diff --git a/tests/phpunit/mediawiki/Api/SearchEntitiesIntegrationTest.php b/tests/phpunit/mediawiki/Api/SearchEntitiesIntegrationTest.php new file mode 100644 index 00000000..4f579de9 --- /dev/null +++ b/tests/phpunit/mediawiki/Api/SearchEntitiesIntegrationTest.php @@ -0,0 +1,70 @@ +saveDummyLexemeToDatabase(); + + $params = [ + 'action' => 'wbsearchentities', + 'search' => self::LEXEME_ID, + 'type' => 'lexeme', + 'language' => 'en', + ]; + + list( $result, ) = $this->doApiRequest( $params ); + + $this->assertCount( 1, $result['search'] ); + $this->assertSame( self::LEXEME_ID, $result['search'][0]['id'] ); + $this->assertSame( + [ 'type' => 'entityId', 'text' => self::LEXEME_ID ], + $result['search'][0]['match'] + ); + } + + public function testGivenIdOfNonExistingLexeme_noResults() { + $this->saveDummyLexemeToDatabase(); + + $params = [ + 'action' => 'wbsearchentities', + 'search' => 'L21323232', + 'type' => 'lexeme', + 'language' => 'en', + ]; + + list( $result, ) = $this->doApiRequest( $params ); + + $this->assertEmpty( $result['search'] ); + } + + private function saveDummyLexemeToDatabase() { + $this->entityStore->saveEntity( + $this->getDummyLexeme(), + self::class, + $this->getMock( User::class ) + ); + } + + private function getDummyLexeme() { + return NewLexeme::havingId( self::LEXEME_ID )->build(); + } + +}