Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
94.29% covered (success)
94.29%
33 / 35
88.89% covered (warning)
88.89%
8 / 9
CRAP
0.00% covered (danger)
0.00%
0 / 1
CompletionSearchProfileRepository
94.29% covered (success)
94.29%
33 / 35
88.89% covered (warning)
88.89%
8 / 9
16.05
0.00% covered (danger)
0.00%
0 / 1
 fromFile
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 fromConfig
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 fromRepo
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 __construct
90.48% covered (success)
90.48%
19 / 21
0.00% covered (danger)
0.00%
0 / 1
8.06
 repositoryType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 repositoryName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getProfile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasProfile
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 listExposedProfiles
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace CirrusSearch\Profile;
4
5use CirrusSearch\SearchConfig;
6
7/**
8 * Repository dedicated to completion queries
9 * This one cannot simply use existing implementation because
10 * we need to filter the profiles based on the availability of
11 * some fields in the index.
12 */
13class CompletionSearchProfileRepository implements SearchProfileRepository {
14
15    /**
16     * @var SearchProfileRepository
17     */
18    private $wrapped;
19
20    /**
21     * @param string $repoType
22     * @param string $repoName
23     * @param string $phpFile
24     * @param SearchConfig $config
25     * @return CompletionSearchProfileRepository
26     */
27    public static function fromFile( $repoType, $repoName, $phpFile, SearchConfig $config ) {
28        // TODO: find a construct that does not require duplicating ArrayProfileRepository::fromFile
29        return new self( $repoType, $repoName, $config, static function () use ( $phpFile ) {
30            return require $phpFile;
31        } );
32    }
33
34    /**
35     * @param string $repoType
36     * @param string $repoName
37     * @param string $configEntry
38     * @param SearchConfig $config
39     * @return CompletionSearchProfileRepository
40     */
41    public static function fromConfig( $repoType, $repoName, $configEntry, SearchConfig $config ) {
42        return new self( $repoType, $repoName, $config, static function () use ( $configEntry, $config ) {
43            return ConfigProfileRepository::extractConfig( $configEntry, $config );
44        } );
45    }
46
47    /**
48     * @param SearchProfileRepository $repository
49     * @param SearchConfig $config
50     * @return self
51     */
52    public static function fromRepo( SearchProfileRepository $repository, SearchConfig $config ): self {
53        return new self( $repository->repositoryType(), $repository->repositoryName(), $config, static function () use ( $repository ) {
54            return $repository->listExposedProfiles();
55        } );
56    }
57
58    /**
59     * @param string $repoType
60     * @param string $repoName
61     * @param SearchConfig $config
62     * @param callable $arrayLoader callable that resolves to an array of original profiles
63     */
64    private function __construct( $repoType, $repoName, SearchConfig $config, callable $arrayLoader ) {
65        $this->wrapped = ArrayProfileRepository::lazyLoaded( $repoType, $repoName, static function () use ( $arrayLoader, $config ) {
66            $profiles = [];
67
68            $allowedFields = [ 'suggest' => true, 'suggest-stop' => true ];
69            // Check that we can use the subphrases FST
70            if ( $config->getElement( 'CirrusSearchCompletionSuggesterSubphrases', 'use' ) ) {
71                $allowedFields['suggest-subphrases'] = true;
72            }
73            $originalProfiles = call_user_func( $arrayLoader );
74            if ( !is_array( $originalProfiles ) ) {
75                throw new SearchProfileException( "Expected an array but got a " . gettype( $originalProfiles ) );
76            }
77            foreach ( $originalProfiles as $name => $settings ) {
78                $allowed = true;
79                if ( !isset( $settings['fst'] ) ) {
80                    throw new SearchProfileException( "Completion profile $name must have a fst key defined" );
81                }
82                foreach ( $settings['fst'] as $value ) {
83                    if ( empty( $allowedFields[$value['field']] ) ) {
84                        $allowed = false;
85                        break;
86                    }
87                }
88                if ( !$allowed ) {
89                    continue;
90                }
91                $profiles[$name] = $settings;
92            }
93            return $profiles;
94        } );
95    }
96
97    /**
98     * @return string
99     */
100    public function repositoryType() {
101        return $this->wrapped->repositoryType();
102    }
103
104    /**
105     * @return string
106     */
107    public function repositoryName() {
108        return $this->wrapped->repositoryName();
109    }
110
111    /**
112     * @param string $name
113     * @return array
114     */
115    public function getProfile( $name ) {
116        return $this->wrapped->getProfile( $name );
117    }
118
119    /**
120     * @param string $name
121     * @return bool
122     */
123    public function hasProfile( $name ) {
124        return $this->wrapped->hasProfile( $name );
125    }
126
127    /**
128     * @return array[]
129     */
130    public function listExposedProfiles() {
131        return $this->wrapped->listExposedProfiles();
132    }
133}