[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
1 <?php 2 3 use dokuwiki\Extension\CLIPlugin; 4 use splitbrain\phpcli\Options; 5 use splitbrain\phpcli\TableFormatter; 6 use splitbrain\phpcli\Colors; 7 8 /** 9 * Class cli_plugin_extension 10 * 11 * Command Line component for the extension manager 12 * 13 * @license GPL2 14 * @author Andreas Gohr <andi@splitbrain.org> 15 */ 16 class cli_plugin_extension extends CLIPlugin 17 { 18 /** @inheritdoc */ 19 protected function setup(Options $options) 20 { 21 // general setup 22 $options->setHelp( 23 "Manage plugins and templates for this DokuWiki instance\n\n" . 24 "Status codes:\n" . 25 " i - installed\n" . 26 " b - bundled with DokuWiki\n" . 27 " g - installed via git\n" . 28 " d - disabled\n" . 29 " u - update available\n" 30 ); 31 32 // search 33 $options->registerCommand('search', 'Search for an extension'); 34 $options->registerOption('max', 'Maximum number of results (default 10)', 'm', 'number', 'search'); 35 $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'search'); 36 $options->registerArgument('query', 'The keyword(s) to search for', true, 'search'); 37 38 // list 39 $options->registerCommand('list', 'List installed extensions'); 40 $options->registerOption('verbose', 'Show detailed extension information', 'v', false, 'list'); 41 $options->registerOption('filter', 'Filter by this status', 'f', 'status', 'list'); 42 43 // upgrade 44 $options->registerCommand('upgrade', 'Update all installed extensions to their latest versions'); 45 46 // install 47 $options->registerCommand('install', 'Install or upgrade extensions'); 48 $options->registerArgument( 49 'extensions...', 50 'One or more extensions to install. Either by name or download URL', 51 true, 52 'install' 53 ); 54 55 // uninstall 56 $options->registerCommand('uninstall', 'Uninstall a new extension'); 57 $options->registerArgument('extensions...', 'One or more extensions to install', true, 'uninstall'); 58 59 // enable 60 $options->registerCommand('enable', 'Enable installed extensions'); 61 $options->registerArgument('extensions...', 'One or more extensions to enable', true, 'enable'); 62 63 // disable 64 $options->registerCommand('disable', 'Disable installed extensions'); 65 $options->registerArgument('extensions...', 'One or more extensions to disable', true, 'disable'); 66 } 67 68 /** @inheritdoc */ 69 protected function main(Options $options) 70 { 71 /** @var helper_plugin_extension_repository $repo */ 72 $repo = plugin_load('helper', 'extension_repository'); 73 if (!$repo->hasAccess(false)) { 74 $this->warning('Extension Repository API is not accessible, no remote info available!'); 75 } 76 77 switch ($options->getCmd()) { 78 case 'list': 79 $ret = $this->cmdList($options->getOpt('verbose'), $options->getOpt('filter', '')); 80 break; 81 case 'search': 82 $ret = $this->cmdSearch( 83 implode(' ', $options->getArgs()), 84 $options->getOpt('verbose'), 85 (int)$options->getOpt('max', 10) 86 ); 87 break; 88 case 'install': 89 $ret = $this->cmdInstall($options->getArgs()); 90 break; 91 case 'uninstall': 92 $ret = $this->cmdUnInstall($options->getArgs()); 93 break; 94 case 'enable': 95 $ret = $this->cmdEnable(true, $options->getArgs()); 96 break; 97 case 'disable': 98 $ret = $this->cmdEnable(false, $options->getArgs()); 99 break; 100 case 'upgrade': 101 $ret = $this->cmdUpgrade(); 102 break; 103 default: 104 echo $options->help(); 105 $ret = 0; 106 } 107 108 exit($ret); 109 } 110 111 /** 112 * Upgrade all extensions 113 * 114 * @return int 115 */ 116 protected function cmdUpgrade() 117 { 118 /* @var helper_plugin_extension_extension $ext */ 119 $ext = $this->loadHelper('extension_extension'); 120 $list = $this->getInstalledExtensions(); 121 122 $ok = 0; 123 foreach ($list as $extname) { 124 $ext->setExtension($extname); 125 $date = $ext->getInstalledVersion(); 126 $avail = $ext->getLastUpdate(); 127 if ($avail && $avail > $date && !$ext->isBundled()) { 128 $ok += $this->cmdInstall([$extname]); 129 } 130 } 131 132 return $ok; 133 } 134 135 /** 136 * Enable or disable one or more extensions 137 * 138 * @param bool $set 139 * @param string[] $extensions 140 * @return int 141 */ 142 protected function cmdEnable($set, $extensions) 143 { 144 /* @var helper_plugin_extension_extension $ext */ 145 $ext = $this->loadHelper('extension_extension'); 146 147 $ok = 0; 148 foreach ($extensions as $extname) { 149 $ext->setExtension($extname); 150 if (!$ext->isInstalled()) { 151 $this->error(sprintf('Extension %s is not installed', $ext->getID())); 152 ++$ok; 153 continue; 154 } 155 156 if ($set) { 157 $status = $ext->enable(); 158 $msg = 'msg_enabled'; 159 } else { 160 $status = $ext->disable(); 161 $msg = 'msg_disabled'; 162 } 163 164 if ($status !== true) { 165 $this->error($status); 166 ++$ok; 167 continue; 168 } else { 169 $this->success(sprintf($this->getLang($msg), $ext->getID())); 170 } 171 } 172 173 return $ok; 174 } 175 176 /** 177 * Uninstall one or more extensions 178 * 179 * @param string[] $extensions 180 * @return int 181 */ 182 protected function cmdUnInstall($extensions) 183 { 184 /* @var helper_plugin_extension_extension $ext */ 185 $ext = $this->loadHelper('extension_extension'); 186 187 $ok = 0; 188 foreach ($extensions as $extname) { 189 $ext->setExtension($extname); 190 if (!$ext->isInstalled()) { 191 $this->error(sprintf('Extension %s is not installed', $ext->getID())); 192 ++$ok; 193 continue; 194 } 195 196 $status = $ext->uninstall(); 197 if ($status) { 198 $this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID())); 199 } else { 200 $this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID()))); 201 $ok = 1; 202 } 203 } 204 205 return $ok; 206 } 207 208 /** 209 * Install one or more extensions 210 * 211 * @param string[] $extensions 212 * @return int 213 */ 214 protected function cmdInstall($extensions) 215 { 216 /* @var helper_plugin_extension_extension $ext */ 217 $ext = $this->loadHelper('extension_extension'); 218 219 $ok = 0; 220 foreach ($extensions as $extname) { 221 $installed = []; 222 223 if (preg_match("/^https?:\/\//i", $extname)) { 224 try { 225 $installed = $ext->installFromURL($extname, true); 226 } catch (Exception $e) { 227 $this->error($e->getMessage()); 228 ++$ok; 229 } 230 } else { 231 $ext->setExtension($extname); 232 233 if (!$ext->getDownloadURL()) { 234 ++$ok; 235 $this->error( 236 sprintf('Could not find download for %s', $ext->getID()) 237 ); 238 continue; 239 } 240 241 try { 242 $installed = $ext->installOrUpdate(); 243 } catch (Exception $e) { 244 $this->error($e->getMessage()); 245 ++$ok; 246 } 247 } 248 249 foreach ($installed as $info) { 250 $this->success( 251 sprintf( 252 $this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'), 253 $info['base'] 254 ) 255 ); 256 } 257 } 258 return $ok; 259 } 260 261 /** 262 * Search for an extension 263 * 264 * @param string $query 265 * @param bool $showdetails 266 * @param int $max 267 * @return int 268 * @throws \splitbrain\phpcli\Exception 269 */ 270 protected function cmdSearch($query, $showdetails, $max) 271 { 272 /** @var helper_plugin_extension_repository $repository */ 273 $repository = $this->loadHelper('extension_repository'); 274 $result = $repository->search($query); 275 if ($max) { 276 $result = array_slice($result, 0, $max); 277 } 278 279 $this->listExtensions($result, $showdetails); 280 return 0; 281 } 282 283 /** 284 * @param bool $showdetails 285 * @param string $filter 286 * @return int 287 * @throws \splitbrain\phpcli\Exception 288 */ 289 protected function cmdList($showdetails, $filter) 290 { 291 $list = $this->getInstalledExtensions(); 292 $this->listExtensions($list, $showdetails, $filter); 293 294 return 0; 295 } 296 297 /** 298 * Get all installed extensions 299 * 300 * @return array 301 */ 302 protected function getInstalledExtensions() 303 { 304 /** @var Doku_Plugin_Controller $plugin_controller */ 305 global $plugin_controller; 306 $pluginlist = $plugin_controller->getList('', true); 307 $tpllist = glob(DOKU_INC . 'lib/tpl/*', GLOB_ONLYDIR); 308 $tpllist = array_map(static fn($path) => 'template:' . basename($path), $tpllist); 309 310 $list = array_merge($pluginlist, $tpllist); 311 sort($list); 312 return $list; 313 } 314 315 /** 316 * List the given extensions 317 * 318 * @param string[] $list 319 * @param bool $details display details 320 * @param string $filter filter for this status 321 * @throws \splitbrain\phpcli\Exception 322 */ 323 protected function listExtensions($list, $details, $filter = '') 324 { 325 /** @var helper_plugin_extension_extension $ext */ 326 $ext = $this->loadHelper('extension_extension'); 327 $tr = new TableFormatter($this->colors); 328 329 330 foreach ($list as $name) { 331 $ext->setExtension($name); 332 333 $status = ''; 334 if ($ext->isInstalled()) { 335 $date = $ext->getInstalledVersion(); 336 $avail = $ext->getLastUpdate(); 337 $status = 'i'; 338 if ($avail && $avail > $date) { 339 $vcolor = Colors::C_RED; 340 $status .= 'u'; 341 } else { 342 $vcolor = Colors::C_GREEN; 343 } 344 if ($ext->isGitControlled()) $status = 'g'; 345 if ($ext->isBundled()) $status = 'b'; 346 if ($ext->isEnabled()) { 347 $ecolor = Colors::C_BROWN; 348 } else { 349 $ecolor = Colors::C_DARKGRAY; 350 $status .= 'd'; 351 } 352 } else { 353 $ecolor = null; 354 $date = $ext->getLastUpdate(); 355 $vcolor = null; 356 } 357 358 if ($filter && strpos($status, $filter) === false) { 359 continue; 360 } 361 362 echo $tr->format( 363 [20, 3, 12, '*'], 364 [ 365 $ext->getID(), 366 $status, 367 $date, 368 strip_tags(sprintf( 369 $this->getLang('extensionby'), 370 $ext->getDisplayName(), 371 $this->colors->wrap($ext->getAuthor(), Colors::C_PURPLE) 372 )) 373 ], 374 [ 375 $ecolor, 376 Colors::C_YELLOW, 377 $vcolor, 378 null, 379 ] 380 ); 381 382 if (!$details) continue; 383 384 echo $tr->format( 385 [5, '*'], 386 ['', $ext->getDescription()], 387 [null, Colors::C_CYAN] 388 ); 389 } 390 } 391 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body