Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 5
CRAP
53.12% covered (warning)
53.12%
17 / 32
LexemeLanguageField
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 5
34.19
53.12% covered (warning)
53.12%
17 / 32
 __construct
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 4
 getMapping
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 5
 getLanguageCode
0.00% covered (danger)
0.00%
0 / 1
7.12
86.67% covered (warning)
86.67%
13 / 15
 getFieldData
0.00% covered (danger)
0.00%
0 / 1
2.03
80.00% covered (warning)
80.00%
4 / 5
 getEngineHints
0.00% covered (danger)
0.00%
0 / 1
6
0.00% covered (danger)
0.00%
0 / 3
<?php
namespace Wikibase\Lexeme\Search\Elastic;
use CirrusSearch\CirrusSearch;
use CirrusSearch\Search\CirrusIndexField;
use DataValues\StringValue;
use SearchEngine;
use Wikibase\DataModel\Entity\EntityDocument;
use Wikibase\DataModel\Entity\EntityId;
use Wikibase\DataModel\Entity\NumericPropertyId;
use Wikibase\DataModel\Services\Lookup\EntityLookup;
use Wikibase\DataModel\Snak\PropertyValueSnak;
use Wikibase\DataModel\Statement\StatementListProvider;
use Wikibase\Lexeme\Domain\Model\Lexeme;
/**
 * Lexeme language field - this contains Q-id of lexeme language.
 */
class LexemeLanguageField extends LexemeKeywordField {
    public const NAME = 'lexeme_language';
    /**
     * @var EntityLookup
     */
    private $entityLookup;
    /**
     * @var NumericPropertyId|null
     */
    private $lexemeLanguageCodePropertyId;
    public function __construct(
        EntityLookup $entityLookup,
        NumericPropertyId $lexemeLanguageCodePropertyId = null
    ) {
        parent::__construct();
        $this->lexemeLanguageCodePropertyId = $lexemeLanguageCodePropertyId;
        $this->entityLookup = $entityLookup;
    }
    /**
     * Create mapping for Lexeme language.
     * Two fields:
     * - entity - Q-id of language entity
     * - code - language code for the language
     * @param SearchEngine $engine
     *
     * @return array
     */
    public function getMapping( SearchEngine $engine ) {
        // Since we need a specially tuned field, we can not use
        // standard search engine types.
        if ( !( $engine instanceof CirrusSearch ) ) {
            // For now only Cirrus/Elastic is supported
            return [];
        }
        return [
            'type' => 'object',
            'properties' => [
                // Both subfields are keywords
                'entity' => parent::getMapping( $engine ),
                'code' => parent::getMapping( $engine ),
            ],
        ];
    }
    /**
     * Extract language code from language entity
     * @param EntityId $languageId The ID of the language entity
     * @return null|string
     */
    private function getLanguageCode( EntityId $languageId ) {
        if ( !$this->lexemeLanguageCodePropertyId ) {
            return null;
        }
        $langEntity = $this->entityLookup->getEntity( $languageId );
        if ( !$langEntity || !( $langEntity instanceof StatementListProvider ) ) {
            return null;
        }
        $langCodes = $langEntity->getStatements()->getByPropertyId( $this->lexemeLanguageCodePropertyId );
        if ( $langCodes->isEmpty() ) {
            return null;
        }
        // if there are more than one code, take the first one.
        $codeSnak = $langCodes->getAllSnaks()[0];
        if ( !( $codeSnak instanceof PropertyValueSnak ) ) {
            return null;
        }
        $value = $codeSnak->getDataValue();
        if ( !( $value instanceof StringValue ) ) {
            return null;
        }
        return $value->getValue();
    }
    /**
     * @param EntityDocument $entity
     *
     * @return mixed Get the value of the field to be indexed when a page/document
     *               is indexed. This might be an array with nested data, if the field
     *               is defined with nested type or an int or string for simple field types.
     */
    public function getFieldData( EntityDocument $entity ) {
        if ( !( $entity instanceof Lexeme ) ) {
            return [];
        }
        /**
         * @var Lexeme $entity
         */
        $language = $entity->getLanguage();
        return [
            'entity' => $language->getSerialization(),
            'code' => $this->getLanguageCode( $language ),
        ];
    }
    /**
     * Set engine hints.
     * Specifically, sets noop hint so that forms would be compared
     * as arrays and changes in language parts would be processed correctly.
     * @param SearchEngine $engine
     * @return array
     */
    public function getEngineHints( SearchEngine $engine ) {
        if ( !( $engine instanceof CirrusSearch ) ) {
            // For now only Cirrus/Elastic is supported
            return [];
        }
        return [ CirrusIndexField::NOOP_HINT => "equals" ];
    }
}