Passed
Push — master ( 622e79...efafc0 )
by Andreas
03:31
created

midgard_collector   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 172
Duplicated Lines 0 %

Test Coverage

Coverage 92.54%

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 63
c 7
b 0
f 0
dl 0
loc 172
ccs 62
cts 67
cp 0.9254
rs 10
wmc 27

9 Methods

Rating   Name   Duplication   Size   Complexity  
A get() 0 3 1
A build_property_select() 0 20 5
A set_key_property() 0 9 2
A __construct() 0 5 2
A list_keys() 0 6 2
A _has_results() 0 4 1
B execute() 0 45 9
A add_value_property() 0 14 4
A get_subkey() 0 3 1
1
<?php
2
/**
3
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
4
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
6
 */
7
8
use midgard\portable\api\error\exception;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, exception. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
use midgard\portable\storage\connection;
10
11
class midgard_collector extends midgard_query_builder
12
{
13
    /**
14
     * the results determined by execute
15
     *
16
     * @var array
17
     */
18
    private $_results = null;
19
20
    /**
21
     *
22
     * @var string
23
     */
24
    private $key_property = "guid";
25
26
    private $value_properties = [];
27
28 11
    public function __construct($class, $field = null, $value = null)
29
    {
30 11
        parent::__construct($class);
31 11
        if ($field) {
32 11
            $this->add_constraint($field, '=', $value);
33
        }
34 11
    }
35
36
    /**
37
     * @param string $property
38
     * @return boolean
39
     */
40 5
    public function set_key_property($property)
41
    {
42
        // after execute there is no sense in changing the key property
43 5
        if ($this->_results !== null) {
44
            return false;
45
        }
46 5
        $this->key_property = $property;
47
48 5
        return true;
49
    }
50
51
    /**
52
     * @param string $property
53
     * @return boolean
54
     */
55 6
    public function add_value_property($property)
56
    {
57 6
        if ($this->_results !== null) {
58
            return false;
59
        }
60
61 6
        if (!isset($this->value_properties[$property])) {
62
            try {
63 6
                $this->value_properties[$property] = $this->build_property_select($property);
64 1
            } catch (exception $e) {
65 1
                return false;
66
            }
67
        }
68 5
        return true;
69
    }
70
71 10
    protected function build_property_select($property)
72
    {
73 10
        $parsed = $this->parse_constraint_name($property);
74
75
        // for properties like up.name
76 9
        if (   strpos($property, ".") !== false
77 9
            && !(strpos($property, "metadata") === 0)) {
78 1
            return $parsed['name'] . " as " . str_replace(".", "_", $property);
79
        }
80
81 9
        $cm = connection::get_em()->getClassMetadata($this->classname);
82 9
        if (array_key_exists($property, $cm->midgard['field_aliases'])) {
83 1
            return $parsed['name'] . " as " . str_replace(".", "_", $property);
84
        }
85
86 9
        if ($cm->hasAssociation($property)) {
87 1
            return 'IDENTITY(' . $parsed['name'] . ") as " . $property;
88
        }
89
90 9
        return $parsed['name'];
91
    }
92
93
    /**
94
     * @return boolean
95
     */
96 8
    public function execute()
97
    {
98 8
        if ($this->_results !== null) {
99
            return false;
100
        }
101 8
        $this->check_groups();
102 8
        $properties = $this->value_properties;
103 8
        if (!isset($this->value_properties[$this->key_property])) {
104
            try {
105 7
                $properties[] = $this->build_property_select($this->key_property);
106
            } catch (exception $e) {
107
                throw new exception('Property "' . $this->key_property . '" not found in "' . $this->classname . '"', exception::INVALID_PROPERTY, $e);
108
            }
109
        }
110
111 8
        $this->qb->addSelect(implode(", ", $properties));
112 8
        $this->pre_execution();
113 8
        $results = $this->qb->getQuery()->getArrayResult();
114 8
        $this->post_execution();
115
116 8
        $cm = connection::get_em()->getClassMetadata($this->classname);
117
        // map results by current key property
118 8
        $results_map = [];
119 8
        foreach ($results as $result) {
120 8
            foreach ($result as $key => &$value) {
121
                // for metadata fields remove the "metadata_" prefix
122 8
                if (strpos($key, "metadata_") !== false) {
123 1
                    $result[str_replace("metadata_", "", $key)] = $value;
124 1
                    unset($result[$key]);
125
                }
126
                // TODO: find out why Doctrine doesn't do this on its own
127 8
                if ($cm->hasAssociation($key)) {
128 1
                    $value = (int) $value;
129
                }
130
            }
131 8
            $key = $result[$this->key_property];
132 8
            if (!isset($this->value_properties[$this->key_property])) {
133 7
                unset($result[$this->key_property]);
134
            }
135
136 8
            $results_map[$key] = $result;
137
        }
138
139 8
        $this->_results = $results_map;
140 8
        return true;
141
    }
142
143
    /**
144
     *
145
     * @param string $key
146
     * @return array
147
     */
148 2
    public function get($key)
149
    {
150 2
        return $this->_results[$key] ?? false;
151
    }
152
153
    /**
154
     *
155
     * @param string $key
156
     * @param string $property
157
     */
158 2
    public function get_subkey($key, $property)
159
    {
160 2
        return $this->_results[$key][$property] ?? false;
161
    }
162
163
    /**
164
     * check whether we got any results to work on
165
     *
166
     * @return boolean
167
     */
168 8
    private function _has_results()
169
    {
170
        // execute was not called or we got an empty resultset
171 8
        return !empty($this->_results);
172
    }
173
174
    /**
175
     * @return array
176
     */
177 8
    public function list_keys()
178
    {
179 8
        if (!$this->_has_results()) {
180 1
            return [];
181
        }
182 8
        return array_fill_keys(array_keys($this->_results), '');
183
    }
184
}
185