22
33namespace Wikibase \Repo \Domains \Search \Infrastructure \DataAccess ;
44
5+ use Wikibase \DataModel \Entity \BasicEntityIdParser ;
6+ use Wikibase \DataModel \Entity \EntityIdParsingException ;
57use Wikibase \DataModel \Entity \Item ;
8+ use Wikibase \DataModel \Entity \ItemId ;
69use Wikibase \DataModel \Entity \Property ;
10+ use Wikibase \DataModel \Entity \PropertyId ;
11+ use Wikibase \DataModel \Services \Lookup \EntityLookup ;
712use Wikibase \DataModel \Term \TermTypes ;
813use Wikibase \Lib \LanguageFallbackChainFactory ;
914use Wikibase \Lib \Store \MatchingTermsLookup ;
1015use Wikibase \Lib \TermIndexEntry ;
16+ use Wikibase \Repo \Domains \Search \Domain \Model \Description ;
1117use Wikibase \Repo \Domains \Search \Domain \Model \ItemSearchResult ;
1218use Wikibase \Repo \Domains \Search \Domain \Model \ItemSearchResults ;
1319use Wikibase \Repo \Domains \Search \Domain \Model \Label ;
2632class SqlTermStoreSearchEngine implements ItemSearchEngine, PropertySearchEngine {
2733
2834 private MatchingTermsLookup $ matchingTermsLookup ;
35+ private EntityLookup $ entityLookup ;
2936 private TermRetriever $ termRetriever ;
3037 private LanguageFallbackChainFactory $ languageFallbackChainFactory ;
3138
3239 public function __construct (
3340 MatchingTermsLookup $ matchingTermsLookup ,
41+ EntityLookup $ entityLookup ,
3442 TermRetriever $ termRetriever ,
3543 LanguageFallbackChainFactory $ languageFallbackChainFactory
3644 ) {
3745 $ this ->matchingTermsLookup = $ matchingTermsLookup ;
46+ $ this ->entityLookup = $ entityLookup ;
3847 $ this ->termRetriever = $ termRetriever ;
3948 $ this ->languageFallbackChainFactory = $ languageFallbackChainFactory ;
4049 }
@@ -45,10 +54,26 @@ public function searchItemByLabel(
4554 int $ limit ,
4655 int $ offset
4756 ): ItemSearchResults {
48- return new ItemSearchResults ( ...array_map (
49- $ this ->convertResult ( ItemSearchResult::class, $ languageCode ),
50- $ this ->findMatchingLabelsAndAliases ( Item::ENTITY_TYPE , $ searchTerm , $ languageCode , $ limit , $ offset )
51- ) );
57+ $ results = [];
58+ $ resultById = $ this ->searchItemById ( $ searchTerm , $ languageCode );
59+ if ( $ resultById ) {
60+ // when an Item was found by ID
61+ if ( $ offset === 0 ) {
62+ // add it on top of the first page and reduce limit by one
63+ $ results [] = $ resultById ;
64+ $ limit --;
65+ } else {
66+ // reduce offset by one on consecutive pages
67+ $ offset --;
68+ }
69+ }
70+ return new ItemSearchResults (
71+ ...$ results ,
72+ ...array_map (
73+ $ this ->convertResult ( ItemSearchResult::class, $ languageCode ),
74+ $ this ->findMatchingLabelsAndAliases ( Item::ENTITY_TYPE , $ searchTerm , $ languageCode , $ limit , $ offset )
75+ )
76+ );
5277 }
5378
5479 public function searchPropertyByLabel (
@@ -57,10 +82,26 @@ public function searchPropertyByLabel(
5782 int $ limit ,
5883 int $ offset
5984 ): PropertySearchResults {
60- return new PropertySearchResults ( ...array_map (
61- $ this ->convertResult ( PropertySearchResult::class, $ languageCode ),
62- $ this ->findMatchingLabelsAndAliases ( Property::ENTITY_TYPE , $ searchTerm , $ languageCode , $ limit , $ offset )
63- ) );
85+ $ results = [];
86+ $ resultById = $ this ->searchPropertyById ( $ searchTerm , $ languageCode );
87+ if ( $ resultById ) {
88+ // when a Property was found by ID
89+ if ( $ offset === 0 ) {
90+ // add it on top of the first page and reduce limit by one
91+ $ results [] = $ resultById ;
92+ $ limit --;
93+ } else {
94+ // reduce offset by one on consecutive pages
95+ $ offset --;
96+ }
97+ }
98+ return new PropertySearchResults (
99+ ...$ results ,
100+ ...array_map (
101+ $ this ->convertResult ( PropertySearchResult::class, $ languageCode ),
102+ $ this ->findMatchingLabelsAndAliases ( Property::ENTITY_TYPE , $ searchTerm , $ languageCode , $ limit , $ offset )
103+ )
104+ );
64105 }
65106
66107 /**
@@ -98,4 +139,64 @@ private function convertResult( string $resultClass, string $languageCode ): cal
98139 };
99140 }
100141
142+ private function searchItemById ( string $ searchTerm , string $ languageCode ): ?ItemSearchResult {
143+ $ item = $ this ->lookupItemById ( $ searchTerm );
144+ if ( !$ item ) {
145+ return null ;
146+ }
147+
148+ $ fallbackChain = $ this ->languageFallbackChainFactory ->newFromLanguageCode ( $ languageCode );
149+ $ itemLabel = $ fallbackChain ->extractPreferredValue ( $ item ->getLabels ()->toTextArray () );
150+ $ itemDescription = $ fallbackChain ->extractPreferredValue ( $ item ->getDescriptions ()->toTextArray () );
151+ return new ItemSearchResult (
152+ $ item ->getId (),
153+ $ itemLabel ? new Label ( $ itemLabel ['language ' ], $ itemLabel ['value ' ] ) : null ,
154+ $ itemDescription ? new Description ( $ itemDescription ['language ' ], $ itemDescription ['value ' ] ) : null ,
155+ new MatchedData ( 'entityId ' , null , $ item ->getId ()->getSerialization () )
156+ );
157+ }
158+
159+ private function searchPropertyById ( string $ searchTerm , string $ languageCode ): ?PropertySearchResult {
160+ $ property = $ this ->lookupPropertyById ( $ searchTerm );
161+ if ( !$ property ) {
162+ return null ;
163+ }
164+
165+ $ fallbackChain = $ this ->languageFallbackChainFactory ->newFromLanguageCode ( $ languageCode );
166+ $ propertyLabel = $ fallbackChain ->extractPreferredValue ( $ property ->getLabels ()->toTextArray () );
167+ $ propertyDescription = $ fallbackChain ->extractPreferredValue ( $ property ->getDescriptions ()->toTextArray () );
168+ return new PropertySearchResult (
169+ $ property ->getId (),
170+ $ propertyLabel ? new Label ( $ propertyLabel ['language ' ], $ propertyLabel ['value ' ] ) : null ,
171+ $ propertyDescription ? new Description ( $ propertyDescription ['language ' ], $ propertyDescription ['value ' ] ) : null ,
172+ new MatchedData ( 'entityId ' , null , $ property ->getId ()->getSerialization () )
173+ );
174+ }
175+
176+ private function lookupItemById ( string $ searchTerm ): ?Item {
177+ try {
178+ $ entityId = ( new BasicEntityIdParser () )->parse ( $ searchTerm );
179+ } catch ( EntityIdParsingException $ ex ) {
180+ $ entityId = null ;
181+ }
182+
183+ $ item = $ entityId instanceof ItemId ? $ this ->entityLookup ->getEntity ( $ entityId ) : null ;
184+ '@phan-var \Wikibase\DataModel\Entity\Item $item ' ;
185+
186+ return $ item instanceof Item ? $ item : null ;
187+ }
188+
189+ private function lookupPropertyById ( string $ searchTerm ): ?Property {
190+ try {
191+ $ entityId = ( new BasicEntityIdParser () )->parse ( $ searchTerm );
192+ } catch ( EntityIdParsingException $ ex ) {
193+ $ entityId = null ;
194+ }
195+
196+ $ property = $ entityId instanceof PropertyId ? $ this ->entityLookup ->getEntity ( $ entityId ) : null ;
197+ '@phan-var \Wikibase\DataModel\Entity\Property $property ' ;
198+
199+ return $ property instanceof Property ? $ property : null ;
200+ }
201+
101202}
0 commit comments