Passed
Pull Request — master (#170)
by
unknown
08:08
created

LocalFactory::isAttributesForFaceting()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * This file is part of Scout Extended.
7
 *
8
 * (c) Algolia Team <[email protected]>
9
 *
10
 *  For the full copyright and license information, please view the LICENSE
11
 *  file that was distributed with this source code.
12
 */
13
14
namespace Algolia\ScoutExtended\Settings;
15
16
use function in_array;
17
use Illuminate\Support\Str;
18
use Algolia\AlgoliaSearch\SearchIndex;
19
use Illuminate\Database\QueryException;
20
use Algolia\ScoutExtended\Searchable\Aggregator;
21
use Algolia\ScoutExtended\Contracts\SettingsUpdaterContract;
22
use Algolia\ScoutExtended\Exceptions\ModelNotFoundException;
23
use Algolia\ScoutExtended\Repositories\RemoteSettingsRepository;
24
use Algolia\ScoutExtended\Settings\SettingAttribute\searchableAttribute;
25
use Algolia\ScoutExtended\Settings\SettingAttribute\attributeForFaceting;
26
use Algolia\ScoutExtended\Settings\SettingAttribute\CustomRankingAttribute;
27
use Algolia\ScoutExtended\Settings\SettingAttribute\UnretrievableAttribute;
28
use Algolia\ScoutExtended\Settings\SettingAttribute\DisableTypoToleranceAttribute;
29
use Illuminate\Database\Eloquent\ModelNotFoundException as BaseModelNotFoundException;
30
31
/**
32
 * @internal
33
 */
34
final class LocalFactory
35
{
36
    /**
37
     * @var \Algolia\ScoutExtended\Repositories\RemoteSettingsRepository
38
     */
39
    private $remoteRepository;
40
41
    /**
42
     * @var string[]
43
     */
44
    private static $settings = [
45
        'searchableAttributes' => searchableAttribute::class,
46
        'attributesForFaceting' => attributeForFaceting::class,
47
        'customRanking' => CustomRankingAttribute::class,
48
        'disableTypoToleranceOnAttributes' => DisableTypoToleranceAttribute::class,
49
        'unretrievableAttributes' => UnretrievableAttribute::class,
50
    ];
51
52
    /**
53
     * SettingsFactory constructor.
54
     *
55
     * @param \Algolia\ScoutExtended\Repositories\RemoteSettingsRepository $remoteRepository
56
     *
57
     * @return void
58
     */
59 5
    public function __construct(RemoteSettingsRepository $remoteRepository)
60
    {
61 5
        $this->remoteRepository = $remoteRepository;
62 5
    }
63
64
    /**
65
     * Creates settings for the given model.
66
     *
67
     * @param \Algolia\AlgoliaSearch\SearchIndex $index
68
     * @param string $model
69
     *
70
     * @return \Algolia\ScoutExtended\Settings\Settings
71
     */
72 5
    public function create(SearchIndex $index, string $model): Settings
73
    {
74 5
        $attributes = $this->getAttributes($model);
75
76 4
        $attributeArray = array_fill_keys(array_keys(self::$settings), []);
77
78 4
        foreach ($attributes as $key => $value) {
79 4
            $key = (string) $key;
80 4
            foreach (self::$settings as $setting => $settingClass) {
81 4
                $attributeArray[$setting] = (new $settingClass)->getValue($key, $value, $attributeArray[$setting]);
82
            }
83
        }
84 4
        foreach ($attributeArray as $key => $value) {
85 4
            $detectedSettings[$key] = ! empty($value) ? $value : null;
86
        }
87 4
        $detectedSettings['queryLanguages'] = array_unique([config('app.locale'), config('app.fallback_locale')]);
88
89 4
        $settings = array_merge($this->remoteRepository->find($index)->compiled(), $detectedSettings);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $detectedSettings seems to be defined by a foreach iteration on line 84. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
90 4
        foreach ($attributes as $key => $value) {
91 4
            $method = 'split'.Str::camel((string) $key);
92 4
            if (method_exists($model, $method)) {
93 1
                $result = (new $model)->{$method}($value);
94 1
                if (is_string($result)) {
95 1
                    $result = app($result);
96
                }
97 1
                if ($result instanceof SettingsUpdaterContract) {
98 4
                    $settings = $result->updateSettings($settings, (string) $key);
99
                }
100
            }
101
        }
102
103 4
        return new Settings($settings, $this->remoteRepository->defaults());
104
    }
105
106
    /**
107
     * Tries to get attributes from the searchable class.
108
     *
109
     * @param  string $searchable
110
     *
111
     * @return array
112
     */
113 5
    private function getAttributes(string $searchable): array
114
    {
115 5
        $attributes = [];
116
117 5
        if (in_array(Aggregator::class, class_parents($searchable), true)) {
118
            foreach (($instance = new $searchable)->getModels() as $model) {
0 ignored issues
show
Unused Code introduced by
The assignment to $instance is dead and can be removed.
Loading history...
119
                $attributes = array_merge($attributes, $this->getAttributes($model));
120
            }
121
        } else {
122 5
            $instance = null;
123
124
            try {
125 5
                $instance = $searchable::firstOrFail();
126 1
            } catch (QueryException | BaseModelNotFoundException $e) {
127 1
                throw tap(new ModelNotFoundException())->setModel($searchable);
128
            }
129
130 4
            $attributes = method_exists($instance, 'toSearchableArray') ? $instance->toSearchableArray() :
131 4
                $instance->toArray();
132
        }
133
134 4
        return $attributes;
135
    }
136
}
137