Completed
Pull Request — refacto/local-factory (#167)
by Nuno
11:16 queued 06:37
created

LocalFactory   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 89
Duplicated Lines 0 %

Test Coverage

Coverage 92.59%

Importance

Changes 0
Metric Value
eloc 32
dl 0
loc 89
ccs 25
cts 27
cp 0.9259
rs 10
c 0
b 0
f 0
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A getAttributes() 0 22 5
A create() 0 20 5
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 Algolia\AlgoliaSearch\SearchIndex;
18
use Illuminate\Database\QueryException;
19
use Algolia\ScoutExtended\Searchable\Aggregator;
20
use Algolia\ScoutExtended\Exceptions\ModelNotFoundException;
21
use Algolia\ScoutExtended\Repositories\RemoteSettingsRepository;
22
use Algolia\ScoutExtended\Settings\SettingAttribute\searchableAttribute;
23
use Algolia\ScoutExtended\Settings\SettingAttribute\attributeForFaceting;
24
use Algolia\ScoutExtended\Settings\SettingAttribute\CustomRankingAttribute;
25
use Algolia\ScoutExtended\Settings\SettingAttribute\UnretrievableAttribute;
26
use Algolia\ScoutExtended\Settings\SettingAttribute\DisableTypoToleranceAttribute;
27
use Illuminate\Database\Eloquent\ModelNotFoundException as BaseModelNotFoundException;
28
29
/**
30
 * @internal
31
 */
32
final class LocalFactory
33
{
34
    /**
35
     * @var \Algolia\ScoutExtended\Repositories\RemoteSettingsRepository
36
     */
37
    private $remoteRepository;
38
39
    /**
40
     * @var string[]
41
     */
42
    private static $settings = [
43
        'searchableAttributes' => searchableAttribute::class,
44
        'attributesForFaceting' => attributeForFaceting::class,
45
        'customRanking' => CustomRankingAttribute::class,
46
        'disableTypoToleranceOnAttributes' => DisableTypoToleranceAttribute::class,
47
        'unretrievableAttributes' => UnretrievableAttribute::class,
48
    ];
49
50
    /**
51
     * SettingsFactory constructor.
52
     *
53
     * @param \Algolia\ScoutExtended\Repositories\RemoteSettingsRepository $remoteRepository
54
     *
55
     * @return void
56
     */
57 4
    public function __construct(RemoteSettingsRepository $remoteRepository)
58
    {
59 4
        $this->remoteRepository = $remoteRepository;
60 4
    }
61
62
    /**
63
     * Creates settings for the given model.
64
     *
65
     * @param \Algolia\AlgoliaSearch\SearchIndex $index
66
     * @param string $model
67
     *
68
     * @return \Algolia\ScoutExtended\Settings\Settings
69
     */
70 4
    public function create(SearchIndex $index, string $model): Settings
71
    {
72 4
        $attributes = $this->getAttributes($model);
73
74 3
        $attributeArray = array_fill_keys(array_keys(self::$settings), []);
75
76 3
        foreach ($attributes as $key => $value) {
77 3
            $key = (string) $key;
78 3
            foreach (self::$settings as $setting => $settingClass) {
79 3
                $attributeArray[$setting] = (new $settingClass)->getValue($key, $value, $attributeArray[$setting]);
80
            }
81
        }
82 3
        foreach ($attributeArray as $key => $value) {
83 3
            $detectedSettings[$key] = ! empty($value) ? $value : null;
84
        }
85 3
        $detectedSettings['queryLanguages'] = array_unique([config('app.locale'), config('app.fallback_locale')]);
86
87 3
        $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 82. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
88
89 3
        return new Settings($settings, $this->remoteRepository->defaults());
90
    }
91
92
    /**
93
     * Tries to get attributes from the searchable class.
94
     *
95
     * @param  string $searchable
96
     *
97
     * @return array
98
     */
99 4
    private function getAttributes(string $searchable): array
100
    {
101 4
        $attributes = [];
102
103 4
        if (in_array(Aggregator::class, class_parents($searchable), true)) {
104
            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...
105
                $attributes = array_merge($attributes, $this->getAttributes($model));
106
            }
107
        } else {
108 4
            $instance = null;
109
110
            try {
111 4
                $instance = $searchable::firstOrFail();
112 1
            } catch (QueryException | BaseModelNotFoundException $e) {
113 1
                throw tap(new ModelNotFoundException())->setModel($searchable);
114
            }
115
116 3
            $attributes = method_exists($instance, 'toSearchableArray') ? $instance->toSearchableArray() :
117 3
                $instance->toArray();
118
        }
119
120 3
        return $attributes;
121
    }
122
}
123