Issues (806)

src/midcom/dba/parameters.php (2 issues)

Labels
Severity
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 array $parameter_cache = [];
24
    private static array $parameter_all = [];
25
26
    /**
27
     * Return a parameter from the database.
28
     *
29
     * @return ?string The parameter value or null otherwise (remember typesafe comparisons to protect against '' strings).
30
     */
31 186
    public function get_parameter(string $domain, string $name)
32
    {
33 186
        if (!$this->guid) {
34 21
            debug_add('Cannot retrieve information on a non-persistent object.', MIDCOM_LOG_INFO);
35 21
            return null;
36
        }
37
38 166
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
39
            // We have this domain in cache already thanks to some parameter listing
40 2
            if (!isset(self::$parameter_cache[$this->guid][$domain][$name])) {
41 2
                return null;
42
            }
43
            return self::$parameter_cache[$this->guid][$domain][$name];
44
        }
45
46
        // Not in cache, query from MgdSchema API directly
47 164
        return $this->__object->get_parameter($domain, $name);
48
    }
49
50
    /**
51
     * List the parameters of an object. This will either list the parameters of
52
     * a single domain or the complete set of parameters, depending on the value
53
     * of $domain.
54
     *
55
     * It delegates the actual execution to two separate helper functions.
56
     *
57
     * No event handlers are called here yet.
58
     *
59
     * In case of a complete query, the result will be an associative array indexed
60
     * by the domain name and containing another array with parameter name/value pairs.
61
     * For example:
62
     *
63
     * <pre>
64
     * Array
65
     * (
66
     *     [Asgard] => Array
67
     *     (
68
     *         [lang] => en_US
69
     *         [act] => view
70
     *         [actloc] => tree
71
     *     )
72
     *     [AsgardTreeHost] => Array
73
     *     (
74
     *         [selected] => host0
75
     *     )
76
     * )
77
     * </pre>
78
     *
79
     * If you query only a single domain, the result will be a single associative
80
     * array containing the parameter name/value pairs. For example:
81
     *
82
     * <pre>
83
     * Array
84
     * (
85
     *     [lang] => en_US
86
     *     [act] => view
87
     *     [actloc] => tree
88
     * )
89
     * </pre>
90
     *
91
     * In both cases an empty Array will indicate that no parameter was found, while
92
     * false will indicate a failure while querying the database.
93
     *
94
     * @param string $domain The parameter domain to query, this may be null to indicate a full listing.
95
     */
96 409
    public function list_parameters(?string $domain = null) : array
97
    {
98 409
        if (!$this->guid) {
99 7
            debug_add('Cannot retrieve information on a non-persistent object.', MIDCOM_LOG_INFO);
100 7
            return [];
101
        }
102
103 405
        if ($domain !== null) {
104 404
            return $this->list_parameters_domain($domain);
105
        }
106
107 2
        return $this->list_parameters_all();
108
    }
109
110
    /**
111
     * List the parameters of a single domain of an object.
112
     *
113
     * No event handlers are called here yet.
114
     *
115
     * @see list_parameters()
116
     */
117 404
    private function list_parameters_domain(string $domain) : array
118
    {
119 404
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
120 379
            return self::$parameter_cache[$this->guid][$domain];
121
        }
122
123 114
        self::$parameter_cache[$this->guid] ??= [];
124 114
        self::$parameter_cache[$this->guid][$domain] = [];
125
126 114
        $mc = midgard_parameter::new_collector('parentguid', $this->guid);
127 114
        $mc->set_key_property('name');
128 114
        $mc->add_value_property('value');
129 114
        $mc->add_constraint('domain', '=', $domain);
130 114
        $mc->execute();
131
132 114
        foreach ($mc->list_keys() as $name => $values) {
133 6
            self::$parameter_cache[$this->guid][$domain][$name] = $mc->get_subkey($name, 'value');
134
        }
135
136 114
        return self::$parameter_cache[$this->guid][$domain];
137
    }
138
139
    /**
140
     * List all parameters of an object.
141
     *
142
     * No event handlers are called here yet.
143
     *
144
     * @see list_parameters()
145
     */
146 2
    private function list_parameters_all() : array
147
    {
148 2
        self::$parameter_cache[$this->guid] ??= [];
149
150 2
        if (!isset(self::$parameter_all[$this->guid])) {
151 2
            $mc = midgard_parameter::new_collector('parentguid', $this->guid);
152 2
            $mc->set_key_property('guid');
153 2
            $mc->add_value_property('domain');
154 2
            $mc->add_value_property('name');
155 2
            $mc->add_value_property('value');
156 2
            $mc->execute();
157
158 2
            foreach ($mc->list_keys() as $guid => $values) {
159 1
                $name = $mc->get_subkey($guid, 'name');
160 1
                $domain = $mc->get_subkey($guid, 'domain');
161
162 1
                self::$parameter_cache[$this->guid][$domain] ??= [];
163 1
                self::$parameter_cache[$this->guid][$domain][$name] = $mc->get_subkey($guid, 'value');
164
            }
165
166
            // Flag that we have queried all domains for this object
167 2
            self::$parameter_all[$this->guid] = true;
168
        }
169
        // Clean up empty arrays
170 2
        return array_filter(self::$parameter_cache[$this->guid], count(...));
0 ignored issues
show
The type midcom\dba\count was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
171
    }
172
173
    /**
174
     * Set a parameter to the value specified.
175
     *
176
     * This is either a create or an update operation depending on whether there was
177
     * already a parameter of that domain/name present, or not.
178
     *
179
     * The user needs both update and parameter manipulation permission on the parent object for updates.
180
     *
181
     * @param string $value The Parameter value. If this is empty, the corresponding parameter is deleted.
182
     */
183 67
    public function set_parameter(string $domain, string $name, $value) : bool
184
    {
185 67
        if (!$this->guid) {
186
            debug_add('Cannot set parameters on a non-persistent object.', MIDCOM_LOG_WARN);
187
            return false;
188
        }
189 67
        if (empty($domain) || empty($name)) {
190
            debug_add('Parameter domain and name must be non-empty strings', MIDCOM_LOG_WARN);
191
            return false;
192
        }
193
194 67
        if (   !$this->can_do('midgard:update')
0 ignored issues
show
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

194
        if (   !$this->/** @scrutinizer ignore-call */ can_do('midgard:update')
Loading history...
195 67
            || !$this->can_do('midgard:parameters')) {
196 2
            debug_add("Failed to set parameters, midgard:update or midgard:parameters on " . static::class . " {$this->guid} not granted for the current user.",
197 2
                  MIDCOM_LOG_ERROR);
198 2
            midcom_connection::set_error(MGD_ERR_ACCESS_DENIED);
199 2
            return false;
200
        }
201
202
        // Set via MgdSchema API directly
203 65
        if (!$this->__object->set_parameter($domain, $name, (string) $value)) {
204 4
            return false;
205
        }
206
207 63
        if (isset(self::$parameter_cache[$this->guid][$domain])) {
208 10
            self::$parameter_cache[$this->guid][$domain][$name] = $value;
209
        }
210
211 63
        midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::PARAMETER);
212
213 63
        return true;
214
    }
215
216
    /**
217
     * Delete a parameter.
218
     *
219
     * Current implementation note: Deletion is not yet implemented in MgdSchema.
220
     * Therefore we set the parameters to an empty string for now, which should
221
     * have almost the same effect for most cases and thus is good enough for now.
222
     * Note, that empty string parameters are filtered in the getter methods until
223
     * this matter is resolved.
224
     *
225
     * The user needs both update and parameter manipulation permission on the parent object for updates.
226
     */
227 4
    public function delete_parameter(string $domain, string $name) : bool
228
    {
229 4
        if (!$this->guid) {
230
            debug_add('Cannot delete parameters on a non-persistent object.', MIDCOM_LOG_WARN);
231
            return false;
232
        }
233 4
        if (empty($domain) || empty($name)) {
234
            debug_add('Parameter domain and name must be non-empty strings', MIDCOM_LOG_WARN);
235
            return false;
236
        }
237
238 4
        if (   !$this->can_do('midgard:update')
239 4
            || !$this->can_do('midgard:parameters')) {
240
            debug_add("Failed to delete parameters, midgard:update or midgard:parameters on " . static::class . " {$this->guid} not granted for the current user.",
241
                  MIDCOM_LOG_ERROR);
242
            midcom_connection::set_error(MGD_ERR_ACCESS_DENIED);
243
            return false;
244
        }
245
246
        // Invalidate run-time cache
247 4
        unset(self::$parameter_cache[$this->guid][$domain]);
248
249
        // Unset via MgdSchema API directly
250 4
        $result = $this->__object->set_parameter($domain, $name, '');
251
252 4
        midcom::get()->dispatcher->dispatch(new dbaevent($this), dbaevent::PARAMETER);
253
254 4
        return $result;
255
    }
256
}
257