Completed
Push — master ( 9c6f05...775967 )
by Andreas
17:56
created

parameters   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 263
Duplicated Lines 0 %

Test Coverage

Coverage 77.66%

Importance

Changes 0
Metric Value
eloc 91
dl 0
loc 263
ccs 73
cts 94
cp 0.7766
rs 9.68
c 0
b 0
f 0
wmc 34

6 Methods

Rating   Name   Duplication   Size   Complexity  
A get_parameter() 0 17 4
A list_parameters_domain() 0 23 4
B delete_parameter() 0 33 8
B set_parameter() 0 36 10
A list_parameters() 0 12 3
A list_parameters_all() 0 30 5
1
<?php
2
/**
3
 * @package midcom.dba
4
 * @author CONTENT CONTROL http://www.contentcontrol-berlin.de/
5
 * @copyright CONTENT CONTROL http://www.contentcontrol-berlin.de/
6
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License
7
 */
8
9
namespace midcom\dba;
10
11
use midcom_connection;
12
use midgard_parameter;
13
use midcom;
14
use midcom\events\dbaevent;
15
16
/**
17
 * midcom parameter support
18
 *
19
 * @package midcom.dba
20
 */
21
trait parameters
22
{
23
    private static $parameter_cache = [];
24
    private static $parameter_all = [];
25
26
    /**
27
     * Return a parameter from the database.
28
     *
29
     * No event handlers are called here yet.
30
     *
31
     * @param string $domain The parameter domain.
32
     * @param string $name The parameter name.
33
     * @return ?string The parameter value or false otherwise (remember typesafe comparisons to protect against '' strings).
34
     */
35 268
    public function get_parameter($domain, $name)
36
    {
37 268
        if (!$this->guid) {
38 34
            debug_add('Cannot retrieve information on a non-persistent object.', MIDCOM_LOG_INFO);
39 34
            return false;
40
        }
41
42 235
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
43
            // We have this domain in cache already thanks to some parameter listing
44 2
            if (!isset(self::$parameter_cache[$this->guid][$domain][$name])) {
45 2
                return null;
46
            }
47
            return self::$parameter_cache[$this->guid][$domain][$name];
48
        }
49
50
        // Not in cache, query from MgdSchema API directly
51 233
        return $this->__object->get_parameter($domain, $name);
52
    }
53
54
    /**
55
     * List the parameters of an object. This will either list the parameters of
56
     * a single domain or the complete set of parameters, depending on the value
57
     * of $domain.
58
     *
59
     * It delegates the actual execution to two separate helper functions.
60
     *
61
     * No event handlers are called here yet.
62
     *
63
     * In case of a complete query, the result will be an associative array indexed
64
     * by the domain name and containing another array with parameter name/value pairs.
65
     * For example:
66
     *
67
     * <pre>
68
     * Array
69
     * (
70
     *     [Asgard] => Array
71
     *     (
72
     *         [lang] => en_US
73
     *         [act] => view
74
     *         [actloc] => tree
75
     *     )
76
     *     [AsgardTreeHost] => Array
77
     *     (
78
     *         [selected] => host0
79
     *     )
80
     * )
81
     * </pre>
82
     *
83
     * If you query only a single domain, the result will be a single associative
84
     * array containing the parameter name/value pairs. For example:
85
     *
86
     * <pre>
87
     * Array
88
     * (
89
     *     [lang] => en_US
90
     *     [act] => view
91
     *     [actloc] => tree
92
     * )
93
     * </pre>
94
     *
95
     * In both cases an empty Array will indicate that no parameter was found, while
96
     * false will indicate a failure while querying the database.
97
     *
98
     * @param string $domain The parameter domain to query, this may be null to indicate a full listing.
99
     */
100 383
    public function list_parameters($domain = null) : array
101
    {
102 383
        if (!$this->guid) {
103 5
            debug_add('Cannot retrieve information on a non-persistent object.', MIDCOM_LOG_INFO);
104 5
            return [];
105
        }
106
107 379
        if ($domain !== null) {
108 379
            return $this->list_parameters_domain($domain);
109
        }
110
111 1
        return $this->list_parameters_all();
112
    }
113
114
    /**
115
     * List the parameters of a single domain of an object.
116
     *
117
     * No event handlers are called here yet.
118
     *
119
     * @see list_parameters()
120
     */
121 379
    private function list_parameters_domain(string $domain) : array
122
    {
123 379
        if (!isset(self::$parameter_cache[$this->guid])) {
124 107
            self::$parameter_cache[$this->guid] = [];
125
        }
126
127 379
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
128 356
            return self::$parameter_cache[$this->guid][$domain];
129
        }
130
131 110
        self::$parameter_cache[$this->guid][$domain] = [];
132
133 110
        $mc = midgard_parameter::new_collector('parentguid', $this->guid);
134 110
        $mc->set_key_property('name');
135 110
        $mc->add_value_property('value');
136 110
        $mc->add_constraint('domain', '=', $domain);
137 110
        $mc->execute();
138
139 110
        foreach ($mc->list_keys() as $name => $values) {
140 6
            self::$parameter_cache[$this->guid][$domain][$name] = $mc->get_subkey($name, 'value');
141
        }
142
143 110
        return self::$parameter_cache[$this->guid][$domain];
144
    }
145
146
    /**
147
     * List all parameters of an object.
148
     *
149
     * No event handlers are called here yet.
150
     *
151
     * @see list_parameters()
152
     */
153 1
    private function list_parameters_all() : array
154
    {
155 1
        if (!isset(self::$parameter_cache[$this->guid])) {
156
            self::$parameter_cache[$this->guid] = [];
157
        }
158
159 1
        if (!isset(self::$parameter_all[$this->guid])) {
160 1
            $mc = midgard_parameter::new_collector('parentguid', $this->guid);
161 1
            $mc->set_key_property('guid');
162 1
            $mc->add_value_property('domain');
163 1
            $mc->add_value_property('name');
164 1
            $mc->add_value_property('value');
165 1
            $mc->execute();
166
167 1
            foreach ($mc->list_keys() as $guid => $values) {
168
                $name = $mc->get_subkey($guid, 'name');
169
                $domain = $mc->get_subkey($guid, 'domain');
170
171
                if (!isset(self::$parameter_cache[$this->guid][$domain])) {
172
                    self::$parameter_cache[$this->guid][$domain] = [];
173
                }
174
175
                self::$parameter_cache[$this->guid][$domain][$name] = $mc->get_subkey($guid, 'value');
176
            }
177
178
            // Flag that we have queried all domains for this object
179 1
            self::$parameter_all[$this->guid] = true;
180
        }
181
        // Clean up empty arrays
182 1
        return array_filter(self::$parameter_cache[$this->guid], 'count');
183
    }
184
185
    /**
186
     * Set a parameter to the value specified.
187
     *
188
     * This is either a create or an update operation depending on whether there was
189
     * already a parameter of that domain/name present, or not.
190
     *
191
     * The user needs both update and parameter manipulation permission on the parent object for updates.
192
     *
193
     * @param string $domain The Parameter Domain.
194
     * @param string $name The Parameter name.
195
     * @param string $value The Parameter value. If this is empty, the corresponding parameter is deleted.
196
     * @return bool Indicating success.
197
     */
198 63
    public function set_parameter($domain, $name, $value) : bool
199
    {
200 63
        if (!$this->guid) {
201 1
            debug_add('Cannot set parameters on a non-persistent object.', MIDCOM_LOG_WARN);
202 1
            return false;
203
        }
204 62
        if (   empty($domain)
205 62
            || empty($name)
206 62
            || !is_string($domain)
207 62
            || !is_string($name)) {
208
            debug_add('Parameter domain and name must be non-empty strings', MIDCOM_LOG_WARN);
209
            debug_print_r('$domain', $domain);
210
            debug_print_r('$name', $name);
211
            return false;
212
        }
213
214 62
        if (   !$this->can_do('midgard:update')
0 ignored issues
show
Bug introduced by
It seems like can_do() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

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

214
        if (   !$this->/** @scrutinizer ignore-call */ can_do('midgard:update')
Loading history...
215 62
            || !$this->can_do('midgard:parameters')) {
216 2
            debug_add("Failed to set parameters, midgard:update or midgard:parameters on the " . get_class($this) . " {$this->guid} not granted for the current user.",
217 2
                      MIDCOM_LOG_ERROR);
218 2
            midcom_connection::set_error(MGD_ERR_ACCESS_DENIED);
219 2
            return false;
220
        }
221
222
        // Set via MgdSchema API directly
223 60
        if (!$this->__object->set_parameter($domain, $name, (string) $value)) {
224 3
            return false;
225
        }
226
227 59
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
228 13
            self::$parameter_cache[$this->guid][$domain][$name] = $value;
229
        }
230
231 59
        midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::PARAMETER);
232
233 59
        return true;
234
    }
235
236
    /**
237
     * Delete a parameter.
238
     *
239
     * Current implementation note: Deletion is not yet implemented in MgdSchema.
240
     * Therefore we set the parameters to an empty string for now, which should
241
     * have almost the same effect for most cases and thus is good enough for now.
242
     * Note, that empty string parameters are filtered in the getter methods until
243
     * this matter is resolved.
244
     *
245
     * The user needs both update and parameter manipulation permission on the parent object for updates.
246
     *
247
     * @param string $domain The Parameter Domain.
248
     * @param string $name The Parameter name.
249
     * @return bool Indicating success.
250
     */
251 2
    public function delete_parameter($domain, $name) : bool
252
    {
253 2
        if (!$this->guid) {
254
            debug_add('Cannot delete parameters on a non-persistent object.', MIDCOM_LOG_WARN);
255
            return false;
256
        }
257 2
        if (   empty($domain)
258 2
            || empty($name)
259 2
            || !is_string($domain)
260 2
            || !is_string($name)) {
261
            debug_add('Parameter domain and name must be non-empty strings', MIDCOM_LOG_WARN);
262
            debug_print_r('$domain', $domain);
263
            debug_print_r('$name', $name);
264
            return false;
265
        }
266
267 2
        if (   !$this->can_do('midgard:update')
268 2
            || !$this->can_do('midgard:parameters')) {
269
            debug_add("Failed to delete parameters, midgard:update or midgard:parameters on the " . get_class($this) . " {$this->guid} not granted for the current user.",
270
                      MIDCOM_LOG_ERROR);
271
            midcom_connection::set_error(MGD_ERR_ACCESS_DENIED);
272
            return false;
273
        }
274
275
        // Invalidate run-time cache
276 2
        unset(self::$parameter_cache[$this->guid][$domain]);
277
278
        // Unset via MgdSchema API directly
279 2
        $result = $this->__object->set_parameter($domain, $name, '');
280
281 2
        midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::PARAMETER);
282
283 2
        return $result;
284
    }
285
}
286