Completed
Pull Request — master (#1569)
by
unknown
04:30
created

Indexable   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 80.85%

Importance

Changes 0
Metric Value
wmc 19
lcom 1
cbo 2
dl 0
loc 141
ccs 38
cts 47
cp 0.8085
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A isObjectIndexable() 0 17 4
A buildCallback() 0 18 5
A buildExpressionCallback() 0 21 3
A getCallback() 0 8 2
A getExpressionLanguage() 0 8 2
A getExpressionVar() 0 10 2
1
<?php
2
3
/*
4
 * This file is part of the FOSElasticaBundle package.
5
 *
6
 * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
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 FOS\ElasticaBundle\Provider;
13
14
use Symfony\Component\ExpressionLanguage\Expression;
15
use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
16
use Symfony\Component\ExpressionLanguage\SyntaxError;
17
18
class Indexable implements IndexableInterface
19
{
20
    /**
21
     * An array of raw configured callbacks for all types.
22
     *
23
     * @var array
24
     */
25
    private $callbacks = [];
26
27
    /**
28
     * An instance of ExpressionLanguage.
29
     *
30
     * @var ExpressionLanguage
31
     */
32
    private $expressionLanguage;
33
34
    /**
35
     * An array of initialised callbacks.
36
     *
37
     * @var array
38
     */
39
    private $initialisedCallbacks = [];
40
41 15
    public function __construct(array $callbacks)
42
    {
43 15
        $this->callbacks = $callbacks;
44 15
    }
45
46
    /**
47
     * Return whether the object is indexable with respect to the callback.
48
     */
49 1
    public function isObjectIndexable(string $indexName, object $object): bool
50
    {
51 1
        if (!$callback = $this->getCallback($indexName, $object)) {
52
            return true;
53
        }
54
55 1
        if ($callback instanceof Expression) {
56 1
            return (bool) $this->getExpressionLanguage()->evaluate($callback, [
57 1
                'object' => $object,
58 1
                $this->getExpressionVar($object) => $object,
59
            ]);
60
        }
61
62 1
        return is_string($callback)
63 1
            ? call_user_func([$object, $callback])
64 1
            : call_user_func($callback, $object);
65
    }
66
67
    /**
68
     * Builds and initialises a callback.
69
     *
70
     * @return callable|string|ExpressionLanguage|null
71
     */
72 1
    private function buildCallback(string $index, object $object)
73
    {
74 1
        if (!array_key_exists($index, $this->callbacks)) {
75
            return null;
76
        }
77
78 1
        $callback = $this->callbacks[$index];
79
80 1
        if (is_callable($callback) or is_callable([$object, $callback])) {
81 1
            return $callback;
82
        }
83
84 1
        if (is_string($callback)) {
85 1
            return $this->buildExpressionCallback($index, $object, $callback);
86
        }
87
88
        throw new \InvalidArgumentException(sprintf('Callback for index "%s" is not a valid callback.', $index));
89
    }
90
91
    /**
92
     * Processes a string expression into an Expression.
93
     */
94 1
    private function buildExpressionCallback(string $index, object $object, string $callback): Expression
95
    {
96 1
        $expression = $this->getExpressionLanguage();
97 1
        if (!$expression) {
98
            throw new \RuntimeException('Unable to process an expression without the ExpressionLanguage component.');
99
        }
100
101
        try {
102 1
            $callback = new Expression($callback);
103 1
            $expression->compile($callback, [
104 1
                'object', $this->getExpressionVar($object),
105
            ]);
106
107 1
            return $callback;
108
        } catch (SyntaxError $e) {
109
            throw new \InvalidArgumentException(sprintf(
110
                'Callback for index "%s" is an invalid expression',
111
                $index
112
            ), $e->getCode(), $e);
113
        }
114
    }
115
116
    /**
117
     * Retreives a cached callback, or creates a new callback if one is not found.
118
     *
119
     * @return mixed
120
     */
121 1
    private function getCallback(string $index, object $object)
122
    {
123 1
        if (!array_key_exists($index, $this->initialisedCallbacks)) {
124 1
            $this->initialisedCallbacks[$index] = $this->buildCallback($index, $object);
125
        }
126
127 1
        return $this->initialisedCallbacks[$index];
128
    }
129
130
    /**
131
     * Returns the ExpressionLanguage class if it is available.
132
     */
133 1
    private function getExpressionLanguage(): ?ExpressionLanguage
134
    {
135 1
        if (null === $this->expressionLanguage) {
136 1
            $this->expressionLanguage = new ExpressionLanguage();
137
        }
138
139 1
        return $this->expressionLanguage;
140
    }
141
142
    /**
143
     * Returns the variable name to be used to access the object when using the ExpressionLanguage
144
     * component to parse and evaluate an expression.
145
     *
146
     * @param mixed $object
147
     */
148 1
    private function getExpressionVar($object = null): string
149
    {
150 1
        if (!is_object($object)) {
151
            return 'object';
152
        }
153
154 1
        $ref = new \ReflectionClass($object);
155
156 1
        return strtolower($ref->getShortName());
157
    }
158
}
159