Failed Conditions
Pull Request — master (#2627)
by Andreas
10:50 queued 07:53
created

cli_plugin_extension::cmdEnable()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 6
nop 2
dl 0
loc 33
rs 9.0808
c 0
b 0
f 0
1
<?php
2
3
use splitbrain\phpcli\Colors;
4
5
/**
6
 * Class cli_plugin_extension
7
 *
8
 * Command Line component for the extension manager
9
 *
10
 * @license GPL2
11
 * @author Andreas Gohr <[email protected]>
12
 */
13
class cli_plugin_extension extends DokuWiki_CLI_Plugin
14
{
15
    /** @inheritdoc */
16
    protected function setup(\splitbrain\phpcli\Options $options)
17
    {
18
        // general setup
19
        $options->setHelp('Manage plugins and templates for this DokuWiki instance');
20
21
        // search
22
        $options->registerCommand('search', 'Search for an extension');
23
        $options->registerOption('max', 'Maximum number of results (default 10)', 'm', 'number', 'search');
24
        $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'search');
25
        $options->registerArgument('query', 'The keyword(s) to search for', true, 'search');
26
27
        // list
28
        $options->registerCommand('list', 'List installed extensions');
29
        $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'list');
30
31
        // upgrade
32
        $options->registerCommand('upgrade', 'Update all installed extensions to their latest versions');
33
34
        // install
35
        $options->registerCommand('install', 'Install or upgrade extensions');
36
        $options->registerArgument('extensions...', 'One or more extensions to install', true, 'install');
37
38
        // uninstall
39
        $options->registerCommand('uninstall', 'Uninstall a new extension');
40
        $options->registerArgument('extensions...', 'One or more extensions to install', true, 'uninstall');
41
42
        // enable
43
        $options->registerCommand('enable', 'Enable installed extensions');
44
        $options->registerArgument('extensions...', 'One or more extensions to enable', true, 'enable');
45
46
        // disable
47
        $options->registerCommand('disable', 'Disable installed extensions');
48
        $options->registerArgument('extensions...', 'One or more extensions to disable', true, 'disable');
49
50
51
    }
52
53
    /** @inheritdoc */
54
    protected function main(\splitbrain\phpcli\Options $options)
55
    {
56
        /** @var helper_plugin_extension_repository $repo */
57
        $repo = plugin_load('helper', 'extension_repository');
58
        if(!$repo->hasAccess(false)) {
59
            $this->warning('Extension Repository API is not accessible, no remote info available!');
60
        }
61
62
        switch ($options->getCmd()) {
63
            case 'list':
64
                $ret = $this->cmdList($options->getOpt('verbose'));
65
                break;
66
            case 'search':
67
                $ret = $this->cmdSearch(
68
                    implode(' ', $options->getArgs()),
69
                    $options->getOpt('verbose'),
70
                    (int)$options->getOpt('max', 10)
71
                );
72
                break;
73
            case 'install':
74
                $ret = $this->cmdInstall($options->getArgs());
75
                break;
76
            case 'uninstall':
77
                $ret = $this->cmdUnInstall($options->getArgs());
78
                break;
79
            case 'enable':
80
                $ret = $this->cmdEnable(true, $options->getArgs());
81
                break;
82
            case 'disable':
83
                $ret = $this->cmdEnable(false, $options->getArgs());
84
                break;
85
            case 'upgrade':
86
                $ret = $this->cmdUpgrade();
87
                break;
88
            default:
89
                echo $options->help();
90
                $ret = 0;
91
        }
92
93
        exit($ret);
94
    }
95
96
    /**
97
     * Upgrade all extensions
98
     *
99
     * @return int
100
     */
101
    protected function cmdUpgrade()
102
    {
103
        /* @var helper_plugin_extension_extension $ext */
104
        $ext = $this->loadHelper('extension_extension');
105
        $list = $this->getInstalledExtensions();
106
107
        $ok = 0;
108
        foreach ($list as $extname) {
109
            $ext->setExtension($extname);
110
            $date = $ext->getInstalledVersion();
111
            $avail = $ext->getLastUpdate();
112
            if ($avail && $avail > $date) {
113
                $ok += $this->cmdInstall([$extname]);
114
            }
115
        }
116
117
        return $ok;
118
    }
119
120
    /**
121
     * Enable or disable one or more extensions
122
     *
123
     * @param bool $set
124
     * @param string[] $extensions
125
     * @return int
126
     */
127
    protected function cmdEnable($set, $extensions)
128
    {
129
        /* @var helper_plugin_extension_extension $ext */
130
        $ext = $this->loadHelper('extension_extension');
131
132
        $ok = 0;
133
        foreach ($extensions as $extname) {
134
            $ext->setExtension($extname);
135
            if (!$ext->isInstalled()) {
136
                $this->error(sprintf('Extension %s is not installed', $ext->getID()));
137
                $ok += 1;
138
                continue;
139
            }
140
141
            if ($set) {
142
                $status = $ext->enable();
143
                $msg = 'msg_enabled';
144
            } else {
145
                $status = $ext->disable();
146
                $msg = 'msg_disabled';
147
            }
148
149
            if ($status !== true) {
150
                $this->error($status);
0 ignored issues
show
Bug introduced by
It seems like $status can also be of type boolean; however, splitbrain\phpcli\CLI::error() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
151
                $ok += 1;
152
                continue;
153
            } else {
154
                $this->success(sprintf($this->getLang($msg), $ext->getID()));
155
            }
156
        }
157
158
        return $ok;
159
    }
160
161
    /**
162
     * Uninstall one or more extensions
163
     *
164
     * @param string[] $extensions
165
     * @return int
166
     */
167
    protected function cmdUnInstall($extensions)
168
    {
169
        /* @var helper_plugin_extension_extension $ext */
170
        $ext = $this->loadHelper('extension_extension');
171
172
        $ok = 0;
173
        foreach ($extensions as $extname) {
174
            $ext->setExtension($extname);
175
            if (!$ext->isInstalled()) {
176
                $this->error(sprintf('Extension %s is not installed', $ext->getID()));
177
                $ok += 1;
178
                continue;
179
            }
180
181
            $status = $ext->uninstall();
182
            if ($status) {
183
                $this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID()));
184
            } else {
185
                $this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID())));
186
                $ok = 1;
187
            }
188
        }
189
190
        return $ok;
191
    }
192
193
    /**
194
     * Install one or more extensions
195
     *
196
     * @param string[] $extensions
197
     * @return int
198
     */
199
    protected function cmdInstall($extensions)
200
    {
201
        /* @var helper_plugin_extension_extension $ext */
202
        $ext = $this->loadHelper('extension_extension');
203
204
        $ok = 0;
205
        foreach ($extensions as $extname) {
206
            $ext->setExtension($extname);
207
208
            if (!$ext->getDownloadURL()) {
209
                $ok += 1;
210
                $this->error(
211
                    sprintf('Could not find download for %s', $ext->getID())
212
                );
213
                continue;
214
            }
215
216
            try {
217
                $installed = $ext->installOrUpdate();
218
                foreach ($installed as $ext => $info) {
219
                    $this->success(sprintf(
220
                            $this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'),
221
                            $info['base'])
222
                    );
223
                }
224
            } catch (Exception $e) {
225
                $this->error($e->getMessage());
226
                $ok += 1;
227
            }
228
        }
229
        return $ok;
230
    }
231
232
    /**
233
     * Search for an extension
234
     *
235
     * @param string $query
236
     * @param bool $showdetails
237
     * @param int $max
238
     * @return int
239
     * @throws \splitbrain\phpcli\Exception
240
     */
241
    protected function cmdSearch($query, $showdetails, $max)
242
    {
243
        /** @var helper_plugin_extension_repository $repository */
244
        $repository = $this->loadHelper('extension_repository');
245
        $result = $repository->search($query);
246
        if ($max) {
247
            $result = array_slice($result, 0, $max);
248
        }
249
250
        $this->listExtensions($result, $showdetails);
251
        return 0;
252
    }
253
254
    /**
255
     * @param bool $showdetails
256
     * @return int
257
     * @throws \splitbrain\phpcli\Exception
258
     */
259
    protected function cmdList($showdetails)
260
    {
261
        $list = $this->getInstalledExtensions();
262
        $this->listExtensions($list, $showdetails);
263
264
        return 0;
265
    }
266
267
    /**
268
     * Get all installed extensions
269
     *
270
     * @return array
271
     */
272
    protected function getInstalledExtensions()
273
    {
274
        /** @var Doku_Plugin_Controller $plugin_controller */
275
        global $plugin_controller;
276
        $pluginlist = $plugin_controller->getList('', true);
277
        $tpllist = glob(DOKU_INC . 'lib/tpl/*', GLOB_ONLYDIR);
278
        $tpllist = array_map(function ($path) {
279
            return 'template:' . basename($path);
280
        }, $tpllist);
281
        $list = array_merge($pluginlist, $tpllist);
282
        sort($list);
283
        return $list;
284
    }
285
286
    /**
287
     * List the given extensions
288
     *
289
     * @param string[] $list
290
     * @param bool $details display details
291
     * @throws \splitbrain\phpcli\Exception
292
     */
293
    protected function listExtensions($list, $details)
294
    {
295
        /** @var helper_plugin_extension_extension $ext */
296
        $ext = $this->loadHelper('extension_extension');
297
        $tr = new \splitbrain\phpcli\TableFormatter($this->colors);
298
299
300
        foreach ($list as $name) {
301
            $ext->setExtension($name);
302
303
            $status = '';
304
            if ($ext->isInstalled()) {
305
                $date = $ext->getInstalledVersion();
306
                $avail = $ext->getLastUpdate();
307
                $status = 'i';
308
                if ($avail && $avail > $date) {
309
                    $vcolor = Colors::C_RED;
310
                } else {
311
                    $vcolor = Colors::C_GREEN;
312
                }
313
                if ($ext->isGitControlled()) $status = 'g';
314
                if ($ext->isBundled()) $status = 'b';
315
                if ($ext->isEnabled()) {
316
                    $ecolor = Colors::C_BROWN;
317
                } else {
318
                    $ecolor = Colors::C_DARKGRAY;
319
                    $status .= 'd';
320
                }
321
            } else {
322
                $ecolor = null;
323
                $date = $ext->getLastUpdate();
324
                $vcolor = null;
325
            }
326
327
328
            echo $tr->format(
329
                [20, 3, 12, '*'],
330
                [
0 ignored issues
show
Documentation introduced by
array($ext->getID(), $st...li\Colors::C_PURPLE)))) is of type array<integer,string|boo...boolean","3":"string"}>, but the function expects a array<integer,string>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
331
                    $ext->getID(),
332
                    $status,
333
                    $date,
334
                    strip_tags(sprintf(
335
                            $this->getLang('extensionby'),
336
                            $ext->getDisplayName(),
337
                            $this->colors->wrap($ext->getAuthor(), Colors::C_PURPLE))
0 ignored issues
show
Bug introduced by
It seems like $ext->getAuthor() targeting helper_plugin_extension_extension::getAuthor() can also be of type boolean; however, splitbrain\phpcli\Colors::wrap() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
338
                    )
339
                ],
340
                [
341
                    $ecolor,
342
                    Colors::C_YELLOW,
343
                    $vcolor,
344
                    null,
345
                ]
346
            );
347
348
            if (!$details) continue;
349
350
            echo $tr->format(
351
                [5, '*'],
352
                ['', $ext->getDescription()],
353
                [null, Colors::C_CYAN]
354
            );
355
        }
356
    }
357
}
358