Completed
Push — master ( b8503d...c8d932 )
by Andreas
07:57
created

parameters   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 253
Duplicated Lines 0 %

Test Coverage

Coverage 77.91%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 81
dl 0
loc 253
ccs 67
cts 86
cp 0.7791
rs 10
c 2
b 0
f 0
wmc 30

6 Methods

Rating   Name   Duplication   Size   Complexity  
A get_parameter() 0 17 4
A list_parameters_domain() 0 23 4
A list_parameters() 0 12 3
A list_parameters_all() 0 30 5
B set_parameter() 0 31 8
A delete_parameter() 0 28 6
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(string $domain, string $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(string $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(string $domain, string $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) || empty($name)) {
205
            debug_add('Parameter domain and name must be non-empty strings', MIDCOM_LOG_WARN);
206
            return false;
207
        }
208
209 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

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