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
Bug
introduced
by
![]() |
|||||
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
|
|||||
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
![]() |
|||||
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
![]() |
|||||
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
![]() |
|||||
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 |