1<?php
2
3namespace dokuwiki\plugin\struct\meta;
4
5use dokuwiki\Extension\Plugin;
6use dokuwiki\Form\Form;
7use dokuwiki\plugin\struct\types\Text;
8
9/**
10 * Class SchemaEditor
11 *
12 * Provides the editing interface for a given Schema as used in the admin backend. The actual modifying of the
13 * schema happens in the SchemaBuilder class.
14 *
15 * @package dokuwiki\plugin\struct\meta
16 */
17class SchemaEditor
18{
19    /** @var Schema the schema that is edited */
20    protected $schema;
21
22    /** @var Plugin */
23    protected $hlp;
24
25    /**
26     * SchemaEditor constructor.
27     * @param Schema $schema
28     */
29    public function __construct(Schema $schema)
30    {
31        $this->schema = $schema;
32        $this->hlp = plugin_load('helper', 'struct_config');
33    }
34
35    /**
36     * Returns the Admin Form to edit the schema
37     *
38     * This data is processed by the SchemaBuilder class
39     *
40     * @return string the HTML for the editor form
41     * @see SchemaBuilder
42     */
43    public function getEditor()
44    {
45        $form = new Form(['method' => 'POST', 'id' => 'plugin__struct_editor']);
46        $form->setHiddenField('do', 'admin');
47        $form->setHiddenField('page', 'struct_schemas');
48        $form->setHiddenField('table', $this->schema->getTable());
49        $form->setHiddenField('schema[id]', $this->schema->getId());
50
51        $form->addHTML('<table class="inline">');
52        $form->addHTML("<tr>
53            <th>{$this->hlp->getLang('editor_sort')}</th>
54            <th>{$this->hlp->getLang('editor_label')}</th>
55            <th>{$this->hlp->getLang('editor_multi')}</th>
56            <th>{$this->hlp->getLang('editor_conf')}</th>
57            <th>{$this->hlp->getLang('editor_type')}</th>
58            <th>{$this->hlp->getLang('editor_enabled')}</th>
59        </tr>");
60
61
62        foreach ($this->schema->getColumns() as $col) {
63            $form->addHTML($this->adminColumn($col->getColref(), $col));
64        }
65
66        // FIXME new one needs to be added dynamically, this is just for testing
67        $form->addHTML($this->adminColumn('new1', new Column($this->schema->getMaxsort() + 10, new Text()), 'new'));
68
69        $form->addHTML('</table>');
70
71        $form->addFieldsetOpen();
72
73        $config = json_encode($this->schema->getConfig(), JSON_PRETTY_PRINT);
74        $form->addHTML(
75            '<textarea name="schema[config]" id="schemaConfig" cols="45" rows="10" class="config">' .
76            hsc($config) .
77            '</textarea>'
78        );
79        $form->addFieldsetClose();
80
81
82        $form->addButton('save', 'Save')->attr('type', 'submit');
83        return $form->toHTML() . $this->initJSONEditor();
84    }
85
86    /**
87     * Gives the code to attach the JSON editor to the config field
88     *
89     * We do not use the "normal" way, because this is rarely used code and there's no need to always load it.
90     * @return string
91     */
92    protected function initJSONEditor()
93    {
94        $html = '';
95        $html .= '<link href="' . DOKU_BASE .
96            'lib/plugins/struct/jsoneditor/jsoneditor.min.css" rel="stylesheet" type="text/css">';
97        $html .= '<link href="' . DOKU_BASE .
98            'lib/plugins/struct/jsoneditor/setup.css" rel="stylesheet" type="text/css">';
99        $html .= '<script src="' . DOKU_BASE .
100            'lib/plugins/struct/jsoneditor/jsoneditor-minimalist.min.js" defer="defer"></script>';
101        $html .= '<script src="' . DOKU_BASE .
102            'lib/plugins/struct/jsoneditor/setup.js" defer="defer"></script>';
103        return $html;
104    }
105
106    /**
107     * Returns the HTML to edit a single column definition of the schema
108     *
109     * @param string $column_id
110     * @param Column $col
111     * @param string $key The key to use in the form
112     * @return string
113     * @todo this should probably be reused for adding new columns via AJAX later?
114     */
115    protected function adminColumn($column_id, Column $col, $key = 'cols')
116    {
117        $base = 'schema[' . $key . '][' . $column_id . ']'; // base name for all fields
118
119        $class = $col->isEnabled() ? '' : 'disabled';
120
121        $html = "<tr class=\"$class\">";
122
123        $html .= '<td class="sort">';
124        $html .= '<input type="text" name="' . $base . '[sort]" value="' . hsc($col->getSort()) . '" size="3">';
125        $html .= '</td>';
126
127        $html .= '<td class="label">';
128        $html .= '<input type="text" name="' . $base . '[label]" value="' . hsc($col->getType()->getLabel()) . '">';
129        $html .= '</td>';
130
131        $html .= '<td class="ismulti">';
132        $checked = $col->getType()->isMulti() ? 'checked="checked"' : '';
133        $html .= '<input type="checkbox" name="' . $base . '[ismulti]" value="1" ' . $checked . '>';
134        $html .= '</td>';
135
136        $html .= '<td class="config">';
137        $config = json_encode($col->getType()->getConfig(), JSON_PRETTY_PRINT);
138        $html .= '<textarea name="' . $base . '[config]" cols="45" rows="10" class="config">' .
139            hsc($config) .
140            '</textarea>';
141        $html .= '</td>';
142
143        $types = array_keys(Column::allTypes());
144        $html .= '<td class="class">';
145        $html .= '<select name="' . $base . '[class]">';
146        foreach ($types as $type) {
147            $selected = ($col->getType()->getClass() == $type) ? 'selected="selected"' : '';
148            $html .= '<option value="' . hsc($type) . '" ' . $selected . '>' . hsc($type) . '</option>';
149        }
150        $html .= '</select>';
151        $html .= '</td>';
152
153
154        $html .= '<td class="isenabled">';
155        $checked = $col->isEnabled() ? 'checked="checked"' : '';
156        $html .= '<input type="checkbox" name="' . $base . '[isenabled]" value="1" ' . $checked . '>';
157        $html .= '</td>';
158
159        $html .= '</tr>';
160
161        return $html;
162    }
163}
164