Passed
Push — master ( 0cded3...9172b1 )
by Andreas
97:58
created

schemabuilder::build_autocomplete_config()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 21
c 1
b 0
f 0
nc 12
nop 3
dl 0
loc 28
ccs 20
cts 20
cp 1
crap 5
rs 9.2728
1
<?php
2
/**
3
 * @package midgard.admin.asgard
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\datamanager;
10
11
use midcom_core_dbaobject;
12
use midcom_helper_reflector;
13
use midgard_reflection_property;
14
use midgard_object_class;
15
use midcom;
16
17
/**
18
 * Helper class to create a DM schema from an object via reflection
19
 *
20
 * @package midgard.admin.asgard
21
 */
22
class schemabuilder
23
{
24
    /**
25
     * The object we're working with
26
     *
27
     * @var midcom_core_dbaobject
28
     */
29
    protected $object;
30
31
    /**
32
     * The schema in use
33
     *
34
     * @var array
35
     */
36
    protected $schema;
37
38
    /**
39
     * Midgard reflection property instance for the current object's class.
40
     *
41
     * @var midgard_reflection_property
42
     */
43
    protected $reflector;
44
45 31
    public function __construct(midcom_core_dbaobject $object)
46
    {
47 31
        $this->object = $object;
48 31
        $this->reflector = new midgard_reflection_property(midcom_helper_reflector::resolve_baseclass($this->object));
49 31
    }
50
51
    /**
52
     * Generates, loads and prepares the schema database.
53
     *
54
     * The operations are done on all available schemas within the DB.
55
     */
56 9
    public function create($include_fields) : schemadb
57
    {
58 9
        $type = get_class($this->object);
59 9
        $type_fields = $this->object->get_properties();
60
61 9
        $this->schema = [
62
            'description' => 'object schema',
63
            'fields'      => []
64
        ];
65
66 9
        if ($component = midcom::get()->dbclassloader->get_component_for_class($type)) {
67 9
            $this->schema['l10n_db'] = $component;
68
        }
69
70 9
        if (!empty($include_fields)) {
71
            // Skip the fields that aren't requested, if inclusion list has been defined
72 2
            $type_fields = array_intersect($type_fields, (array) $include_fields);
73
        }
74 9
        $type_fields = array_filter($type_fields, [$this, '_filter_schema_fields']);
75
76 9
        $this->process_type($type, $type_fields);
77
78 9
        return new schemadb(['default' => $this->schema]);
79
    }
80
81 9
    protected function process_type(string $type, array $type_fields)
82
    {
83
        // Iterate through object properties
84 9
        foreach ($type_fields as $key) {
85
            // Linked fields should use chooser
86 8
            if ($this->reflector->is_link($key)) {
87 8
                $this->add_linked_field($key);
88
                // Skip rest of processing
89 8
                continue;
90
            }
91
92 7
            $field_type = $this->reflector->get_midgard_type($key);
93
            switch ($field_type) {
94 7
                case MGD_TYPE_GUID:
95 7
                case MGD_TYPE_STRING:
96 7
                    $this->add_string_field($key, $type);
97 7
                    break;
98 7
                case MGD_TYPE_LONGTEXT:
99 7
                    $this->add_longtext_field($key);
100 7
                    break;
101 7
                case MGD_TYPE_INT:
102 5
                case MGD_TYPE_UINT:
103 2
                    $this->add_int_field($key);
104 2
                    break;
105 5
                case MGD_TYPE_FLOAT:
106
                    $this->schema['fields'][$key] = [
107
                        'title'       => $key,
108
                        'storage'     => $key,
109
                        'type'        => 'number',
110
                        'widget'      => 'text',
111
                    ];
112
                    break;
113 5
                case MGD_TYPE_BOOLEAN:
114 5
                    $this->schema['fields'][$key] = [
115 5
                        'title'       => $key,
116 5
                        'storage'     => $key,
117 5
                        'type'        => 'boolean',
118 5
                        'widget'      => 'checkbox',
119
                    ];
120 5
                    break;
121
                case MGD_TYPE_TIMESTAMP:
122
                    $this->schema['fields'][$key] = [
123
                        'title'       => $key,
124
                        'storage'     => $key,
125
                        'type' => 'date',
126
                        'widget' => 'jsdate',
127
                    ];
128
                    break;
129
            }
130
        }
131 9
    }
132
133 8
    private function _filter_schema_fields(string $key) : bool
134
    {
135 8
        return !in_array($key, ['id', 'guid', 'metadata']);
136
    }
137
138 7
    protected function add_string_field(string $key, string $type)
139
    {
140 7
        $this->schema['fields'][$key] = [
141 7
            'title'       => $key,
142 7
            'storage'     => $key,
143 7
            'type'        => 'text',
144 7
            'widget'      => 'text',
145
        ];
146 7
    }
147
148 2
    protected function add_int_field(string $key)
149
    {
150 2
        if (in_array($key, ['start', 'end', 'added', 'date'])) {
151
            // We can safely assume that INT fields called start and end store unixtimes
152
            $this->schema['fields'][$key] = [
153
                'title'       => $key,
154
                'storage'     => $key,
155
                'type' => 'date',
156
                'type_config' => [
157
                    'storage_type' => 'UNIXTIME'
158
                ],
159
                'widget' => 'jsdate',
160
            ];
161
        } else {
162 2
            $this->schema['fields'][$key] = [
163 2
                'title'       => $key,
164 2
                'storage'     => $key,
165 2
                'type'        => 'number',
166 2
                'widget'      => 'text',
167
            ];
168
        }
169 2
    }
170
171 7
    protected function add_longtext_field(string $key)
172
    {
173
        // Figure out nice size for the editing field
174 7
        $output_mode = '';
175 7
        $widget = 'textarea';
176 7
        $dm_type = 'text';
177
178 7
        switch ($key) {
179 7
            case 'content':
180 7
            case 'description':
181 7
                $height = 30;
182 7
                $output_mode = 'html';
183 7
                break;
184
185 7
            case 'value':
186 7
            case 'code':
187
                // These are typical "large" fields
188 5
                $height = 30;
189 5
                $dm_type = 'php';
190 5
                $output_mode = 'code';
191 5
                break;
192
193
            default:
194 7
                $height = 6;
195 7
                break;
196
        }
197
198 7
        $this->schema['fields'][$key] = [
199 7
            'title'       => $key,
200 7
            'storage'     => $key,
201 7
            'type'        => $dm_type,
202
            'type_config' => [
203 7
                'output_mode' => $output_mode,
204
            ],
205 7
            'widget'      => $widget,
206
            'widget_config' => [
207 7
                'height' => $height,
208 7
                'width' => '100%',
209
            ],
210
        ];
211 7
    }
212
213 8
    protected function add_linked_field(string $key)
214
    {
215 8
        $linked_type = $this->reflector->get_link_name($key);
216 8
        $field_type = $this->reflector->get_midgard_type($key);
217 8
        $type_label = midcom_helper_reflector::get($linked_type)->get_class_label();
218
219 8
        if (str_starts_with($type_label, $key)) {
220
            // Handle abbreviations like "lang" for "language"
221
            $field_label = $type_label;
222 8
        } elseif ($key == $type_label) {
223
            $field_label = $key;
224
        } else {
225 8
            $l10n = midcom_helper_reflector::get($this->object)->get_component_l10n();
226 8
            $field_label = $l10n->get($key);
227
        }
228
229
        // Get the chooser widgets
230
        switch ($field_type) {
231 8
            case MGD_TYPE_UINT:
232
            case MGD_TYPE_STRING:
233
            case MGD_TYPE_GUID:
234 8
                $class = midcom::get()->dbclassloader->get_midcom_class_name_for_mgdschema_object($linked_type);
235 8
                if (!$class) {
236
                    break;
237
                }
238 8
                $this->schema['fields'][$key] = [
239 8
                    'title'       => $field_label,
240 8
                    'storage'     => $key,
241 8
                    'type'        => 'select',
242
                    'type_config' => [
243
                        'require_corresponding_option' => false,
244
                        'options' => [],
245
                        'allow_other' => true,
246
                        'allow_multiple' => false,
247
                    ],
248 8
                    'widget' => 'autocomplete',
249 8
                    'widget_config' => $this->build_autocomplete_config($key, $class, $linked_type),
0 ignored issues
show
Bug introduced by
It seems like $linked_type can also be of type null; however, parameter $linked_type of midcom\datamanager\schem...d_autocomplete_config() does only seem to accept string, 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

249
                    'widget_config' => $this->build_autocomplete_config($key, $class, /** @scrutinizer ignore-type */ $linked_type),
Loading history...
250 8
                    'required' => (midgard_object_class::get_property_parent($this->object->__mgdschema_class_name__) == $key)
251
                ];
252 8
                break;
253
        }
254 8
    }
255
256 8
    private function build_autocomplete_config(string $key, string $class, string $linked_type) : array
257
    {
258 8
        $reflector = midcom_helper_reflector::get($linked_type);
259 8
        $component = midcom::get()->dbclassloader->get_component_for_class($linked_type);
260 8
        $searchfields = $reflector->get_search_properties();
261 8
        $label_property = $reflector->get_label_property();
262 8
        $has_parent = !empty(midgard_object_class::get_property_parent($linked_type)) || !empty(midgard_object_class::get_property_up($linked_type));
263 8
        $result_headers = [];
264
265 8
        foreach ($searchfields as $field) {
266 8
            if ($field !== $label_property) {
267 8
                $result_headers[] = [
268 8
                    'name' => $field,
269 8
                    'title' => ucfirst($field),
270
                ];
271
            }
272
        }
273 8
        $searchfields[] = 'guid';
274
275
        return [
276 8
            'class' => $class,
277 8
            'component' => $component,
278 8
            'titlefield' => method_exists($class, 'get_label') ? null : $label_property,
279 8
            'id_field' => $this->reflector->get_link_target($key),
280 8
            'searchfields' => $searchfields,
281 8
            'result_headers' => $result_headers,
282
            'orders' => [],
283 8
            'categorize_by_parent_label' => $has_parent
284
        ];
285
    }
286
}
287