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.
Passed
Pull Request — master (#62)
by Simone
02:21
created

JsonPathFinder::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 7
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 14
rs 9.4285
1
<?php
2
3
namespace Mado\QueryBundle\Component\Meta;
4
5
use Psr\Log\LoggerInterface;
6
7
/**
8
 * @since Class available since Release 2.1.0
9
 */
10
class JsonPathFinder
11
{
12
    const INDEX_ENTITY_PARENT = 0;
13
14
    const INDEX_FK_RELATION_NAME = 1;
15
16
    const INDEX_ENTITY_FIRST_CHILD = 2;
17
18
    private $map;
19
20
    private $entity;
21
22
    private $entitiesPath = [];
23
24
    private $wrongPath = [];
25
26
    private $mapper;
27
28
    private $appendRootEntityToSubject;
29
30
    private $incrementSubject;
31
32
    private $allPaths = [];
33
34
    private static $indexesToDescriptionMap = [
35
        self::INDEX_ENTITY_PARENT      => 'parent',
36
        self::INDEX_FK_RELATION_NAME   => 'relation',
37
        self::INDEX_ENTITY_FIRST_CHILD => 'first child',
38
    ];
39
40
    private $logger;
41
42
    public function __construct(
43
        DataMapper $mapper,
44
        LoggerInterface $logger = null
45
    ) {
46
        $this->mapper = $mapper;
47
        $this->logger = $logger;
48
49
        $this->appendRootEntityToSubject =  function($subject, $rootEntity) {
50
            $subject[] = $rootEntity;
51
            return $subject;
52
        };
53
54
        $this->incrementSubject = function($subject) {
55
            return ++$subject;
56
        };
57
    }
58
59
    public function setEntity(string $entity)
60
    {
61
        $this->entity = $entity;
62
    }
63
64
    public function getFirstParentOf(string $innerEntity)
65
    {
66
        $this->getMap();
67
68
        return $this->keep(
69
            self::INDEX_ENTITY_PARENT,
70
            $innerEntity
71
        );
72
    }
73
74
    public function getFirstChildOf(string $innerEntity)
75
    {
76
        return $this->keep(
77
            self::INDEX_ENTITY_FIRST_CHILD,
78
            $innerEntity
79
        );
80
    }
81
82
    public function getSourceRelation(string $innerEntity)
83
    {
84
        return $this->keep(
85
            self::INDEX_FK_RELATION_NAME,
86
            $innerEntity
87
        );
88
    }
89
90
    public function clearMap(string $innerEntity)
91
    {
92
        if (in_array($this->entity, $this->listOfParentsOf($innerEntity))) {
93
            foreach ($this->map as $rootEntity => $meta) {
94
                if ($this->entity != $rootEntity) {
95
                    unset($this->map[$rootEntity]);
96
                }
97
            }
98
        }
99
    }
100
101
    public function getPathTo(string $innerEntity = '', $nest = 0)
102
    {
103
        $this->entitiesPath[] = $innerEntity;
104
105
        $path = $this->getSourceRelation($innerEntity);
106
107
        if ($this->numberOfRelationsToEntity($innerEntity) != 1) {
108
            $this->clearMap($innerEntity);
109
        }
110
111
        if ($this->entity != $this->getFirstParentOf($innerEntity)) {
112
            if (!($relation = $this->getFirstParentOf($innerEntity))) {
113
                throw new Exceptions\UnreachablePathException(var_export([
114
                    'innerEntity' => $innerEntity,
115
                    'relation' => $relation,
116
                ], true));
117
            }
118
119
            if ($nest > 10) {
120
                // @codeCoverageIgnoreStart
121
                if ($this->logger) {
122
                    $this->logger->critical(json_encode([
123
                        'nest'         => $nest,
124
                        'entitiesPath' => $this->getEntitiesPath(),
125
                    ], true));
0 ignored issues
show
Bug introduced by
true of type true is incompatible with the type integer expected by parameter $options of json_encode(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
                    ], /** @scrutinizer ignore-type */ true));
Loading history...
126
                }
127
                // @codeCoverageIgnoreEnd
128
129
                throw new Exceptions\NestingException(
130
                    'Loop found in entities : ' .
131
                    var_export($this->getEntitiesPath(), true)
132
                );
133
            }
134
135
            return $this->getPathTo($relation, ++$nest) . '.' . $path;
136
        }
137
138
        return $path;
139
    }
140
141
    public function setQueryStartEntity(string $startEntity)
142
    {
143
        $this->setEntity($startEntity);
144
    }
145
146
    public function getPathToEntity(string $entityToReach, $reloadMap = false)
147
    {
148
        $this->entitiesPath = [];
149
150
        foreach ($this->getMap($reloadMap) as $rootEntity => $meta) {
151
            if (in_array($rootEntity, $this->wrongPath)) {
152
                unset($this->map[$rootEntity]);
153
            }
154
        }
155
156
        $return = '_embedded.' . $this->getPathTo($entityToReach);
157
158
        $this->allPaths[] = $this->entitiesPath;
159
160
        return $return;
161
    }
162
163
    public function keep($val, $innerEntity)
164
    {
165
        foreach ($this->getMap() as $rootEntity => $meta) {
166
            foreach ($meta['relations'] as $name => $entity) {
167
                if (self::INDEX_ENTITY_FIRST_CHILD == $val) {
168
                    return $entity;
169
                }
170
171
                if ($entity == $innerEntity) {
172
                    $return = [
173
                        self::INDEX_ENTITY_PARENT      => $rootEntity,
174
                        self::INDEX_FK_RELATION_NAME   => $name,
175
                    ][$val];
176
177
                    return $return;
178
                }
179
            }
180
        }
181
182
        throw new Exceptions\UnexpectedValueException(var_export([
183
            'val'         => self::$indexesToDescriptionMap[$val],
184
            'innerEntity' => $innerEntity,
185
            'map'         => $this->getMap(),
186
        ], true));
187
    }
188
189
    public function numberOfRelationsToEntity(string $entityToReach)
190
    {
191
        return $this->mapTargetRelations(
192
            $this->incrementSubject,
193
            $subject = 0,
194
            $entityToReach
195
        );
196
    }
197
198
    public function listOfParentsOf(string $entityToReach)
199
    {
200
        return $this->mapTargetRelations(
201
            $this->appendRootEntityToSubject,
202
            $subject = [],
203
            $entityToReach
204
        );
205
    }
206
207
    public function getEntitiesPath()
208
    {
209
        if (!$this->entitiesPath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->entitiesPath of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
210
            throw new Exceptions\UndefinedPathException(
211
                'Any path was requested'
212
            );
213
        }
214
215
        return $this->entitiesPath;
216
    }
217
218
    public function removeStep($parentToSkip)
219
    {
220
        $this->wrongPath[] = $parentToSkip;
221
    }
222
223
    public function getHashKeyForDestination(string $destination)
224
    {
225
        return md5($this->entity . $destination);
226
    }
227
228
    public function forceMapReloading()
229
    {
230
        $this->map = $this->mapper->getMap();
231
    }
232
233
    private function getMap($reloadMap = false)
234
    {
235
        if ($reloadMap || !$this->map) {
236
            $this->forceMapReloading();
237
        }
238
239
        return $this->map;
240
    }
241
242
    public function addEntity(array $parents, $rootEntity) : array
243
    {
244
        $parents[] = $rootEntity;
245
246
        return $parents;
247
    }
248
249
    public function mapTargetRelations(
250
        callable $action,
251
        $subject,
252
        string $entityToReach
253
    ) {
254
        foreach ($this->getMap() as $rootEntity => $meta) {
255
            foreach ($meta['relations'] as $name => $relationEntity) {
256
                if ($relationEntity == $entityToReach) {
257
                    $subject = $action($subject, $rootEntity);
258
                }
259
            }
260
        }
261
262
        return $subject;
263
    }
264
265
    public function getAllPaths() : array
266
    {
267
        array_multisort($this->allPaths);
268
        return $this->allPaths;
269
    }
270
271
    public function findAllPathsTo(string $dest)
272
    {
273
        while (true) {
274
            try {
275
                $this->getPathToEntity($dest);
276
                $entities = $this->getEntitiesPath();
277
                $lastEntityFound = end($entities);
278
                $this->removeStep($lastEntityFound);
279
            } catch(\Mado\QueryBundle\Component\Meta\Exceptions\UnexpectedValueException $e) {
280
                return;
281
            }
282
        }
283
    }
284
}
285