Passed
Push — master ( 69958c...d88402 )
by Andreas
23:02
created

detect_schema()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 5.0035

Importance

Changes 0
Metric Value
cc 5
eloc 18
nc 5
nop 2
dl 0
loc 26
ccs 18
cts 19
cp 0.9474
crap 5.0035
rs 9.3554
c 0
b 0
f 0
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
use midcom\datamanager\schemadb;
10
use midcom\datamanager\validation\phpValidator;
11
12
/**
13
 * Helper class to create a DM schema from component's config
14
 *
15
 * @package midgard.admin.asgard
16
 */
17
class midgard_admin_asgard_schemadb_config
18
{
19
    private string $component;
20
21
    private midcom_helper_configuration $config;
22
23
    private bool $is_folder;
24
25 2
    public function __construct(string $component, midcom_helper_configuration $config, bool $is_folder)
26
    {
27 2
        $this->component = $component;
28 2
        $this->config = $config;
29 2
        $this->is_folder = $is_folder;
30
    }
31
32 2
    public function create() : schemadb
33
    {
34
        // Load SchemaDb
35 2
        $schemaname = 'default';
36
37 2
        if ($path = $this->config->get('schemadb_config')) {
38 2
            $schemadb = schemadb::from_path($path);
39 2
            if ($schemadb->has('config')) {
40 2
                $schemaname = 'config';
41
            }
42
        } else {
43
            // Create dummy schema. Naughty component would not provide config schema.
44
            $schemadb = new schemadb(['default' => [
45
                'description' => 'configuration for ' . $this->component,
46
                'fields'      => []
47
            ]]);
48
        }
49 2
        $schema = $schemadb->get($schemaname);
50 2
        $schema->set('l10n_db', $this->component);
51 2
        $fields = $schema->get('fields');
52
53 2
        foreach ($this->config->_global as $key => $value) {
54
            // try to sniff what fields are missing in schema
55 2
            if (!array_key_exists($key, $fields)) {
56 2
                $fields[$key] = $this->detect_schema($key, $value);
57
            }
58
59 2
            if (   !isset($this->config->_local[$key])
60 2
                || $this->config->_local[$key] == $this->config->_global[$key]) {
61
                // No local configuration setting, note to user that this is the global value
62 2
                $fields[$key]['title'] = $schema->get_l10n()->get($fields[$key]['title']);
63 2
                $fields[$key]['title'] .= " <span class=\"global\">(" . midcom::get()->i18n->get_string('global value', 'midgard.admin.asgard') .")</span>";
64
            }
65
        }
66
67
        // Prepare defaults
68 2
        $config = array_intersect_key($this->config->get_all(), $fields);
69 2
        foreach ($config as $key => $value) {
70 2
            if (is_array($value)) {
71 2
                $fields[$key]['default'] = var_export($value, true);
72
            } else {
73 2
                if ($fields[$key]['widget'] == 'checkbox') {
74 2
                    $value = (boolean) $value;
75
                }
76 2
                $fields[$key]['default'] = $value;
77
            }
78
        }
79 2
        $schema->set('fields', $fields);
80 2
        $validation = $schema->get('validation') ?: [];
81 2
        $validation[] = [
82 2
            'callback' => $this->check_config(...),
83 2
        ];
84 2
        $schema->set('validation', $validation);
85 2
        return $schemadb;
86
    }
87
88 2
    private function detect_schema(string $key, $value) : array
89
    {
90 2
        $result = [
91 2
            'title'  => $key,
92 2
            'type'   => 'text',
93 2
            'widget' => 'text',
94 2
        ];
95
96 2
        $type = gettype($value);
97
        switch ($type) {
98 2
            case "boolean":
99 2
                $result['type'] = 'boolean';
100 2
                $result['widget'] = 'checkbox';
101 2
                break;
102 2
            case "array":
103 2
                $result['widget'] = 'textarea';
104
                // Complex Array fields should be readonly for topics as we cannot store and read them properly with parameters
105 2
                $result['readonly'] = $this->is_folder;
106 2
                break;
107 2
            case 'string':
108 2
                if (str_contains($value, "\n")) {
109
                    $result['widget'] = 'textarea';
110
                }
111
        }
112
113 2
        return $result;
114
    }
115
116
    /**
117
     * Ensure the configuration is valid (form validation callback)
118
     */
119
    public function check_config(array $values)
120
    {
121
        $current = $this->config->get_all();
122
        $result = [];
123
        foreach ($values as $key => $newval) {
124
            if ($newval === '' || !isset($current[$key])) {
125
                continue;
126
            }
127
            $val = $current[$key];
128
129
            if (is_array($val)) {
130
                $code = "<?php\n\$data = array({$newval}\n);\n?>";
131
                if ($error = phpValidator::lint($code)) {
132
                    $result[$key] = $error;
133
                }
134
            }
135
        }
136
        return $result ?: true;
137
    }
138
}