GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 9c36c2...03eb4b )
by Anderson
02:16
created

ElasticConnection::unsetEmpties()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 15
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 15
rs 8.8571
c 0
b 0
f 0
cc 6
eloc 9
nc 6
nop 2
1
<?php
2
3
namespace DoctrineElastic\Connection;
4
5
use Elasticsearch\Client;
6
7
/**
8
 * Default elastic connection class for general operations
9
 * Notice that the original elastic result of most of operations can be get by $return param
10
 *
11
 * @author Ands
12
 */
13
class ElasticConnection implements ElasticConnectionInterface {
14
15
    /** Override default elastic limit size query */
16
    const DEFAULT_MAX_RESULTS = 10000;
17
18
    /** @var Client */
19
    protected $elastic;
20
21
    public function __construct(Client $elastic) {
22
        $this->elastic = $elastic;
23
    }
24
25
    /**
26
     * @param string $index
27
     * @param array|null $mappings
28
     * @param array|null $settings
29
     * @param array|null $aliases
30
     * @param array|null $return
31
     * @return bool
32
     */
33
    public function createIndex(
34
        $index, array $mappings = null, array $settings = null, array $aliases = null, array &$return = null
35
    ) {
36
        if ($this->indexExists($index)) {
37
            throw new \InvalidArgumentException(sprintf("'%s' index already exists", $index));
38
        }
39
40
        $params = array(
41
            'index' => $index,
42
            'update_all_types' => true,
43
            'body' => []
44
        );
45
46
        if (boolval($mappings)) {
47
            foreach ($mappings as $typeName => $mapping) {
0 ignored issues
show
Bug introduced by
The expression $mappings of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
48
                $properties = $mapping['properties'];
49
50
                foreach ($properties as $fieldName => $fieldMap) {
51
                    if (isset($fieldMap['type']) && in_array($fieldMap['type'], ['string', 'text', 'keyword'])) {
52
                        continue;
53
                    }
54
55 View Code Duplication
                    if (isset($mappings[$typeName]['properties'][$fieldName]['index'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
56
                        unset($mappings[$typeName]['properties'][$fieldName]['index']);
57
                    }
58
59 View Code Duplication
                    if (isset($mappings[$typeName]['properties'][$fieldName]['boost'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
60
                        unset($mappings[$typeName]['properties'][$fieldName]['boost']);
61
                    }
62
                }
63
            }
64
            $params['body']['mappings'] = $mappings;
65
        }
66
67
        if (boolval($settings)) {
68
            $params['body']['settings'] = $settings;
69
        }
70
71
        $return = $this->elastic->indices()->create($params);
72
73
        if (isset($return['acknowledged'])) {
74
            return $return['acknowledged'];
75
        }
76
77
        return false;
78
    }
79
80
    /**
81
     * @param string $index
82
     * @param array|null $return
83
     * @return bool
84
     */
85
    public function deleteIndex($index, array &$return = null) {
86
        if (!$this->indexExists($index)) {
87
            throw new \InvalidArgumentException(sprintf("'%s' index does not exists", $index));
88
        }
89
90
        if (is_string($index) && !strstr('_all', $index) && !strstr('*', $index)) {
91
            $return = $this->elastic->indices()->delete(['index' => $index]);
92
93
            if (isset($return['acknowledged'])) {
94
                return $return['acknowledged'];
95
            }
96
        }
97
98
        return false;
99
    }
100
101
    /**
102
     * @param string $index
103
     * @param string $type
104
     * @param array $mappings
105
     * @param array|null $return
106
     * @return bool
107
     */
108
    public function createType($index, $type, array $mappings = [], array &$return = null) {
109
        if (!$this->indexExists($index)) {
110
            throw new \InvalidArgumentException(sprintf("%s' index does not exists", $index));
111
        }
112
113
        if ($this->typeExists($index, $type)) {
114
            throw new \InvalidArgumentException(sprintf("Type 's%' already exists on index %s", $type, $index));
115
        }
116
117
        $return = $this->elastic->indices()->putMapping(array(
118
            'index' => $index,
119
            'type' => $type,
120
            'update_all_types' => true,
121
            'body' => $mappings
122
        ));
123
124
        if (isset($return['acknowledged'])) {
125
            return $return['acknowledged'];
126
        }
127
128
        return false;
129
    }
130
131
    /**
132
     * @param string $index
133
     * @param string $type
134
     * @param array $body
135
     * @param array $mergeParams
136
     * @param array|null $return
137
     * @return bool
138
     */
139
    public function insert($index, $type, array $body, array $mergeParams = [], array &$return = null) {
140
        if (!$this->indexExists($index)) {
141
            trigger_error("$index index does not exists at insert attempt");
142
            return false;
143
        }
144
145
        if (!$this->typeExists($index, $type)) {
146
            trigger_error("$type type does not exists at insert attempt");
147
            return false;
148
        }
149
150
        $defaultParams = array(
151
            'index' => $index,
152
            'type' => $type,
153
            'op_type' => 'create',
154
            'timestamp' => time(),
155
            'refresh' => "true",
156
            'body' => $body
157
        );
158
159
        $params = array_merge_recursive($defaultParams, $mergeParams);
160
161
        $return = $this->elastic->create($params);
162
163
        if (isset($return['created'])) {
164
            return $return['created'];
165
        }
166
167
        return false;
168
    }
169
170
    /**
171
     * @param string $index
172
     * @param string $type
173
     * @param string $_id
174
     * @param array $body
175
     * @param array $mergeParams
176
     * @param array|null $return
177
     *
178
     * @return bool
179
     */
180
    public function update($index, $type, $_id, array $body = [], array $mergeParams = [], array &$return = null) {
181
        if (!$this->indexExists($index)) {
182
            return false;
183
        }
184
185
        $defaultParams = array(
186
            'id' => $_id,
187
            'index' => $index,
188
            'type' => $type,
189
            'refresh' => "true",
190
            'body' => array(
191
                'doc' => $body
192
            )
193
        );
194
195
        $params = array_merge_recursive($defaultParams, $mergeParams);
196
197
        $return = $this->elastic->update($params);
198
199
        if (isset($return['_id'])) {
200
            return true;
201
        }
202
203
        return false;
204
    }
205
206
    /**
207
     * @param string $index
208
     * @param string $type
209
     * @param string $_id
210
     * @param array $mergeParams
211
     * @param array|null $return
212
     * @return bool
213
     */
214
    public function delete($index, $type, $_id, array $mergeParams = [], array &$return = null) {
215
        if (!$this->indexExists($index)) {
216
            return false;
217
        }
218
219
        $defaultParams = array(
220
            'id' => $_id,
221
            'index' => $index,
222
            'type' => $type,
223
            'refresh' => "true"
224
        );
225
226
        $params = array_merge_recursive($defaultParams, $mergeParams);
227
228
        $return = $this->elastic->delete($params);
229
230
        if (isset($return['found']) && isset($return['_shards']['successful'])) {
231
            return boolval($return['_shards']['successful']);
232
        }
233
234
        return false;
235
    }
236
237
    public function updateWhere($index, $type, array $where, array &$return = null) {
238
        // TODO
239
    }
240
241
    public function deleteWhere($index, $type, array $where, array &$return = null) {
242
        // TODO
243
    }
244
245
    /**
246
     *
247
     * @param string $index
248
     * @param string $type
249
     * @param string $_id
250
     * @param array $mergeParams
251
     * @param array|null $return
252
     * @return array|null
253
     */
254
    public function get($index, $type, $_id, array $mergeParams = [], array &$return = null) {
255
        if (!$this->indexExists($index)) {
256
            return null;
257
        }
258
259
        $defaultParams = array(
260
            'id' => $_id,
261
            'index' => $index,
262
            'type' => $type,
263
            'refresh' => "true",
264
            '_source' => true,
265
            '_source_exclude' => []
266
        );
267
268
        $params = array_merge_recursive($defaultParams, $mergeParams);
269
        $existsParams = array_filter($params, function ($key) {
270
            return in_array($key, ['id', 'index', 'type', 'refresh']);
271
        }, ARRAY_FILTER_USE_KEY);
272
273
        if ($this->elastic->exists($existsParams)) {
274
            $return = $this->elastic->get($params);
275
276
            if (isset($return['found']) && $return['found']) {
277
                return $return;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $return; (callable) is incompatible with the return type declared by the interface DoctrineElastic\Connecti...onnectionInterface::get of type array|null.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
278
            }
279
        }
280
281
        return null;
282
    }
283
284
    /**
285
     * Returns the [hits][hits] array from query
286
     *
287
     * @param string $index
288
     * @param string $type
289
     * @param array $body
290
     * @param array $mergeParams
291
     * @param array|null $return
292
     * @return array
293
     */
294
    public function search($index, $type, array $body = [], array $mergeParams = [], array &$return = null) {
295
        if (!$this->indexExists($index)) {
296
            return [];
297
        }
298
299
        $defaultParams = array(
300
            'index' => $index,
301
            'type' => $type,
302
            '_source' => true,
303
            'query_cache' => false,
304
            'request_cache' => false,
305
            'default_operator' => 'AND',
306
            'size' => self::DEFAULT_MAX_RESULTS,
307
            'body' => $body
308
        );
309
310
        $params = array_replace_recursive($defaultParams, $mergeParams);
311
312
        $this->unsetEmpties($params['body']);
313
314
        if (empty($params['body'])) {
315
            unset($params['body']);
316
        }
317
318
        $return = $this->elastic->search($params);
319
320
        if (isset($return['hits']['hits'])) {
321
            return $return['hits']['hits'];
322
        }
323
324
        return [];
325
    }
326
327
    private function unsetEmpties(array &$array, array &$parent = null) {
328
        for ($count = 2; $count > 0; $count--) {
329
            foreach ($array as $key => $item) {
0 ignored issues
show
Bug introduced by
The expression $array of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
330
                if (empty($item)) {
331
                    unset($array[$key]);
332
333
                    if (is_array($parent)) {
334
                        $this->unsetEmpties($parent);
335
                    }
336
                } else if (is_array($item)) {
337
                    $this->unsetEmpties($array[$key], $array);
338
                }
339
            }
340
        }
341
    }
342
343
    /**
344
     * @param string $index
345
     * @return bool
346
     */
347
    public function indexExists($index) {
348
        return $this->elastic->indices()->exists(['index' => $index]);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->elastic->indices(...ay('index' => $index)); of type boolean|callable adds the type callable to the return on line 348 which is incompatible with the return type declared by the interface DoctrineElastic\Connecti...nInterface::indexExists of type boolean.
Loading history...
349
    }
350
351
    /**
352
     * @param string $index
353
     * @param string $type
354
     * @return bool
355
     */
356
    public function typeExists($index, $type) {
357
        $return = $this->elastic->indices()->existsType(array(
358
            'index' => $index,
359
            'type' => $type,
360
            'ignore_unavailable' => true
361
        ));
362
363
        return boolval($return);
364
    }
365
366
    /**
367
     * @return Client
368
     */
369
    public function getElasticClient() {
370
        return $this->elastic;
371
    }
372
}
373