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.

QueryResultCollection::newTraversable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 1
1
<?php
2
3
namespace Pinq\Providers\Utilities;
4
5
use Pinq\Expressions as O;
6
use Pinq\PinqException;
7
use Pinq\Traversable;
8
9
/**
10
 * Implementation of the query results collection that will
11
 * cache the query results and is able to evaluate queries in memory
12
 * when applicable parent values are loaded:
13
 *
14
 * <code>
15
 * $someRows = $queryable->where(function ($row) { return $row['id'] <= 50; });
16
 *
17
 * foreach ($someRows as $row) {
18
 *     //This will load the values
19
 * }
20
 *
21
 * //This should be evaluated in memory
22
 * $filteredRows = $someRows->where(function ($row) { return $row['isActive'] === true; });
23
 * </code>
24
 *
25
 * @author Elliot Levin <[email protected]>
26
 */
27
class QueryResultCollection implements IQueryResultCollection
28
{
29
    /**
30
     * @var \SplObjectStorage
31
     */
32
    protected $storage;
33
34
    /**
35
     * @var callable
36
     */
37
    protected $traversableFactory;
38
39
    public function __construct(callable $traversableFactory = null)
40
    {
41
        $this->storage            = new \SplObjectStorage();
42
        $this->traversableFactory = $traversableFactory ?: Traversable::factory();
43
    }
44
45
    public function optimizeQuery(O\Expression $queryExpression)
46
    {
47
        //Converts all values requests (->asArray(), ->asIterator(), ->asCollection(), ->asTraversable())
48
        //to ->asTrueIterator() such that the true underlying values are retrieved
49
        //and hence can be cached as a Traversable instance such that any queries
50
        //on scoped values can be evaluated in memory using the traversable implementation.
51
        if ($queryExpression instanceof O\MethodCallExpression) {
52
            $nameExpression = $queryExpression->getName();
53
            if ($nameExpression instanceof O\ValueExpression) {
54
                switch (strtolower($nameExpression->getValue())) {
55
                    case 'asarray':
56
                    case 'asiterator':
57
                    case 'ascollection':
58
                    case 'astraversable':
59
                        return $queryExpression->update(
60
                                $queryExpression->getValue(),
61
                                O\Expression::value('getTrueIterator'),
62
                                $queryExpression->getArguments());
63
                }
64
            }
65
        }
66
67
        return $queryExpression;
68
    }
69
70
    protected function removeGetTrueIteratorCall(O\Expression $queryExpression)
71
    {
72
        //Removes the ->getTrueIterator() method call expression so when
73
        //searching for applicable results the expression will be a common ancestor
74
        if ($queryExpression instanceof O\MethodCallExpression) {
75
            $nameExpression = $queryExpression->getName();
76
            if ($nameExpression instanceof O\ValueExpression) {
77
                if (strtolower($nameExpression->getValue()) === 'gettrueiterator') {
78
                    return $queryExpression->getValue();
79
                }
80
            }
81
        }
82
83
        return $queryExpression;
84
    }
85
86
    public function saveResults(O\Expression $expression, $results)
87
    {
88
        $this->storage->attach($this->removeGetTrueIteratorCall($expression), $results);
89
    }
90
91
    public function clearResults()
92
    {
93
        $this->storage = new \SplObjectStorage();
94
    }
95
96
    public function removeResults(O\Expression $queryExpression)
97
    {
98
        unset($this->storage[$queryExpression]);
99
    }
100
101
    public function tryComputeResults(O\Expression $queryExpression, &$results)
102
    {
103
        if (isset($this->storage[$queryExpression])) {
104
            $results = $this->storage[$queryExpression];
105
106
            return true;
107
        }
108
109
        $foundApplicableResults = false;
110
111
        //Searches the query expression tree and checks if any parent expressions have saved results
112
        //If so, the expression tree is updated with a Traversable implementation with the saved results
113
        $applicableScopeFinder =
114
                function (O\Expression $expression, O\ExpressionWalker $self) use (&$foundApplicableResults) {
115
                    if (isset($this->storage[$expression])) {
116
                        $foundApplicableResults = true;
117
118
                        return O\Expression::value($this->newTraversable($this->storage[$expression]));
119
                    }
120
121
                    if ($expression instanceof O\ValueExpression) {
122
                        return $expression;
123
                    }
124
125
                    /** @var $expression O\TraversalExpression */
126
127
                    return $expression->updateValue($self->walk($expression->getValue()));
128
                };
129
130
        $traversalWalker = new O\DynamicExpressionWalker([
131
                O\TraversalExpression::getType() => $applicableScopeFinder,
132
                O\ValueExpression::getType()     => $applicableScopeFinder
133
        ]);
134
135
        $remainingQueryExpression = $traversalWalker->walk($queryExpression);
136
137
        //If found applicable results, execute the updated expression tree against the Traversable
138
        //implementation to compute the result of the query.
139
        $results = $foundApplicableResults ? $remainingQueryExpression->evaluate() : null;
140
141
        return $foundApplicableResults;
142
    }
143
144
    public function computeResults(O\Expression $expression)
145
    {
146
        if ($this->tryComputeResults($expression, $results)) {
147
            return $results;
148
        }
149
150
        throw new PinqException(
151
                'Could not compute query results: no applicable saved results found for the query expression, %s',
152
                $expression->compileDebug());
153
    }
154
155
    protected function newTraversable($values)
156
    {
157
        $factory = $this->traversableFactory;
158
159
        return $factory($values);
160
    }
161
}
162