Issues (809)

src/midcom/datamanager/schemabuilder.php (5 issues)

Severity
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_object_class;
14
use midcom;
15
16
/**
17
 * Helper class to create a DM schema from an object via reflection
18
 *
19
 * @package midgard.admin.asgard
20
 */
21
class schemabuilder
22
{
23
    /**
24
     * The object we're working with
25
     */
26
    protected midcom_core_dbaobject $object;
27
28
    /**
29
     * The schema in use
30
     */
31
    protected array $schema;
32
33
    /**
34
     * Reflector instance for the current object's class.
35
     */
36
    protected midcom_helper_reflector $reflector;
37
38 35
    public function __construct(midcom_core_dbaobject $object)
39
    {
40 35
        $this->object = $object;
41 35
        $this->reflector = new midcom_helper_reflector($object);
0 ignored issues
show
$object of type midcom_core_dbaobject is incompatible with the type midgard\portable\api\mgdobject|string expected by parameter $src of midcom_helper_reflector::__construct(). ( Ignorable by Annotation )

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

41
        $this->reflector = new midcom_helper_reflector(/** @scrutinizer ignore-type */ $object);
Loading history...
42
    }
43
44
    /**
45
     * Generates, loads and prepares the schema database.
46
     *
47
     * The operations are done on all available schemas within the DB.
48
     */
49 13
    public function create(?array $include_fields = null) : schemadb
50
    {
51 13
        $type = $this->object::class;
52 13
        $type_fields = $this->object->get_properties();
53
54 13
        $this->schema = [
55 13
            'description' => 'object schema',
56 13
            'fields'      => []
57 13
        ];
58
59 13
        if ($component = midcom::get()->dbclassloader->get_component_for_class($type)) {
60 13
            $this->schema['l10n_db'] = $component;
61
        }
62
63 13
        if ($include_fields) {
64
            // Skip the fields that aren't requested, if inclusion list has been defined
65 2
            $type_fields = array_intersect($type_fields, $include_fields);
66
        }
67 13
        $type_fields = array_filter($type_fields, $this->_filter_schema_fields(...));
68
69 13
        $this->process_type($type, $type_fields);
70
71 13
        return new schemadb(['default' => $this->schema]);
72
    }
73
74 13
    protected function process_type(string $type, array $type_fields)
75
    {
76
        // Iterate through object properties
77 13
        foreach ($type_fields as $key) {
78
            // Linked fields should use chooser
79 13
            if ($this->reflector->is_link($key)) {
80 9
                $this->add_linked_field($key);
81
                // Skip rest of processing
82 9
                continue;
83
            }
84
85 11
            $field_type = $this->reflector->get_midgard_type($key);
86
            switch ($field_type) {
87 11
                case MGD_TYPE_GUID:
88 11
                case MGD_TYPE_STRING:
89 11
                    $this->add_string_field($key, $type);
90 11
                    break;
91 11
                case MGD_TYPE_LONGTEXT:
92 11
                    $this->add_longtext_field($key);
93 11
                    break;
94 11
                case MGD_TYPE_INT:
95 9
                case MGD_TYPE_UINT:
96 6
                    $this->add_int_field($key);
97 6
                    break;
98 9
                case MGD_TYPE_FLOAT:
99
                    $this->schema['fields'][$key] = [
100
                        'title'       => $key,
101
                        'storage'     => $key,
102
                        'type'        => 'number',
103
                        'widget'      => 'text',
104
                    ];
105
                    break;
106 9
                case MGD_TYPE_BOOLEAN:
107 5
                    $this->schema['fields'][$key] = [
108 5
                        'title'       => $key,
109 5
                        'storage'     => $key,
110 5
                        'type'        => 'boolean',
111 5
                        'widget'      => 'checkbox',
112 5
                    ];
113 5
                    break;
114 4
                case MGD_TYPE_TIMESTAMP:
115 4
                    $this->schema['fields'][$key] = [
116 4
                        'title'       => $key,
117 4
                        'storage'     => $key,
118 4
                        'type' => 'date',
119 4
                        'widget' => 'jsdate',
120 4
                    ];
121 4
                    break;
122
            }
123
        }
124
    }
125
126 13
    private function _filter_schema_fields(string $key) : bool
0 ignored issues
show
The method _filter_schema_fields() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
127
    {
128 13
        return !in_array($key, ['id', 'guid', 'metadata']);
129
    }
130
131 11
    protected function add_string_field(string $key, string $type)
132
    {
133 11
        $this->schema['fields'][$key] = [
134 11
            'title'       => $key,
135 11
            'storage'     => $key,
136 11
            'type'        => 'text',
137 11
            'widget'      => 'text',
138 11
        ];
139
    }
140
141 6
    protected function add_int_field(string $key)
142
    {
143 6
        if (in_array($key, ['start', 'end', 'added', 'date'])) {
144
            // We can safely assume that INT fields called start and end store unixtimes
145
            $this->schema['fields'][$key] = [
146
                'title'       => $key,
147
                'storage'     => $key,
148
                'type' => 'date',
149
                'type_config' => [
150
                    'storage_type' => 'UNIXTIME'
151
                ],
152
                'widget' => 'jsdate',
153
            ];
154
        } else {
155 6
            $this->schema['fields'][$key] = [
156 6
                'title'       => $key,
157 6
                'storage'     => $key,
158 6
                'type'        => 'number',
159 6
                'widget'      => 'text',
160 6
            ];
161
        }
162
    }
163
164 11
    protected function add_longtext_field(string $key)
165
    {
166
        // Figure out nice size for the editing field
167 11
        $output_mode = '';
168 11
        $widget = 'textarea';
169 11
        $dm_type = 'text';
170
171
        switch ($key) {
172 11
            case 'content':
173 11
            case 'description':
174 7
                $height = 12;
175 7
                $output_mode = 'html';
176 7
                break;
177
178 11
            case 'value':
179 11
            case 'code':
180
                // These are typical "large" fields
181 5
                $height = 12;
182 5
                $dm_type = 'php';
183 5
                $output_mode = 'code';
184 5
                break;
185
186
            default:
187 11
                $height = 6;
188 11
                break;
189
        }
190
191 11
        $this->schema['fields'][$key] = [
192 11
            'title'       => $key,
193 11
            'storage'     => $key,
194 11
            'type'        => $dm_type,
195 11
            'type_config' => [
196 11
                'output_mode' => $output_mode,
197 11
            ],
198 11
            'widget'      => $widget,
199 11
            'widget_config' => [
200 11
                'height' => $height,
201 11
                'width' => '100%',
202 11
            ],
203 11
        ];
204
    }
205
206 9
    protected function add_linked_field(string $key)
207
    {
208 9
        $linked_type = $this->reflector->get_link_name($key);
209 9
        $field_type = $this->reflector->get_midgard_type($key);
210 9
        $type_label = midcom_helper_reflector::get($linked_type)->get_class_label();
0 ignored issues
show
It seems like $linked_type can also be of type null; however, parameter $src of midcom_helper_reflector::get() does only seem to accept object|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

210
        $type_label = midcom_helper_reflector::get(/** @scrutinizer ignore-type */ $linked_type)->get_class_label();
Loading history...
211
212 9
        if (str_starts_with($type_label, $key)) {
213
            // Handle abbreviations like "lang" for "language"
214
            $field_label = $type_label;
215 9
        } elseif ($key == $type_label) {
216
            $field_label = $key;
217
        } else {
218 9
            $l10n = $this->reflector->get_component_l10n();
219 9
            $field_label = $l10n->get($key);
220
        }
221
222
        // Get the chooser widgets
223
        switch ($field_type) {
224 9
            case MGD_TYPE_UINT:
225
            case MGD_TYPE_STRING:
226
            case MGD_TYPE_GUID:
227 9
                if ($class = midcom::get()->dbclassloader->get_midcom_class_name_for_mgdschema_object($linked_type)) {
0 ignored issues
show
It seems like $linked_type can also be of type null; however, parameter $classname of midcom_services_dbclassl..._for_mgdschema_object() does only seem to accept object|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

227
                if ($class = midcom::get()->dbclassloader->get_midcom_class_name_for_mgdschema_object(/** @scrutinizer ignore-type */ $linked_type)) {
Loading history...
228 9
                    $this->schema['fields'][$key] = [
229 9
                        'title'       => $field_label,
230 9
                        'storage'     => $key,
231 9
                        'type'        => 'select',
232 9
                        'type_config' => [
233 9
                            'require_corresponding_option' => false,
234 9
                            'options' => [],
235 9
                            'allow_other' => true,
236 9
                            'allow_multiple' => false,
237 9
                        ],
238 9
                        'widget' => 'autocomplete',
239 9
                        'widget_config' => $this->build_autocomplete_config($key, $class, $linked_type),
0 ignored issues
show
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

239
                        'widget_config' => $this->build_autocomplete_config($key, $class, /** @scrutinizer ignore-type */ $linked_type),
Loading history...
240 9
                        'required' => (midgard_object_class::get_property_parent($this->object->__mgdschema_class_name__) == $key)
241 9
                    ];
242
                }
243 9
                break;
244
        }
245
    }
246
247 9
    private function build_autocomplete_config(string $key, string $class, string $linked_type) : array
248
    {
249 9
        $reflector = midcom_helper_reflector::get($linked_type);
250 9
        $searchfields = $reflector->get_search_properties();
251 9
        $label_property = $reflector->get_label_property();
252 9
        $has_parent = !empty(midgard_object_class::get_property_parent($linked_type)) || !empty(midgard_object_class::get_property_up($linked_type));
253 9
        $result_headers = [];
254
255 9
        foreach ($searchfields as $field) {
256 9
            if ($field !== $label_property) {
257 9
                $result_headers[] = ['name' => $field];
258
            }
259
        }
260 9
        $searchfields[] = 'guid';
261
262 9
        return [
263 9
            'class' => $class,
264 9
            'titlefield' => method_exists($class, 'get_label') ? null : $label_property,
265 9
            'id_field' => $this->reflector->get_link_target($key),
266 9
            'searchfields' => $searchfields,
267 9
            'result_headers' => $result_headers,
268 9
            'orders' => [],
269 9
            'categorize_by_parent_label' => $has_parent
270 9
        ];
271
    }
272
}
273