Failed Conditions
Push — psr2-config ( 8ea568...077c27 )
by Andreas
03:33
created

admin_plugin_config::getTOC()   C

Complexity

Conditions 11
Paths 160

Size

Total Lines 51
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 33
nc 160
nop 0
dl 0
loc 51
rs 5.3599
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Configuration Manager admin plugin
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Christopher Smith <[email protected]>
7
 * @author     Ben Coburn <[email protected]>
8
 */
9
10
use dokuwiki\plugin\config\core\Configuration;
11
use dokuwiki\plugin\config\core\Setting;
12
use dokuwiki\plugin\config\core\SettingFieldset;
13
use dokuwiki\plugin\config\core\SettingHidden;
14
15
/**
16
 * All DokuWiki plugins to extend the admin function
17
 * need to inherit from this class
18
 */
19
class admin_plugin_config extends DokuWiki_Admin_Plugin {
20
21
    const METADATA = __DIR__ . 'settings/config.metadata.php';
22
    const IMGDIR = DOKU_BASE . 'lib/plugins/config/images/';
23
24
    protected $_localised_prompts = false;
25
26
    /** @var Configuration */
27
    protected $configuration;
28
29
    /**
30
     * admin_plugin_config constructor.
31
     */
32
    public function __construct() {
33
        $this->configuration = new Configuration();
34
    }
35
36
    /**
37
     * handle user request
38
     */
39
    public function handle() {
40
        global $ID, $INPUT;
41
42
        if(!$INPUT->bool('save') || !checkSecurityToken()) {
43
            return;
44
        }
45
46
        // don't go any further if the configuration is locked
47
        if($this->configuration->isLocked()) return;
48
49
        // update settings and redirect of successful
50
        $ok = $this->configuration->updateSettings($INPUT->arr('config'));
51
        if($ok) { // no errors
52
            try {
53
                if($this->configuration->hasChanged()) {
54
                    $this->configuration->save();
55
                } else {
56
                    $this->configuration->touch();
57
                }
58
                msg($this->getLang('updated'), -1);
59
            } catch(Exception $e) {
60
                msg($this->getLang('error'), -1);
61
            }
62
            send_redirect(wl($ID, array('do' => 'admin', 'page' => 'config'), true, '&'));
63
        }
64
    }
65
66
    /**
67
     * output appropriate html
68
     */
69
    public function html() {
70
        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
71
        global $lang;
72
        global $ID;
73
74
        $this->setupLocale(true);
75
76
        print $this->locale_xhtml('intro');
77
78
        ptln('<div id="config__manager">');
79
80
        if($this->configuration->isLocked()) {
81
            ptln('<div class="info">' . $this->getLang('locked') . '</div>');
82
        }
83
84
        // POST to script() instead of wl($ID) so config manager still works if
85
        // rewrite config is broken. Add $ID as hidden field to remember
86
        // current ID in most cases.
87
        ptln('<form action="' . script() . '" method="post">');
88
        ptln('<div class="no"><input type="hidden" name="id" value="' . $ID . '" /></div>');
89
        formSecurityToken();
90
        $this->_print_h1('dokuwiki_settings', $this->getLang('_header_dokuwiki'));
91
92
        $in_fieldset = false;
93
        $first_plugin_fieldset = true;
94
        $first_template_fieldset = true;
95
        foreach($this->configuration->getSettings() as $setting) {
96
            if(is_a($setting, SettingHidden::class)) {
97
                continue;
98
            } else if(is_a($setting, settingFieldset::class)) {
99
                // config setting group
100
                if($in_fieldset) {
101
                    ptln('  </table>');
102
                    ptln('  </div>');
103
                    ptln('  </fieldset>');
104
                } else {
105
                    $in_fieldset = true;
106
                }
107
                // fixme this should probably be a function in setting:
108
                if($first_plugin_fieldset && substr($setting->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) {
109
                    $this->_print_h1('plugin_settings', $this->getLang('_header_plugin'));
110
                    $first_plugin_fieldset = false;
111
                } else if($first_template_fieldset && substr($setting->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) {
112
                    $this->_print_h1('template_settings', $this->getLang('_header_template'));
113
                    $first_template_fieldset = false;
114
                }
115
                ptln('  <fieldset id="' . $setting->getKey() . '">');
116
                ptln('  <legend>' . $setting->prompt($this) . '</legend>');
117
                ptln('  <div class="table">');
118
                ptln('  <table class="inline">');
119
            } else {
120
                // config settings
121
                list($label, $input) = $setting->html($this, $this->_error);
0 ignored issues
show
Bug introduced by
The property _error does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
122
123
                $class = $setting->is_default()
124
                    ? ' class="default"'
125
                    : ($setting->is_protected() ? ' class="protected"' : '');
126
                $error = $setting->error()
127
                    ? ' class="value error"'
128
                    : ' class="value"';
129
                $icon = $setting->caution()
130
                    ? '<img src="' . self::IMGDIR . $setting->caution() . '.png" ' .
131
                    'alt="' . $setting->caution() . '" title="' . $this->getLang($setting->caution()) . '" />'
132
                    : '';
133
134
                ptln('    <tr' . $class . '>');
135
                ptln('      <td class="label">');
136
                ptln('        <span class="outkey">' . $setting->_out_key(true, true) . '</span>');
137
                ptln('        ' . $icon . $label);
138
                ptln('      </td>');
139
                ptln('      <td' . $error . '>' . $input . '</td>');
140
                ptln('    </tr>');
141
            }
142
        }
143
144
        ptln('  </table>');
145
        ptln('  </div>');
146
        if($in_fieldset) {
147
            ptln('  </fieldset>');
148
        }
149
150
        // show undefined settings list
151
        $undefined_settings = $this->configuration->getUndefined();
152
        if($allow_debug && !empty($undefined_settings)) {
153
            /**
154
             * Callback for sorting settings
155
             *
156
             * @param Setting $a
157
             * @param Setting $b
158
             * @return int if $a is lower/equal/higher than $b
159
             */
160
            function _setting_natural_comparison($a, $b) {
161
                return strnatcmp($a->getKey(), $b->getKey());
162
            }
163
164
            usort($undefined_settings, '_setting_natural_comparison');
165
            $this->_print_h1('undefined_settings', $this->getLang('_header_undefined'));
166
            ptln('<fieldset>');
167
            ptln('<div class="table">');
168
            ptln('<table class="inline">');
169
            $undefined_setting_match = array();
170
            foreach($undefined_settings as $setting) {
171
                if(
172
                preg_match(
173
                    '/^(?:plugin|tpl)' . Configuration::KEYMARKER . '.*?' . Configuration::KEYMARKER . '(.*)$/',
174
                    $setting->getKey(),
175
                    $undefined_setting_match
176
                )
177
                ) {
178
                    $undefined_setting_key = $undefined_setting_match[1];
179
                } else {
180
                    $undefined_setting_key = $setting->getKey();
181
                }
182
                ptln('  <tr>');
183
                ptln(
184
                    '    <td class="label"><span title="$meta[\'' . $undefined_setting_key . '\']">$' .
185
                    'conf' . '[\'' . $setting->_out_key() . '\']</span></td>'
186
                );
187
                ptln('    <td>' . $this->getLang('_msg_' . get_class($setting)) . '</td>');
188
                ptln('  </tr>');
189
            }
190
            ptln('</table>');
191
            ptln('</div>');
192
            ptln('</fieldset>');
193
        }
194
195
        // finish up form
196
        ptln('<p>');
197
        ptln('  <input type="hidden" name="do"     value="admin" />');
198
        ptln('  <input type="hidden" name="page"   value="config" />');
199
200
        if(!$this->configuration->isLocked()) {
201
            ptln('  <input type="hidden" name="save"   value="1" />');
202
            ptln('  <button type="submit" name="submit" accesskey="s">' . $lang['btn_save'] . '</button>');
203
            ptln('  <button type="reset">' . $lang['btn_reset'] . '</button>');
204
        }
205
206
        ptln('</p>');
207
208
        ptln('</form>');
209
        ptln('</div>');
210
    }
211
212
    /**
213
     * @param bool $prompts
214
     */
215
    public function setupLocale($prompts = false) {
216
217
        parent::setupLocale();
218
        if(!$prompts || $this->_localised_prompts) return;
219
220
        $this->_setup_localised_plugin_prompts();
221
        $this->_localised_prompts = true;
222
223
    }
224
225
    /**
226
     * @return bool
227
     * @fixme this should be done by the loader
228
     */
229
    protected function _setup_localised_plugin_prompts() {
230
        global $conf;
231
232
        $langfile = '/lang/' . $conf['lang'] . '/settings.php';
233
        $enlangfile = '/lang/en/settings.php';
234
235
        if($dh = opendir(DOKU_PLUGIN)) {
236
            while(false !== ($plugin = readdir($dh))) {
237
                if($plugin == '.' || $plugin == '..' || $plugin == 'tmp' || $plugin == 'config') continue;
238
                if(is_file(DOKU_PLUGIN . $plugin)) continue;
239
240
                if(file_exists(DOKU_PLUGIN . $plugin . $enlangfile)) {
241
                    $lang = array();
242
                    @include(DOKU_PLUGIN . $plugin . $enlangfile);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
243
                    if($conf['lang'] != 'en') @include(DOKU_PLUGIN . $plugin . $langfile);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
244
                    foreach($lang as $key => $value) {
245
                        $this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . $key] = $value;
246
                    }
247
                }
248
249
                // fill in the plugin name if missing (should exist for plugins with settings)
250
                if(!isset($this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . 'plugin_settings_name'])) {
251
                    $this->lang['plugin' . Configuration::KEYMARKER . $plugin . Configuration::KEYMARKER . 'plugin_settings_name'] =
252
                        ucwords(str_replace('_', ' ', $plugin));
253
                }
254
            }
255
            closedir($dh);
256
        }
257
258
        // the same for the active template
259
        $tpl = $conf['template'];
260
261
        if(file_exists(tpl_incdir() . $enlangfile)) {
262
            $lang = array();
263
            @include(tpl_incdir() . $enlangfile);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
264
            if($conf['lang'] != 'en') @include(tpl_incdir() . $langfile);
1 ignored issue
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
265
            foreach($lang as $key => $value) {
266
                $this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . $key] = $value;
267
            }
268
        }
269
270
        // fill in the template name if missing (should exist for templates with settings)
271
        if(!isset($this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . 'tpl_settings_name'])) {
272
            $this->lang['tpl' . Configuration::KEYMARKER . $tpl . Configuration::KEYMARKER . 'tpl_settings_name'] =
273
                ucwords(str_replace('_', ' ', $tpl));
274
        }
275
276
        return true;
277
    }
278
279
    /**
280
     * Generates a two-level table of contents for the config plugin.
281
     *
282
     * @author Ben Coburn <[email protected]>
283
     *
284
     * @return array
285
     */
286
    public function getTOC() {
287
        $this->setupLocale(true);
288
289
        $allow_debug = $GLOBALS['conf']['allowdebug']; // avoid global $conf; here.
290
291
        // gather toc data
292
        $toc = array('conf' => array(), 'plugin' => array(), 'template' => null);
293
        foreach($this->configuration->getSettings() as $setting) {
294
            if(is_a($setting, 'setting_fieldset')) {
295
                // FIXME as above this should go into Setting class
296
                if(substr($setting->getKey(), 0, 10) == 'plugin' . Configuration::KEYMARKER) {
297
                    $toc['plugin'][] = $setting;
298
                } else if(substr($setting->getKey(), 0, 7) == 'tpl' . Configuration::KEYMARKER) {
299
                    $toc['template'] = $setting;
300
                } else {
301
                    $toc['conf'][] = $setting;
302
                }
303
            }
304
        }
305
306
        // build toc
307
        $t = array();
308
309
        $check = false;
310
        $title = $this->getLang('_configuration_manager');
311
        $t[] = html_mktocitem(sectionID($title, $check), $title, 1);
312
        $t[] = html_mktocitem('dokuwiki_settings', $this->getLang('_header_dokuwiki'), 1);
313
        /** @var setting $setting */
314
        foreach($toc['conf'] as $setting) {
315
            $name = $setting->prompt($this);
316
            $t[] = html_mktocitem($setting->getKey(), $name, 2);
317
        }
318
        if(!empty($toc['plugin'])) {
319
            $t[] = html_mktocitem('plugin_settings', $this->getLang('_header_plugin'), 1);
320
        }
321
        foreach($toc['plugin'] as $setting) {
322
            $name = $setting->prompt($this);
323
            $t[] = html_mktocitem($setting->getKey(), $name, 2);
324
        }
325
        if(isset($toc['template'])) {
326
            $t[] = html_mktocitem('template_settings', $this->getLang('_header_template'), 1);
327
            $setting = $toc['template'];
328
            $name = $setting->prompt($this);
329
            $t[] = html_mktocitem($setting->getKey(), $name, 2);
330
        }
331
        if(count($this->configuration->getUndefined()) && $allow_debug) {
332
            $t[] = html_mktocitem('undefined_settings', $this->getLang('_header_undefined'), 1);
333
        }
334
335
        return $t;
336
    }
337
338
    /**
339
     * @param string $id
340
     * @param string $text
341
     */
342
    protected function _print_h1($id, $text) {
343
        ptln('<h1 id="' . $id . '">' . $text . '</h1>');
344
    }
345
346
    /**
347
     * Adds a translation to this plugin's language array
348
     *
349
     * @param string $key
350
     * @param string $value
351
     */
352
    public function addLang($key, $value) {
353
        if(!$this->localised) $this->setupLocale();
354
        $this->lang[$key] = $value;
355
    }
356
}
357