Passed
Pull Request — master (#700)
by Edoardo
03:11
created

PropertiesComponent::hiddenRelationsList()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2018 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
14
namespace App\Controller\Component;
15
16
use App\Utility\CacheTools;
17
use Cake\Cache\Cache;
18
use Cake\Controller\Component;
19
use Cake\Core\Configure;
20
use Cake\Utility\Hash;
21
22
/**
23
 * Component to handle properties view in modules.
24
 */
25
class PropertiesComponent extends Component
26
{
27
    /**
28
     * Default properties groups
29
     *
30
     * @var array
31
     */
32
    protected $defaultGroups = [
33
        'view' => [
34
            // always open on the top
35
            'core' => [
36
                'title',
37
                'description',
38
            ],
39
            // publishing related
40
            'publish' => [
41
                'uname',
42
                'status',
43
                'publish_start',
44
                'publish_end',
45
            ],
46
            // power users
47
            'advanced' => [
48
                'extra',
49
            ],
50
            // remaining attributes
51
            // items listed here only used for ordering, not listed if present in other groups
52
            'other' => [
53
                'body',
54
                'lang',
55
                // remaining attributes
56
            ],
57
        ],
58
        // index properties list
59
        // don't include: 'id', 'status', and 'modified' => always listed
60
        'index' => [
61
            'title',
62
        ],
63
64
        'filter' => [
65
            'status',
66
        ],
67
        'bulk' => [
68
            'status',
69
        ],
70
    ];
71
72
    /**
73
     * Properties to exclude from groups view
74
     *
75
     * @var array
76
     */
77
    protected $excluded = [
78
        'categories',
79
        'date_ranges',
80
        'tags',
81
        'lang',
82
    ];
83
84
    /**
85
     * Init properties
86
     *
87
     * @return void
88
     */
89
    public function startup(): void
90
    {
91
        $cacheKey = CacheTools::cacheKey('properties');
92
        $properties = Cache::read($cacheKey, 'default');
93
        if (!empty($properties)) {
94
            $this->setConfig('Properties', $properties);
95
96
            return;
97
        }
98
99
        Configure::load('properties');
100
        $properties = (array)Configure::read('Properties');
101
        $defaultProperties = (array)Configure::read('DefaultProperties');
102
        $keys = array_unique(
103
            array_merge(
104
                array_keys($properties),
105
                array_keys($defaultProperties)
106
            )
107
        );
108
        sort($keys);
109
        $config = [];
110
        foreach ($keys as $key) {
111
            $config[$key] = array_merge(
112
                (array)Hash::get($defaultProperties, $key),
113
                (array)Hash::get($properties, $key)
114
            );
115
        }
116
        $this->setConfig('Properties', $config);
117
        Cache::write($cacheKey, $config);
118
    }
119
120
    /**
121
     * Setup object attributes into groups from configuration for the view.
122
     * An array with a key for each group will be created.
123
     *
124
     * Displayed view groups are
125
     *      + 'core' always open on the top
126
     *      + 'publish' publishing related
127
     *      + 'advanced' for power users (JSON mainly)
128
     *      + 'other' remaining attributes
129
     *
130
     * Customization available via `Properties.{type}.view` configuration where properties
131
     * names can be grouped in `core`, `publish`, `advanced` and `other` as well
132
     *
133
     * Properties not present in $object will not be set in any group unless they're listed
134
     * under `_keep` in the above configuration.
135
     *
136
     * Properties in `Properties.{type}.view._hide` will be removed from groups.
137
     *
138
     * Properties in internal `$excluded` array will be removed from groups.
139
     *
140
     * @param array  $object Object data to view
141
     * @param string $type   Object type
142
     *
143
     * @return array
144
     */
145
    public function viewGroups(array $object, string $type): array
146
    {
147
        $properties = $used = [];
148
        $keep = (array)$this->getConfig(sprintf('Properties.%s.view._keep', $type), []);
149
        $hide = (array)$this->getConfig(sprintf('Properties.%s.view._hide', $type), []);
150
        $attributes = array_merge(array_fill_keys($keep, ''), (array)Hash::get($object, 'attributes'));
151
        $attributes = array_diff_key($attributes, array_flip($this->excluded));
152
        $attributes = array_diff_key($attributes, array_flip($hide));
153
        $defaults = array_merge($this->getConfig(sprintf('Properties.%s.view', $type), []), $this->defaultGroups['view']);
0 ignored issues
show
Bug introduced by
It seems like $this->getConfig(sprintf...view', $type), array()) can also be of type null; however, parameter $arrays of array_merge() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

153
        $defaults = array_merge(/** @scrutinizer ignore-type */ $this->getConfig(sprintf('Properties.%s.view', $type), []), $this->defaultGroups['view']);
Loading history...
154
        unset($defaults['_keep']);
155
156
        foreach ($defaults as $group => $items) {
157
            $key = sprintf('Properties.%s.view.%s', $type, $group);
158
            $list = $this->getConfig($key, $items);
159
            $p = [];
160
            foreach ($list as $item) {
161
                if (array_key_exists($item, $attributes)) {
162
                    $p[$item] = $attributes[$item];
163
                }
164
            }
165
            $properties[$group] = $p;
166
            if ($group !== 'other') {
167
                $used = array_merge($used, $list);
168
            }
169
        }
170
        // add remaining properties to 'other' group
171
        $properties['other'] = array_diff_key($properties['other'], array_flip($used));
172
        $properties['other'] += array_diff_key($attributes, array_flip($used));
173
174
        return $properties;
175
    }
176
177
    /**
178
     * List properties to display in `index` view
179
     *
180
     * @param string $type Object type name
181
     *
182
     * @return array
183
     */
184
    public function indexList(string $type): array
185
    {
186
        $list = $this->getConfig(sprintf('Properties.%s.index', $type), $this->defaultGroups['index']);
187
188
        return array_diff($list, ['id', 'status', 'modified']);
0 ignored issues
show
Bug introduced by
It seems like $list can also be of type null; however, parameter $array of array_diff() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

188
        return array_diff(/** @scrutinizer ignore-type */ $list, ['id', 'status', 'modified']);
Loading history...
189
    }
190
191
    /**
192
     * List of filter to display in `filter` view
193
     *
194
     * @param string $type Object type name
195
     *
196
     * @return array
197
     */
198
    public function filterList(string $type): array
199
    {
200
        return $this->getConfig(sprintf('Properties.%s.filter', $type), $this->defaultGroups['filter']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getConfig(...efaultGroups['filter']) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
201
    }
202
203
    /**
204
     * List of all filters, grouped by type, for passed `$types` list
205
     *
206
     * @param string[] $types List of types to get filters of
207
     *
208
     * @return array
209
     */
210
    public function filtersByType(array $types): array
211
    {
212
        if (empty($types)) {
213
            return [];
214
        }
215
216
        return array_filter(
217
            array_reduce(
218
                $types,
219
                function (array $accumulator, string $type) {
220
                    $accumulator[$type] = $this->filterList($type);
221
222
                    return $accumulator;
223
                },
224
                []
225
            )
226
        );
227
    }
228
229
    /**
230
     * List of bulk actions to display in `index` view
231
     *
232
     * @param string $type Object type name
233
     *
234
     * @return array
235
     */
236
    public function bulkList(string $type): array
237
    {
238
        return $this->getConfig(sprintf('Properties.%s.bulk', $type), $this->defaultGroups['bulk']);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getConfig(...>defaultGroups['bulk']) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
239
    }
240
241
    /**
242
     * List of ordered relations to display.
243
     * Relations not included will be displayed after these.
244
     *
245
     * @param string $type Object type name
246
     *
247
     * @return array
248
     */
249
    public function relationsList(string $type): array
250
    {
251
        return $this->getConfig(sprintf('Properties.%s.relations', $type), []);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getConfig(...ions', $type), array()) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
252
    }
253
254
    /**
255
     * List of hidden relations.
256
     *
257
     * @param string $type Object type name
258
     *
259
     * @return array
260
     */
261
    public function hiddenRelationsList(string $type): array
262
    {
263
        return $this->getConfig(sprintf('Properties.%s.relations._hide', $type), []);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getConfig(...hide', $type), array()) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
264
    }
265
266
    /**
267
     * List of readonly relations.
268
     *
269
     * @param string $type Object type name
270
     *
271
     * @return array
272
     */
273
    public function readonlyRelationsList(string $type): array
274
    {
275
        return $this->getConfig(sprintf('Properties.%s.relations._readonly', $type), []);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getConfig(...only', $type), array()) could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
276
    }
277
}
278