Completed
Pull Request — master (#170)
by Simonas
04:25
created

SettingsManager::getAllProfiles()   B

Complexity

Conditions 4
Paths 5

Size

Total Lines 32
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 32
rs 8.5806
cc 4
eloc 20
nc 5
nop 0
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\SettingsBundle\Service;
13
14
use Doctrine\Common\Cache\CacheProvider;
15
use ONGR\CookiesBundle\Cookie\Model\GenericCookie;
16
use ONGR\ElasticsearchBundle\Result\Aggregation\AggregationValue;
17
use ONGR\ElasticsearchDSL\Aggregation\TermsAggregation;
18
use ONGR\ElasticsearchDSL\Aggregation\TopHitsAggregation;
19
use ONGR\SettingsBundle\Exception\SettingNotFoundException;
20
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
21
use ONGR\ElasticsearchBundle\Service\Repository;
22
use ONGR\ElasticsearchBundle\Service\Manager;
23
use ONGR\SettingsBundle\Document\Setting;
24
25
/**
26
 * Class SettingsManager responsible for managing settings actions.
27
 */
28
class SettingsManager
29
{
30
    /**
31
     * Symfony event dispatcher.
32
     *
33
     * @var EventDispatcherInterface
34
     */
35
    private $eventDispatcher;
36
37
    /**
38
     * Elasticsearch manager which handles setting repository.
39
     *
40
     * @var Manager
41
     */
42
    private $manager;
43
44
    /**
45
     * Settings repository.
46
     *
47
     * @var Repository
48
     */
49
    private $repo;
50
51
    /**
52
     * Cache pool container.
53
     *
54
     * @var CacheProvider
55
     */
56
    private $cache;
57
58
    /**
59
     * Cookie storage for active cookies.
60
     *
61
     * @var GenericCookie
62
     */
63
    private $activeProfilesCookie;
64
65
    /**
66
     * Active profiles setting name to store in the cache engine.
67
     *
68
     * @var string
69
     */
70
    private $activeProfilesSettingName;
71
72
    /**
73
     * @param Repository               $repo
74
     * @param EventDispatcherInterface $eventDispatcher
75
     */
76
    public function __construct(
77
        $repo,
78
        EventDispatcherInterface $eventDispatcher
79
    ) {
80
        $this->repo = $repo;
81
        $this->manager = $repo->getManager();
82
        $this->eventDispatcher = $eventDispatcher;
83
    }
84
85
    /**
86
     * @return CacheProvider
87
     */
88
    public function getCache()
89
    {
90
        return $this->cache;
91
    }
92
93
    /**
94
     * @param CacheProvider $cache
95
     */
96
    public function setCache($cache)
97
    {
98
        $this->cache = $cache;
99
    }
100
101
    /**
102
     * @return GenericCookie
103
     */
104
    public function getActiveProfilesCookie()
105
    {
106
        return $this->activeProfilesCookie;
107
    }
108
109
    /**
110
     * @param GenericCookie $activeProfilesCookie
111
     */
112
    public function setActiveProfilesCookie($activeProfilesCookie)
113
    {
114
        $this->activeProfilesCookie = $activeProfilesCookie;
115
    }
116
117
    /**
118
     * @return string
119
     */
120
    public function getActiveProfilesSettingName()
121
    {
122
        return $this->activeProfilesSettingName;
123
    }
124
125
    /**
126
     * @param string $activeProfilesSettingName
127
     */
128
    public function setActiveProfilesSettingName($activeProfilesSettingName)
129
    {
130
        $this->activeProfilesSettingName = $activeProfilesSettingName;
131
    }
132
133
    /**
134
     * Creates setting.
135
     *
136
     * @param array        $data
137
     *
138
     * @return Setting
139
     */
140
    public function create(array $data = [])
141
    {
142
        $data = array_filter($data);
143
        if (!isset($data['name']) || !isset($data['type'])) {
144
            throw new \LogicException('Missing one of the mandatory field!');
145
        }
146
147
        if (!isset($data['value'])) {
148
            $data['value'] = 0;
149
        }
150
151
        $name = $data['name'];
152
        $existingSetting = $this->get($name);
153
154
        if ($existingSetting) {
155
            throw new \LogicException(sprintf('Setting %s already exists.', $name));
156
        }
157
158
        $settingClass = $this->repo->getClassName();
159
        /** @var Setting $setting */
160
        $setting = new $settingClass();
161
162
        #TODO Introduce array populate function in Setting document instead of this foreach.
163
        foreach ($data as $key => $value) {
164
            $setting->{'set'.ucfirst($key)}($value);
165
        }
166
167
        $this->manager->persist($setting);
168
        $this->manager->commit();
169
170
        return $setting;
171
    }
172
173
    /**
174
     * Overwrites setting parameters with given name.
175
     *
176
     * @param string      $name
177
     * @param array       $data
178
     *
179
     * @return Setting
180
     */
181
    public function update($name, $data = [])
182
    {
183
        $setting = $this->get($name);
184
185
        if (!$setting) {
186
            throw new \LogicException(sprintf('Setting %s not exist.', $name));
187
        }
188
189
        #TODO Add populate function to document class
190
        foreach ($data as $key => $value) {
191
            $setting->{'set'.ucfirst($key)}($value);
192
        }
193
194
        $this->manager->persist($setting);
195
        $this->manager->commit();
196
197
        return $setting;
198
    }
199
200
    /**
201
     * Deletes a setting.
202
     *
203
     * @param string    $name
204
     *
205
     * @return array
206
     */
207
    public function delete($name)
208
    {
209
        $setting = $this->repo->findOneBy(['name' => $name]);
210
        return $this->repo->remove($setting->getId());
211
    }
212
213
    /**
214
     * Returns setting object.
215
     *
216
     * @param string $name
217
     *
218
     * @return Setting
219
     */
220
    public function get($name)
221
    {
222
        /** @var Setting $setting */
223
        $setting = $this->repo->findOneBy(['name' => $name]);
224
225
        return $setting;
226
    }
227
228
    /**
229
     * Returns setting object.
230
     *
231
     * @param string $name
232
     *
233
     * @return bool
234
     */
235
    public function has($name)
236
    {
237
        /** @var Setting $setting */
238
        $setting = $this->repo->findOneBy(['name' => $name]);
239
240
        if ($setting) {
241
            return true;
242
        }
243
244
        return false;
245
    }
246
247
    /**
248
     * Get setting value by current active profiles setting.
249
     *
250
     * @param string $name
251
     * @param bool $default
252
     *
253
     * @return mixed
254
     */
255
    public function getValue($name, $default = null)
256
    {
257
        $setting = $this->get($name);
258
259
        if ($setting) {
260
            return $setting->getValue();
261
        }
262
263
        return $default;
264
    }
265
266
    /**
267
     * Get all full profile information.
268
     *
269
     * @return array
270
     */
271
    public function getAllProfiles()
272
    {
273
        $profiles = [];
274
275
        $search = $this->repo->createSearch();
276
        $topHitsAgg = new TopHitsAggregation('documents', 20);
277
        $termAgg = new TermsAggregation('profiles', 'profile');
278
        $termAgg->addAggregation($topHitsAgg);
279
        $search->addAggregation($termAgg);
280
281
        $result = $this->repo->execute($search);
282
283
        /** @var Setting $activeProfiles */
284
        $activeProfiles = $this->getValue($this->activeProfilesSettingName, []);
0 ignored issues
show
Documentation introduced by
array() is of type array, but the function expects a boolean|null.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
285
286
        /** @var AggregationValue $agg */
287
        foreach ($result->getAggregation('profiles') as $agg) {
0 ignored issues
show
Bug introduced by
The method getAggregation does only exist in ONGR\ElasticsearchBundle\Result\DocumentIterator, but not in ONGR\ElasticsearchBundle\Result\RawIterator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
288
            $settings = [];
289
            $docs = $agg->getAggregation('documents');
290
            foreach ($docs['hits']['hits'] as $doc) {
291
                $settings[] = $doc['_source']['name'];
292
            }
293
            $name = $agg->getValue('key');
294
            $profiles[] = [
295
                'active' => $activeProfiles ? in_array($agg->getValue('key'), $activeProfiles) : false,
296
                'name' => $name,
297
                'settings' => implode(', ', $settings),
298
            ];
299
        }
300
301
        return $profiles;
302
    }
303
304
    /**
305
     * Get only profile names.
306
     *
307
     * @param bool $onlyActive
308
     *
309
     * @return array
310
     */
311
    public function getAllProfilesNameList($onlyActive = false)
312
    {
313
        $profiles = [];
314
        $allProfiles = $this->getAllProfiles();
315
316
        foreach ($allProfiles as $profile) {
317
            if ($onlyActive and !$profile['active']) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
Using logical operators such as and instead of && is generally not recommended.

PHP has two types of connecting operators (logical operators, and boolean operators):

  Logical Operators Boolean Operator
AND - meaning and &&
OR - meaning or ||

The difference between these is the order in which they are executed. In most cases, you would want to use a boolean operator like &&, or ||.

Let’s take a look at a few examples:

// Logical operators have lower precedence:
$f = false or true;

// is executed like this:
($f = false) or true;


// Boolean operators have higher precedence:
$f = false || true;

// is executed like this:
$f = (false || true);

Logical Operators are used for Control-Flow

One case where you explicitly want to use logical operators is for control-flow such as this:

$x === 5
    or die('$x must be 5.');

// Instead of
if ($x !== 5) {
    die('$x must be 5.');
}

Since die introduces problems of its own, f.e. it makes our code hardly testable, and prevents any kind of more sophisticated error handling; you probably do not want to use this in real-world code. Unfortunately, logical operators cannot be combined with throw at this point:

// The following is currently a parse error.
$x === 5
    or throw new RuntimeException('$x must be 5.');

These limitations lead to logical operators rarely being of use in current PHP code.

Loading history...
318
                continue;
319
            }
320
321
            $profiles[] = $profile['name'];
322
        }
323
324
        return $profiles;
325
    }
326
}
327