Passed
Push — master ( 74ea42...c9a2e0 )
by Andreas
25:51
created

schemabuilder::add_int_field()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2.2894

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 14
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 19
ccs 7
cts 12
cp 0.5833
crap 2.2894
rs 9.7998
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 35
    public function __construct(midcom_core_dbaobject $object)
46
    {
47 35
        $this->object = $object;
48 35
        $this->reflector = new midgard_reflection_property(midcom_helper_reflector::resolve_baseclass($this->object));
49 35
    }
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 13
    public function create($include_fields) : schemadb
57
    {
58 13
        $type = get_class($this->object);
59 13
        $type_fields = $this->object->get_properties();
60
61 13
        $this->schema = [
62
            'description' => 'object schema',
63
            'fields'      => []
64
        ];
65
66 13
        if ($component = midcom::get()->dbclassloader->get_component_for_class($type)) {
67 13
            $this->schema['l10n_db'] = $component;
68
        }
69
70 13
        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 13
        $type_fields = array_filter($type_fields, [$this, '_filter_schema_fields']);
75
76 13
        $this->process_type($type, $type_fields);
77
78 13
        return new schemadb(['default' => $this->schema]);
79
    }
80
81 13
    protected function process_type(string $type, array $type_fields)
82
    {
83
        // Iterate through object properties
84 13
        foreach ($type_fields as $key) {
85
            // Linked fields should use chooser
86 12
            if ($this->reflector->is_link($key)) {
87 8
                $this->add_linked_field($key);
88
                // Skip rest of processing
89 8
                continue;
90
            }
91
92 11
            $field_type = $this->reflector->get_midgard_type($key);
93
            switch ($field_type) {
94 11
                case MGD_TYPE_GUID:
95 11
                case MGD_TYPE_STRING:
96 11
                    $this->add_string_field($key, $type);
97 11
                    break;
98 11
                case MGD_TYPE_LONGTEXT:
99 11
                    $this->add_longtext_field($key);
100 11
                    break;
101 11
                case MGD_TYPE_INT:
102 9
                case MGD_TYPE_UINT:
103 6
                    $this->add_int_field($key);
104 6
                    break;
105 9
                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 9
                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 4
                case MGD_TYPE_TIMESTAMP:
122 4
                    $this->schema['fields'][$key] = [
123 4
                        'title'       => $key,
124 4
                        'storage'     => $key,
125 4
                        'type' => 'date',
126 4
                        'widget' => 'jsdate',
127
                    ];
128 4
                    break;
129
            }
130
        }
131 13
    }
132
133 12
    private function _filter_schema_fields(string $key) : bool
134
    {
135 12
        return !in_array($key, ['id', 'guid', 'metadata']);
136
    }
137
138 11
    protected function add_string_field(string $key, string $type)
139
    {
140 11
        $this->schema['fields'][$key] = [
141 11
            'title'       => $key,
142 11
            'storage'     => $key,
143 11
            'type'        => 'text',
144 11
            'widget'      => 'text',
145
        ];
146 11
    }
147
148 6
    protected function add_int_field(string $key)
149
    {
150 6
        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 6
            $this->schema['fields'][$key] = [
163 6
                'title'       => $key,
164 6
                'storage'     => $key,
165 6
                'type'        => 'number',
166 6
                'widget'      => 'text',
167
            ];
168
        }
169 6
    }
170
171 11
    protected function add_longtext_field(string $key)
172
    {
173
        // Figure out nice size for the editing field
174 11
        $output_mode = '';
175 11
        $widget = 'textarea';
176 11
        $dm_type = 'text';
177
178 11
        switch ($key) {
179 11
            case 'content':
180 11
            case 'description':
181 7
                $height = 30;
182 7
                $output_mode = 'html';
183 7
                break;
184
185 11
            case 'value':
186 11
            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 11
                $height = 6;
195 11
                break;
196
        }
197
198 11
        $this->schema['fields'][$key] = [
199 11
            'title'       => $key,
200 11
            'storage'     => $key,
201 11
            'type'        => $dm_type,
202
            'type_config' => [
203 11
                'output_mode' => $output_mode,
204
            ],
205 11
            'widget'      => $widget,
206
            'widget_config' => [
207 11
                'height' => $height,
208 11
                'width' => '100%',
209
            ],
210
        ];
211 11
    }
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
        $searchfields = $reflector->get_search_properties();
260 8
        $label_property = $reflector->get_label_property();
261 8
        $has_parent = !empty(midgard_object_class::get_property_parent($linked_type)) || !empty(midgard_object_class::get_property_up($linked_type));
262 8
        $result_headers = [];
263
264 8
        foreach ($searchfields as $field) {
265 8
            if ($field !== $label_property) {
266 8
                $result_headers[] = ['name' => $field];
267
            }
268
        }
269 8
        $searchfields[] = 'guid';
270
271
        return [
272 8
            'class' => $class,
273 8
            'titlefield' => method_exists($class, 'get_label') ? null : $label_property,
274 8
            'id_field' => $this->reflector->get_link_target($key),
275 8
            'searchfields' => $searchfields,
276 8
            'result_headers' => $result_headers,
277
            'orders' => [],
278 8
            'categorize_by_parent_label' => $has_parent
279
        ];
280
    }
281
}
282