1<?php 2 3use 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 <andi@splitbrain.org> 12 */ 13class 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 switch ($options->getCmd()) { 57 case 'list': 58 $ret = $this->cmdList($options->getOpt('verbose')); 59 break; 60 case 'search': 61 $ret = $this->cmdSearch( 62 implode(' ', $options->getArgs()), 63 $options->getOpt('verbose'), 64 (int)$options->getOpt('max', 10) 65 ); 66 break; 67 case 'install': 68 $ret = $this->cmdInstall($options->getArgs()); 69 break; 70 case 'uninstall': 71 $ret = $this->cmdUnInstall($options->getArgs()); 72 break; 73 case 'enable': 74 $ret = $this->cmdEnable(true, $options->getArgs()); 75 break; 76 case 'disable': 77 $ret = $this->cmdEnable(false, $options->getArgs()); 78 break; 79 case 'upgrade': 80 $ret = $this->cmdUpgrade(); 81 break; 82 default: 83 echo $options->help(); 84 $ret = 0; 85 } 86 87 exit($ret); 88 } 89 90 /** 91 * Upgrade all extensions 92 * 93 * @return int 94 */ 95 protected function cmdUpgrade() 96 { 97 /* @var helper_plugin_extension_extension $ext */ 98 $ext = $this->loadHelper('extension_extension'); 99 $list = $this->getInstalledExtensions(); 100 101 $ok = 0; 102 foreach ($list as $extname) { 103 $ext->setExtension($extname); 104 $date = $ext->getInstalledVersion(); 105 $avail = $ext->getLastUpdate(); 106 if ($avail && $avail > $date) { 107 $ok += $this->cmdInstall([$extname]); 108 } 109 } 110 111 return $ok; 112 } 113 114 /** 115 * Enable or disable one or more extensions 116 * 117 * @param bool $set 118 * @param string[] $extensions 119 * @return int 120 */ 121 protected function cmdEnable($set, $extensions) 122 { 123 /* @var helper_plugin_extension_extension $ext */ 124 $ext = $this->loadHelper('extension_extension'); 125 126 $ok = 0; 127 foreach ($extensions as $extname) { 128 $ext->setExtension($extname); 129 if (!$ext->isInstalled()) { 130 $this->error(sprintf('Extension %s is not installed', $ext->getID())); 131 $ok += 1; 132 continue; 133 } 134 135 if ($set) { 136 $status = $ext->enable(); 137 $msg = 'msg_enabled'; 138 } else { 139 $status = $ext->disable(); 140 $msg = 'msg_disabled'; 141 } 142 143 if ($status !== true) { 144 $this->error($status); 145 $ok += 1; 146 continue; 147 } else { 148 $this->success(sprintf($this->getLang($msg), $ext->getID())); 149 } 150 } 151 152 return $ok; 153 } 154 155 /** 156 * Uninstall one or more extensions 157 * 158 * @param string[] $extensions 159 * @return int 160 */ 161 protected function cmdUnInstall($extensions) 162 { 163 /* @var helper_plugin_extension_extension $ext */ 164 $ext = $this->loadHelper('extension_extension'); 165 166 $ok = 0; 167 foreach ($extensions as $extname) { 168 $ext->setExtension($extname); 169 if (!$ext->isInstalled()) { 170 $this->error(sprintf('Extension %s is not installed', $ext->getID())); 171 $ok += 1; 172 continue; 173 } 174 175 $status = $ext->uninstall(); 176 if ($status) { 177 $this->success(sprintf($this->getLang('msg_delete_success'), $ext->getID())); 178 } else { 179 $this->error(sprintf($this->getLang('msg_delete_failed'), hsc($ext->getID()))); 180 $ok = 1; 181 } 182 } 183 184 return $ok; 185 } 186 187 /** 188 * Install one or more extensions 189 * 190 * @param string[] $extensions 191 * @return int 192 */ 193 protected function cmdInstall($extensions) 194 { 195 /* @var helper_plugin_extension_extension $ext */ 196 $ext = $this->loadHelper('extension_extension'); 197 198 $ok = 0; 199 foreach ($extensions as $extname) { 200 $ext->setExtension($extname); 201 202 if (!$ext->getDownloadURL()) { 203 $ok += 1; 204 $this->error( 205 sprintf('Could not find download for %s', $ext->getID()) 206 ); 207 continue; 208 } 209 210 try { 211 $installed = $ext->installOrUpdate(); 212 foreach ($installed as $ext => $info) { 213 $this->success(sprintf( 214 $this->getLang('msg_' . $info['type'] . '_' . $info['action'] . '_success'), 215 $info['base']) 216 ); 217 } 218 } catch (Exception $e) { 219 $this->error($e->getMessage()); 220 $ok += 1; 221 } 222 } 223 return $ok; 224 } 225 226 /** 227 * Search for an extension 228 * 229 * @param string $query 230 * @param bool $showdetails 231 * @param int $max 232 * @return int 233 * @throws \splitbrain\phpcli\Exception 234 */ 235 protected function cmdSearch($query, $showdetails, $max) 236 { 237 /** @var helper_plugin_extension_repository $repository */ 238 $repository = $this->loadHelper('extension_repository'); 239 $result = $repository->search($query); 240 if ($max) { 241 $result = array_slice($result, 0, $max); 242 } 243 244 $this->listExtensions($result, $showdetails); 245 return 0; 246 } 247 248 /** 249 * @param bool $showdetails 250 * @return int 251 * @throws \splitbrain\phpcli\Exception 252 */ 253 protected function cmdList($showdetails) 254 { 255 $list = $this->getInstalledExtensions(); 256 $this->listExtensions($list, $showdetails); 257 258 return 0; 259 } 260 261 /** 262 * Get all installed extensions 263 * 264 * @return array 265 */ 266 protected function getInstalledExtensions() 267 { 268 /** @var Doku_Plugin_Controller $plugin_controller */ 269 global $plugin_controller; 270 $pluginlist = $plugin_controller->getList('', true); 271 $tpllist = glob(DOKU_INC . 'lib/tpl/*', GLOB_ONLYDIR); 272 $tpllist = array_map(function ($path) { 273 return 'template:' . basename($path); 274 }, $tpllist); 275 $list = array_merge($pluginlist, $tpllist); 276 sort($list); 277 return $list; 278 } 279 280 /** 281 * List the given extensions 282 * 283 * @param string[] $list 284 * @param bool $details display details 285 * @throws \splitbrain\phpcli\Exception 286 */ 287 protected function listExtensions($list, $details) 288 { 289 /** @var helper_plugin_extension_extension $ext */ 290 $ext = $this->loadHelper('extension_extension'); 291 $tr = new \splitbrain\phpcli\TableFormatter($this->colors); 292 293 294 foreach ($list as $name) { 295 $ext->setExtension($name); 296 297 $status = ''; 298 if ($ext->isInstalled()) { 299 $date = $ext->getInstalledVersion(); 300 $avail = $ext->getLastUpdate(); 301 $status = 'i'; 302 if ($avail && $avail > $date) { 303 $color = Colors::C_RED; 304 } else { 305 $color = Colors::C_GREEN; 306 } 307 if ($ext->isGitControlled()) $status = 'g'; 308 if ($ext->isBundled()) $status = 'b'; 309 if (!$ext->isEnabled()) $status .= 'd'; 310 } else { 311 $date = $ext->getLastUpdate(); 312 $color = null; 313 } 314 315 316 echo $tr->format( 317 [20, 3, 12, '*'], 318 [ 319 $ext->getID(), 320 $status, 321 $date, 322 strip_tags(sprintf( 323 $this->getLang('extensionby'), 324 $ext->getDisplayName(), 325 $this->colors->wrap($ext->getAuthor(), Colors::C_PURPLE)) 326 ) 327 ], 328 [ 329 Colors::C_BROWN, 330 Colors::C_YELLOW, 331 $color, 332 null, 333 ] 334 ); 335 336 if (!$details) continue; 337 338 echo $tr->format( 339 [5, '*'], 340 ['', $ext->getDescription()], 341 [null, Colors::C_CYAN] 342 ); 343 } 344 } 345} 346