136c0b2b4SAndreas Gohr#!/usr/bin/env php 236c0b2b4SAndreas Gohr<?php 336c0b2b4SAndreas Gohr 436c0b2b4SAndreas Gohruse dokuwiki\Extension\CLIPlugin; 536c0b2b4SAndreas Gohruse dokuwiki\Extension\PluginController; 65586e97bSAndreas Gohruse dokuwiki\plugin\dev\LangProcessor; 770316b84SAndreas Gohruse dokuwiki\plugin\dev\Skeletor; 81a23d1dbSAndreas Gohruse dokuwiki\plugin\dev\SVGIcon; 936c0b2b4SAndreas Gohruse splitbrain\phpcli\Exception as CliException; 1036c0b2b4SAndreas Gohruse splitbrain\phpcli\Options; 1136c0b2b4SAndreas Gohr 1236c0b2b4SAndreas Gohr/** 1336c0b2b4SAndreas Gohr * @license GPL2 1436c0b2b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1536c0b2b4SAndreas Gohr */ 1636c0b2b4SAndreas Gohrclass cli_plugin_dev extends CLIPlugin 1736c0b2b4SAndreas Gohr{ 1836c0b2b4SAndreas Gohr /** 1936c0b2b4SAndreas Gohr * Register options and arguments on the given $options object 2036c0b2b4SAndreas Gohr * 2136c0b2b4SAndreas Gohr * @param Options $options 2236c0b2b4SAndreas Gohr * @return void 2336c0b2b4SAndreas Gohr */ 2436c0b2b4SAndreas Gohr protected function setup(Options $options) 2536c0b2b4SAndreas Gohr { 26f2576912SAndreas Gohr $options->useCompactHelp(); 2736c0b2b4SAndreas Gohr $options->setHelp( 28f2576912SAndreas Gohr "CLI to help with DokuWiki plugin and template development.\n\n" . 2936c0b2b4SAndreas Gohr "Run this script from within the extension's directory." 3036c0b2b4SAndreas Gohr ); 3136c0b2b4SAndreas Gohr 32fcb8165bSAndreas Gohr $options->registerCommand('init', 'Initialize a new plugin or template in the current directory.'); 33f2576912SAndreas Gohr $options->registerCommand('addTest', 'Add the testing framework files and a test. (_test/)'); 34f2576912SAndreas Gohr $options->registerArgument('test', 'Optional name of the new test. Defaults to the general test.', false, 35f2576912SAndreas Gohr 'addTest'); 36f2576912SAndreas Gohr $options->registerCommand('addConf', 'Add the configuration files. (conf/)'); 37f2576912SAndreas Gohr $options->registerCommand('addLang', 'Add the language files. (lang/)'); 3836c0b2b4SAndreas Gohr 39f2576912SAndreas Gohr $types = PluginController::PLUGIN_TYPES; 40f2576912SAndreas Gohr array_walk( 41f2576912SAndreas Gohr $types, 42f2576912SAndreas Gohr function (&$item) { 43f2576912SAndreas Gohr $item = $this->colors->wrap($item, $this->colors::C_BROWN); 44f2576912SAndreas Gohr } 4536c0b2b4SAndreas Gohr ); 4636c0b2b4SAndreas Gohr 47f2576912SAndreas Gohr $options->registerCommand('addComponent', 'Add a new plugin component.'); 48f2576912SAndreas Gohr $options->registerArgument('type', 'Type of the component. Needs to be one of ' . join(', ', $types), true, 49f2576912SAndreas Gohr 'addComponent'); 50f2576912SAndreas Gohr $options->registerArgument('name', 'Optional name of the component. Defaults to a base component.', false, 51f2576912SAndreas Gohr 'addComponent'); 52f2576912SAndreas Gohr 53f2576912SAndreas Gohr $options->registerCommand('deletedFiles', 'Create the list of deleted files based on the git history.'); 54f2576912SAndreas Gohr $options->registerCommand('rmObsolete', 'Delete obsolete files.'); 551a23d1dbSAndreas Gohr 561a23d1dbSAndreas Gohr $prefixes = array_keys(SVGIcon::SOURCES); 571a23d1dbSAndreas Gohr array_walk( 581a23d1dbSAndreas Gohr $prefixes, 591a23d1dbSAndreas Gohr function (&$item) { 601a23d1dbSAndreas Gohr $item = $this->colors->wrap($item, $this->colors::C_BROWN); 611a23d1dbSAndreas Gohr } 621a23d1dbSAndreas Gohr ); 631a23d1dbSAndreas Gohr 641a23d1dbSAndreas Gohr $options->registerCommand('downloadSvg', 'Download an SVG file from a known icon repository.'); 651a23d1dbSAndreas Gohr $options->registerArgument('prefix:name', 661a23d1dbSAndreas Gohr 'Colon-prefixed name of the icon. Available prefixes: ' . join(', ', $prefixes), true, 'downloadSvg'); 671a23d1dbSAndreas Gohr $options->registerArgument('output', 'File to save, defaults to <name>.svg in current dir', false, 681a23d1dbSAndreas Gohr 'downloadSvg'); 6992738407SAndreas Gohr $options->registerOption('keep-ns', 'Keep the SVG namespace. Use when the file is not inlined into HTML.', 'k', 7092738407SAndreas Gohr false, 'downloadSvg'); 711a23d1dbSAndreas Gohr 728f82d673SAndreas Gohr $options->registerCommand('cleanSvg', 'Clean a existing SVG files to reduce their file size.'); 738f82d673SAndreas Gohr $options->registerArgument('files...', 'The files to clean (will be overwritten)', true, 'cleanSvg'); 7492738407SAndreas Gohr $options->registerOption('keep-ns', 'Keep the SVG namespace. Use when the file is not inlined into HTML.', 'k', 7592738407SAndreas Gohr false, 'cleanSvg'); 765586e97bSAndreas Gohr 775586e97bSAndreas Gohr $options->registerCommand('cleanLang', 785586e97bSAndreas Gohr 'Clean language files from unused language strings. Detecting which strings are truly in use may ' . 795586e97bSAndreas Gohr 'not always correctly work. Use with caution.'); 80ec0a687bSAndreas Gohr 81*57732a2dSAndreas Gohr $options->registerCommand( 82*57732a2dSAndreas Gohr 'test', 83*57732a2dSAndreas Gohr 'Run the unit tests for this extension. (calls phpunit using the proper config and group)' 84*57732a2dSAndreas Gohr ); 85*57732a2dSAndreas Gohr $options->registerOption( 86*57732a2dSAndreas Gohr 'filter', 87*57732a2dSAndreas Gohr 'Filter tests to run by a given string. (passed to phpunit)', 88*57732a2dSAndreas Gohr null, 89*57732a2dSAndreas Gohr true, 90*57732a2dSAndreas Gohr 'test' 91*57732a2dSAndreas Gohr ); 92*57732a2dSAndreas Gohr $options->registerArgument('files...', 'The test files to run. Defaults to all.', false, 'test'); 93ec0a687bSAndreas Gohr 94ec0a687bSAndreas Gohr $options->registerCommand('check', 'Check for code style violations.'); 95ec0a687bSAndreas Gohr $options->registerArgument('files...', 'The files to check. Defaults to the whole extension.', false, 'check'); 96ec0a687bSAndreas Gohr 97ec0a687bSAndreas Gohr $options->registerCommand('fix', 'Fix code style violations and refactor outdated code.'); 98ec0a687bSAndreas Gohr $options->registerArgument('files...', 'The files to check. Defaults to the whole extension.', false, 'fix'); 9936c0b2b4SAndreas Gohr } 10036c0b2b4SAndreas Gohr 10136c0b2b4SAndreas Gohr /** @inheritDoc */ 10236c0b2b4SAndreas Gohr protected function main(Options $options) 10336c0b2b4SAndreas Gohr { 1041a23d1dbSAndreas Gohr $args = $options->getArgs(); 1051a23d1dbSAndreas Gohr 10636c0b2b4SAndreas Gohr switch ($options->getCmd()) { 10736c0b2b4SAndreas Gohr case 'init': 10836c0b2b4SAndreas Gohr return $this->cmdInit(); 10936c0b2b4SAndreas Gohr case 'addTest': 11036c0b2b4SAndreas Gohr $test = array_shift($args); 11136c0b2b4SAndreas Gohr return $this->cmdAddTest($test); 11236c0b2b4SAndreas Gohr case 'addConf': 11336c0b2b4SAndreas Gohr return $this->cmdAddConf(); 11436c0b2b4SAndreas Gohr case 'addLang': 11536c0b2b4SAndreas Gohr return $this->cmdAddLang(); 11636c0b2b4SAndreas Gohr case 'addComponent': 11736c0b2b4SAndreas Gohr $type = array_shift($args); 11836c0b2b4SAndreas Gohr $component = array_shift($args); 11936c0b2b4SAndreas Gohr return $this->cmdAddComponent($type, $component); 12036c0b2b4SAndreas Gohr case 'deletedFiles': 12136c0b2b4SAndreas Gohr return $this->cmdDeletedFiles(); 122c5c85a97SAndreas Gohr case 'rmObsolete': 1231a23d1dbSAndreas Gohr return $this->cmdRmObsolete(); 1241a23d1dbSAndreas Gohr case 'downloadSvg': 1251a23d1dbSAndreas Gohr $ident = array_shift($args); 1261a23d1dbSAndreas Gohr $save = array_shift($args); 12770316b84SAndreas Gohr $keep = $options->getOpt('keep-ns'); 12892738407SAndreas Gohr return $this->cmdDownloadSVG($ident, $save, $keep); 1291a23d1dbSAndreas Gohr case 'cleanSvg': 13070316b84SAndreas Gohr $keep = $options->getOpt('keep-ns'); 1318f82d673SAndreas Gohr return $this->cmdCleanSVG($args, $keep); 1325586e97bSAndreas Gohr case 'cleanLang': 1335586e97bSAndreas Gohr return $this->cmdCleanLang(); 134ec0a687bSAndreas Gohr case 'test': 135*57732a2dSAndreas Gohr $filter = $options->getOpt('filter'); 136*57732a2dSAndreas Gohr return $this->cmdTest($filter, $args); 137ec0a687bSAndreas Gohr case 'check': 138ec0a687bSAndreas Gohr return $this->cmdCheck($args); 139ec0a687bSAndreas Gohr case 'fix': 140ec0a687bSAndreas Gohr return $this->cmdFix(); 14136c0b2b4SAndreas Gohr default: 1421a23d1dbSAndreas Gohr $this->error('Unknown command'); 14336c0b2b4SAndreas Gohr echo $options->help(); 14436c0b2b4SAndreas Gohr return 0; 14536c0b2b4SAndreas Gohr } 14636c0b2b4SAndreas Gohr } 14736c0b2b4SAndreas Gohr 14836c0b2b4SAndreas Gohr /** 14936c0b2b4SAndreas Gohr * Get the extension name from the current working directory 15036c0b2b4SAndreas Gohr * 15136c0b2b4SAndreas Gohr * @throws CliException if something's wrong 15236c0b2b4SAndreas Gohr * @param string $dir 15336c0b2b4SAndreas Gohr * @return string[] name, type 15436c0b2b4SAndreas Gohr */ 15536c0b2b4SAndreas Gohr protected function getTypedNameFromDir($dir) 15636c0b2b4SAndreas Gohr { 15736c0b2b4SAndreas Gohr $pdir = fullpath(DOKU_PLUGIN); 15836c0b2b4SAndreas Gohr $tdir = fullpath(tpl_incdir() . '../'); 15936c0b2b4SAndreas Gohr 16036c0b2b4SAndreas Gohr if (strpos($dir, $pdir) === 0) { 16136c0b2b4SAndreas Gohr $ldir = substr($dir, strlen($pdir)); 16236c0b2b4SAndreas Gohr $type = 'plugin'; 16336c0b2b4SAndreas Gohr } elseif (strpos($dir, $tdir) === 0) { 16436c0b2b4SAndreas Gohr $ldir = substr($dir, strlen($tdir)); 16536c0b2b4SAndreas Gohr $type = 'template'; 16636c0b2b4SAndreas Gohr } else { 16736c0b2b4SAndreas Gohr throw new CliException('Current directory needs to be in plugin or template directory'); 16836c0b2b4SAndreas Gohr } 16936c0b2b4SAndreas Gohr 17036c0b2b4SAndreas Gohr $ldir = trim($ldir, '/'); 17136c0b2b4SAndreas Gohr 17236c0b2b4SAndreas Gohr if (strpos($ldir, '/') !== false) { 17336c0b2b4SAndreas Gohr throw new CliException('Current directory has to be main extension directory'); 17436c0b2b4SAndreas Gohr } 17536c0b2b4SAndreas Gohr 17636c0b2b4SAndreas Gohr return [$ldir, $type]; 17736c0b2b4SAndreas Gohr } 17836c0b2b4SAndreas Gohr 17936c0b2b4SAndreas Gohr /** 18036c0b2b4SAndreas Gohr * Interactively ask for a value from the user 18136c0b2b4SAndreas Gohr * 18236c0b2b4SAndreas Gohr * @param string $prompt 18336c0b2b4SAndreas Gohr * @param bool $cache cache given value for next time? 18436c0b2b4SAndreas Gohr * @return string 18536c0b2b4SAndreas Gohr */ 18636c0b2b4SAndreas Gohr protected function readLine($prompt, $cache = false) 18736c0b2b4SAndreas Gohr { 18836c0b2b4SAndreas Gohr $value = ''; 18936c0b2b4SAndreas Gohr $default = ''; 19036c0b2b4SAndreas Gohr $cachename = getCacheName($prompt, '.readline'); 19136c0b2b4SAndreas Gohr if ($cache && file_exists($cachename)) { 19236c0b2b4SAndreas Gohr $default = file_get_contents($cachename); 19336c0b2b4SAndreas Gohr } 19436c0b2b4SAndreas Gohr 19536c0b2b4SAndreas Gohr while ($value === '') { 19636c0b2b4SAndreas Gohr echo $prompt; 19736c0b2b4SAndreas Gohr if ($default) echo ' [' . $default . ']'; 19836c0b2b4SAndreas Gohr echo ': '; 19936c0b2b4SAndreas Gohr 20036c0b2b4SAndreas Gohr $fh = fopen('php://stdin', 'r'); 20136c0b2b4SAndreas Gohr $value = trim(fgets($fh)); 20236c0b2b4SAndreas Gohr fclose($fh); 20336c0b2b4SAndreas Gohr 20436c0b2b4SAndreas Gohr if ($value === '') $value = $default; 20536c0b2b4SAndreas Gohr } 20636c0b2b4SAndreas Gohr 20736c0b2b4SAndreas Gohr if ($cache) { 20836c0b2b4SAndreas Gohr file_put_contents($cachename, $value); 20936c0b2b4SAndreas Gohr } 21036c0b2b4SAndreas Gohr 21136c0b2b4SAndreas Gohr return $value; 21236c0b2b4SAndreas Gohr } 21336c0b2b4SAndreas Gohr 21436c0b2b4SAndreas Gohr /** 21570316b84SAndreas Gohr * Create the given files with their given content 21636c0b2b4SAndreas Gohr * 21770316b84SAndreas Gohr * Ignores all files that already exist 21870316b84SAndreas Gohr * 21970316b84SAndreas Gohr * @param array $files A File array as created by Skeletor::getFiles() 22036c0b2b4SAndreas Gohr */ 221fcb8165bSAndreas Gohr protected function createFiles($files) 222fcb8165bSAndreas Gohr { 22370316b84SAndreas Gohr foreach ($files as $path => $content) { 22470316b84SAndreas Gohr if (file_exists($path)) { 22570316b84SAndreas Gohr $this->error($path . ' already exists'); 22670316b84SAndreas Gohr continue; 22736c0b2b4SAndreas Gohr } 22836c0b2b4SAndreas Gohr 22970316b84SAndreas Gohr io_makeFileDir($path); 23070316b84SAndreas Gohr file_put_contents($path, $content); 23170316b84SAndreas Gohr $this->success($path . ' created'); 23236c0b2b4SAndreas Gohr } 23336c0b2b4SAndreas Gohr } 23436c0b2b4SAndreas Gohr 23536c0b2b4SAndreas Gohr /** 236c5c85a97SAndreas Gohr * Delete the given file if it exists 237c5c85a97SAndreas Gohr * 238c5c85a97SAndreas Gohr * @param string $file 239c5c85a97SAndreas Gohr */ 240c5c85a97SAndreas Gohr protected function deleteFile($file) 241c5c85a97SAndreas Gohr { 242c5c85a97SAndreas Gohr if (!file_exists($file)) return; 243c5c85a97SAndreas Gohr if (@unlink($file)) { 244c5c85a97SAndreas Gohr $this->success('Delete ' . $file); 245c5c85a97SAndreas Gohr } 246c5c85a97SAndreas Gohr } 247c5c85a97SAndreas Gohr 248c5c85a97SAndreas Gohr /** 249c5c85a97SAndreas Gohr * Run git with the given arguments and return the output 250c5c85a97SAndreas Gohr * 251c5c85a97SAndreas Gohr * @throws CliException when the command can't be run 252c5c85a97SAndreas Gohr * @param string ...$args 253c5c85a97SAndreas Gohr * @return string[] 254c5c85a97SAndreas Gohr */ 255c5c85a97SAndreas Gohr protected function git(...$args) 256c5c85a97SAndreas Gohr { 257c5c85a97SAndreas Gohr $args = array_map('escapeshellarg', $args); 258c5c85a97SAndreas Gohr $cmd = 'git ' . join(' ', $args); 259c5c85a97SAndreas Gohr $output = []; 260c5c85a97SAndreas Gohr $result = 0; 261c5c85a97SAndreas Gohr 262c5c85a97SAndreas Gohr $this->info($cmd); 263c5c85a97SAndreas Gohr $last = exec($cmd, $output, $result); 264c5c85a97SAndreas Gohr if ($last === false || $result !== 0) { 265c5c85a97SAndreas Gohr throw new CliException('Running git failed'); 266c5c85a97SAndreas Gohr } 267c5c85a97SAndreas Gohr 268c5c85a97SAndreas Gohr return $output; 269c5c85a97SAndreas Gohr } 270c5c85a97SAndreas Gohr 271c5c85a97SAndreas Gohr // region Commands 272c5c85a97SAndreas Gohr 273c5c85a97SAndreas Gohr /** 27436c0b2b4SAndreas Gohr * Intialize the current directory as a plugin or template 27536c0b2b4SAndreas Gohr * 27636c0b2b4SAndreas Gohr * @return int 27736c0b2b4SAndreas Gohr */ 27836c0b2b4SAndreas Gohr protected function cmdInit() 27936c0b2b4SAndreas Gohr { 28036c0b2b4SAndreas Gohr $dir = fullpath(getcwd()); 28136c0b2b4SAndreas Gohr if ((new FilesystemIterator($dir))->valid()) { 282fcb8165bSAndreas Gohr // existing directory, initialize from info file 283fcb8165bSAndreas Gohr $skeletor = Skeletor::fromDir($dir); 284fcb8165bSAndreas Gohr } else { 285fcb8165bSAndreas Gohr // new directory, ask for info 28670316b84SAndreas Gohr [$base, $type] = $this->getTypedNameFromDir($dir); 28736c0b2b4SAndreas Gohr $user = $this->readLine('Your Name', true); 28836c0b2b4SAndreas Gohr $mail = $this->readLine('Your E-Mail', true); 28936c0b2b4SAndreas Gohr $desc = $this->readLine('Short description'); 29070316b84SAndreas Gohr $skeletor = new Skeletor($type, $base, $desc, $user, $mail); 291fcb8165bSAndreas Gohr } 29270316b84SAndreas Gohr $skeletor->addBasics(); 29370316b84SAndreas Gohr $this->createFiles($skeletor->getFiles()); 29436c0b2b4SAndreas Gohr 295fcb8165bSAndreas Gohr if (!is_dir("$dir/.git")) { 2968b06c9ddSAndreas Gohr try { 2978b06c9ddSAndreas Gohr $this->git('init'); 2988b06c9ddSAndreas Gohr } catch (CliException $e) { 2998b06c9ddSAndreas Gohr $this->error($e->getMessage()); 3008b06c9ddSAndreas Gohr } 301fcb8165bSAndreas Gohr } 3028b06c9ddSAndreas Gohr 30336c0b2b4SAndreas Gohr return 0; 30436c0b2b4SAndreas Gohr } 30536c0b2b4SAndreas Gohr 30636c0b2b4SAndreas Gohr /** 30736c0b2b4SAndreas Gohr * Add test framework 30836c0b2b4SAndreas Gohr * 30936c0b2b4SAndreas Gohr * @param string $test Name of the Test to add 31036c0b2b4SAndreas Gohr * @return int 31136c0b2b4SAndreas Gohr */ 31236c0b2b4SAndreas Gohr protected function cmdAddTest($test = '') 31336c0b2b4SAndreas Gohr { 31470316b84SAndreas Gohr $skeletor = Skeletor::fromDir(getcwd()); 31570316b84SAndreas Gohr $skeletor->addTest($test); 31670316b84SAndreas Gohr $this->createFiles($skeletor->getFiles()); 31736c0b2b4SAndreas Gohr return 0; 31836c0b2b4SAndreas Gohr } 31936c0b2b4SAndreas Gohr 32036c0b2b4SAndreas Gohr /** 32136c0b2b4SAndreas Gohr * Add configuration 32236c0b2b4SAndreas Gohr * 32336c0b2b4SAndreas Gohr * @return int 32436c0b2b4SAndreas Gohr */ 32536c0b2b4SAndreas Gohr protected function cmdAddConf() 32636c0b2b4SAndreas Gohr { 32770316b84SAndreas Gohr $skeletor = Skeletor::fromDir(getcwd()); 32870316b84SAndreas Gohr $skeletor->addConf(is_dir('lang')); 32970316b84SAndreas Gohr $this->createFiles($skeletor->getFiles()); 33036c0b2b4SAndreas Gohr return 0; 33136c0b2b4SAndreas Gohr } 33236c0b2b4SAndreas Gohr 33336c0b2b4SAndreas Gohr /** 33436c0b2b4SAndreas Gohr * Add language 33536c0b2b4SAndreas Gohr * 33636c0b2b4SAndreas Gohr * @return int 33736c0b2b4SAndreas Gohr */ 33836c0b2b4SAndreas Gohr protected function cmdAddLang() 33936c0b2b4SAndreas Gohr { 34070316b84SAndreas Gohr $skeletor = Skeletor::fromDir(getcwd()); 34170316b84SAndreas Gohr $skeletor->addLang(is_dir('conf')); 34270316b84SAndreas Gohr $this->createFiles($skeletor->getFiles()); 34336c0b2b4SAndreas Gohr return 0; 34436c0b2b4SAndreas Gohr } 34536c0b2b4SAndreas Gohr 34636c0b2b4SAndreas Gohr /** 34736c0b2b4SAndreas Gohr * Add another component to the plugin 34836c0b2b4SAndreas Gohr * 34936c0b2b4SAndreas Gohr * @param string $type 35036c0b2b4SAndreas Gohr * @param string $component 35136c0b2b4SAndreas Gohr */ 35236c0b2b4SAndreas Gohr protected function cmdAddComponent($type, $component = '') 35336c0b2b4SAndreas Gohr { 35470316b84SAndreas Gohr $skeletor = Skeletor::fromDir(getcwd()); 35570316b84SAndreas Gohr $skeletor->addComponent($type, $component); 35670316b84SAndreas Gohr $this->createFiles($skeletor->getFiles()); 35736c0b2b4SAndreas Gohr return 0; 35836c0b2b4SAndreas Gohr } 35936c0b2b4SAndreas Gohr 36036c0b2b4SAndreas Gohr /** 36136c0b2b4SAndreas Gohr * Generate a list of deleted files from git 36236c0b2b4SAndreas Gohr * 36336c0b2b4SAndreas Gohr * @link https://stackoverflow.com/a/6018049/172068 36436c0b2b4SAndreas Gohr */ 36536c0b2b4SAndreas Gohr protected function cmdDeletedFiles() 36636c0b2b4SAndreas Gohr { 3678b06c9ddSAndreas Gohr if (!is_dir('.git')) throw new CliException('This extension seems not to be managed by git'); 36836c0b2b4SAndreas Gohr 3698b06c9ddSAndreas Gohr $output = $this->git('log', '--no-renames', '--pretty=format:', '--name-only', '--diff-filter=D'); 37036c0b2b4SAndreas Gohr $output = array_map('trim', $output); 37136c0b2b4SAndreas Gohr $output = array_filter($output); 37236c0b2b4SAndreas Gohr $output = array_unique($output); 37336c0b2b4SAndreas Gohr $output = array_filter($output, function ($item) { 37436c0b2b4SAndreas Gohr return !file_exists($item); 37536c0b2b4SAndreas Gohr }); 37636c0b2b4SAndreas Gohr sort($output); 37736c0b2b4SAndreas Gohr 37836c0b2b4SAndreas Gohr if (!count($output)) { 37936c0b2b4SAndreas Gohr $this->info('No deleted files found'); 38036c0b2b4SAndreas Gohr return 0; 38136c0b2b4SAndreas Gohr } 38236c0b2b4SAndreas Gohr 38336c0b2b4SAndreas Gohr $content = "# This is a list of files that were present in previous releases\n" . 38436c0b2b4SAndreas Gohr "# but were removed later. They should not exist in your installation.\n" . 38536c0b2b4SAndreas Gohr join("\n", $output) . "\n"; 38636c0b2b4SAndreas Gohr 38736c0b2b4SAndreas Gohr file_put_contents('deleted.files', $content); 38836c0b2b4SAndreas Gohr $this->success('written deleted.files'); 38936c0b2b4SAndreas Gohr return 0; 39036c0b2b4SAndreas Gohr } 3918b06c9ddSAndreas Gohr 3928b06c9ddSAndreas Gohr /** 393c5c85a97SAndreas Gohr * Remove files that shouldn't be here anymore 3948b06c9ddSAndreas Gohr */ 3951a23d1dbSAndreas Gohr protected function cmdRmObsolete() 3968b06c9ddSAndreas Gohr { 397c5c85a97SAndreas Gohr $this->deleteFile('_test/general.test.php'); 398c5c85a97SAndreas Gohr $this->deleteFile('.travis.yml'); 39953bec4caSAndreas Gohr $this->deleteFile('.github/workflows/phpTestLinux.yml'); 4008b06c9ddSAndreas Gohr 401c5c85a97SAndreas Gohr return 0; 4028b06c9ddSAndreas Gohr } 4038b06c9ddSAndreas Gohr 4041a23d1dbSAndreas Gohr /** 4051a23d1dbSAndreas Gohr * Download a remote icon 4061a23d1dbSAndreas Gohr * 4071a23d1dbSAndreas Gohr * @param string $ident 4081a23d1dbSAndreas Gohr * @param string $save 40992738407SAndreas Gohr * @param bool $keep 4101a23d1dbSAndreas Gohr * @return int 4111a23d1dbSAndreas Gohr * @throws Exception 4121a23d1dbSAndreas Gohr */ 41392738407SAndreas Gohr protected function cmdDownloadSVG($ident, $save = '', $keep = false) 4141a23d1dbSAndreas Gohr { 4151a23d1dbSAndreas Gohr $svg = new SVGIcon($this); 41692738407SAndreas Gohr $svg->keepNamespace($keep); 4171a23d1dbSAndreas Gohr return (int)$svg->downloadRemoteIcon($ident, $save); 4181a23d1dbSAndreas Gohr } 4191a23d1dbSAndreas Gohr 4201a23d1dbSAndreas Gohr /** 4218f82d673SAndreas Gohr * @param string[] $files 42292738407SAndreas Gohr * @param bool $keep 4231a23d1dbSAndreas Gohr * @return int 4241a23d1dbSAndreas Gohr * @throws Exception 4251a23d1dbSAndreas Gohr */ 4268f82d673SAndreas Gohr protected function cmdCleanSVG($files, $keep = false) 4271a23d1dbSAndreas Gohr { 4281a23d1dbSAndreas Gohr $svg = new SVGIcon($this); 42992738407SAndreas Gohr $svg->keepNamespace($keep); 4308f82d673SAndreas Gohr 4318f82d673SAndreas Gohr $ok = true; 4328f82d673SAndreas Gohr foreach ($files as $file) { 4338f82d673SAndreas Gohr $ok = $ok && $svg->cleanSVGFile($file); 4348f82d673SAndreas Gohr } 4358f82d673SAndreas Gohr return (int)$ok; 4361a23d1dbSAndreas Gohr } 4371a23d1dbSAndreas Gohr 4385586e97bSAndreas Gohr /** 4395586e97bSAndreas Gohr * @return int 4405586e97bSAndreas Gohr */ 4415586e97bSAndreas Gohr protected function cmdCleanLang() 4425586e97bSAndreas Gohr { 4435586e97bSAndreas Gohr $lp = new LangProcessor($this); 4445586e97bSAndreas Gohr 4455586e97bSAndreas Gohr $files = glob('./lang/*/lang.php'); 4465b2e8f12SAndreas Gohr foreach ($files as $file) { 4475b2e8f12SAndreas Gohr $lp->processLangFile($file); 4485b2e8f12SAndreas Gohr } 4495b2e8f12SAndreas Gohr 4505b2e8f12SAndreas Gohr $files = glob('./lang/*/settings.php'); 4515586e97bSAndreas Gohr foreach ($files as $file) { 452f4f76afdSAndreas Gohr $lp->processSettingsFile($file); 4535586e97bSAndreas Gohr } 4545586e97bSAndreas Gohr 4555586e97bSAndreas Gohr return 0; 4565586e97bSAndreas Gohr } 4575586e97bSAndreas Gohr 458ec0a687bSAndreas Gohr /** 459*57732a2dSAndreas Gohr * Run the unit tests for this extension 460*57732a2dSAndreas Gohr * 461*57732a2dSAndreas Gohr * @param string $filter Optional filter string for phpunit 462*57732a2dSAndreas Gohr * @param string[] $args Additional arguments to pass to phpunit (files) 463ec0a687bSAndreas Gohr * @return int 464ec0a687bSAndreas Gohr */ 465*57732a2dSAndreas Gohr protected function cmdTest($filter = '', $args = []) 466ec0a687bSAndreas Gohr { 467ec0a687bSAndreas Gohr $dir = fullpath(getcwd()); 468ec0a687bSAndreas Gohr [$base, $type] = $this->getTypedNameFromDir($dir); 469ec0a687bSAndreas Gohr 470ec0a687bSAndreas Gohr if ($this->colors->isEnabled()) { 471ec0a687bSAndreas Gohr $colors = 'always'; 472ec0a687bSAndreas Gohr } else { 473ec0a687bSAndreas Gohr $colors = 'never'; 474ec0a687bSAndreas Gohr } 475ec0a687bSAndreas Gohr 476*57732a2dSAndreas Gohr $bin = fullpath(__DIR__ . '/../../../_test/vendor/bin/phpunit');; 477*57732a2dSAndreas Gohr if (!file_exists($bin)) { 478*57732a2dSAndreas Gohr $this->error('Testing framework not found. Please run "composer install" in the _test/ directory first.'); 479*57732a2dSAndreas Gohr return 1; 480*57732a2dSAndreas Gohr } 481*57732a2dSAndreas Gohr 482*57732a2dSAndreas Gohr $runArgs = [ 483*57732a2dSAndreas Gohr $bin, 484ec0a687bSAndreas Gohr '--verbose', 485ec0a687bSAndreas Gohr "--colors=$colors", 486ec0a687bSAndreas Gohr '--configuration', fullpath(__DIR__ . '/../../../_test/phpunit.xml'), 487ec0a687bSAndreas Gohr '--group', $type . '_' . $base, 488ec0a687bSAndreas Gohr ]; 489*57732a2dSAndreas Gohr if ($filter) { 490*57732a2dSAndreas Gohr $runArgs[] = '--filter'; 491*57732a2dSAndreas Gohr $runArgs[] = $filter; 492*57732a2dSAndreas Gohr } 493*57732a2dSAndreas Gohr 494*57732a2dSAndreas Gohr $runArgs = array_merge($runArgs, $args); 495*57732a2dSAndreas Gohr $cmd = join(' ', array_map('escapeshellarg', $runArgs)); 496ec0a687bSAndreas Gohr $this->info("Running $cmd"); 497ec0a687bSAndreas Gohr 498ec0a687bSAndreas Gohr $result = 0; 499ec0a687bSAndreas Gohr passthru($cmd, $result); 500ec0a687bSAndreas Gohr return $result; 501ec0a687bSAndreas Gohr } 502ec0a687bSAndreas Gohr 503ec0a687bSAndreas Gohr /** 504ec0a687bSAndreas Gohr * @return int 505ec0a687bSAndreas Gohr */ 506ec0a687bSAndreas Gohr protected function cmdCheck($files = []) 507ec0a687bSAndreas Gohr { 508ec0a687bSAndreas Gohr $dir = fullpath(getcwd()); 509ec0a687bSAndreas Gohr 510ec0a687bSAndreas Gohr $args = [ 511ec0a687bSAndreas Gohr fullpath(__DIR__ . '/../../../_test/vendor/bin/phpcs'), 512ec0a687bSAndreas Gohr '--standard=' . fullpath(__DIR__ . '/../../../_test/phpcs.xml'), 513ec0a687bSAndreas Gohr ($this->colors->isEnabled()) ? '--colors' : '--no-colors', 514ec0a687bSAndreas Gohr '--', 515ec0a687bSAndreas Gohr ]; 516ec0a687bSAndreas Gohr 517ec0a687bSAndreas Gohr if ($files) { 518ec0a687bSAndreas Gohr $args = array_merge($args, $files); 519ec0a687bSAndreas Gohr } else { 520ec0a687bSAndreas Gohr $args[] = fullpath($dir); 521ec0a687bSAndreas Gohr } 522ec0a687bSAndreas Gohr 523ec0a687bSAndreas Gohr $cmd = join(' ', array_map('escapeshellarg', $args)); 524ec0a687bSAndreas Gohr $this->info("Running $cmd"); 525ec0a687bSAndreas Gohr 526ec0a687bSAndreas Gohr $result = 0; 527ec0a687bSAndreas Gohr passthru($cmd, $result); 528ec0a687bSAndreas Gohr return $result; 529ec0a687bSAndreas Gohr } 530ec0a687bSAndreas Gohr 531ec0a687bSAndreas Gohr /** 532ec0a687bSAndreas Gohr * @return int 533ec0a687bSAndreas Gohr */ 534ec0a687bSAndreas Gohr protected function cmdFix($files = []) 535ec0a687bSAndreas Gohr { 536ec0a687bSAndreas Gohr $dir = fullpath(getcwd()); 537ec0a687bSAndreas Gohr 538ec0a687bSAndreas Gohr // first run rector to refactor outdated code 539ec0a687bSAndreas Gohr $args = [ 540ec0a687bSAndreas Gohr fullpath(__DIR__ . '/../../../_test/vendor/bin/rector'), 541ec0a687bSAndreas Gohr ($this->colors->isEnabled()) ? '--ansi' : '--no-ansi', 542ec0a687bSAndreas Gohr '--config=' . fullpath(__DIR__ . '/../../../_test/rector.php'), 543ec0a687bSAndreas Gohr '--no-diffs', 544ec0a687bSAndreas Gohr 'process', 545ec0a687bSAndreas Gohr ]; 546ec0a687bSAndreas Gohr 547ec0a687bSAndreas Gohr if ($files) { 548ec0a687bSAndreas Gohr $args = array_merge($args, $files); 549ec0a687bSAndreas Gohr } else { 550ec0a687bSAndreas Gohr $args[] = fullpath($dir); 551ec0a687bSAndreas Gohr } 552ec0a687bSAndreas Gohr 553ec0a687bSAndreas Gohr $cmd = join(' ', array_map('escapeshellarg', $args)); 554ec0a687bSAndreas Gohr $this->info("Running $cmd"); 555ec0a687bSAndreas Gohr 556ec0a687bSAndreas Gohr $result = 0; 557ec0a687bSAndreas Gohr passthru($cmd, $result); 558ec0a687bSAndreas Gohr if ($result !== 0) return $result; 559ec0a687bSAndreas Gohr 560ec0a687bSAndreas Gohr // now run phpcbf to clean up code style 561ec0a687bSAndreas Gohr $args = [ 562ec0a687bSAndreas Gohr fullpath(__DIR__ . '/../../../_test/vendor/bin/phpcbf'), 563ec0a687bSAndreas Gohr '--standard=' . fullpath(__DIR__ . '/../../../_test/phpcs.xml'), 564ec0a687bSAndreas Gohr ($this->colors->isEnabled()) ? '--colors' : '--no-colors', 565ec0a687bSAndreas Gohr '--', 566ec0a687bSAndreas Gohr ]; 567ec0a687bSAndreas Gohr 568ec0a687bSAndreas Gohr if ($files) { 569ec0a687bSAndreas Gohr $args = array_merge($args, $files); 570ec0a687bSAndreas Gohr } else { 571ec0a687bSAndreas Gohr $args[] = fullpath($dir); 572ec0a687bSAndreas Gohr } 573ec0a687bSAndreas Gohr 574ec0a687bSAndreas Gohr $cmd = join(' ', array_map('escapeshellarg', $args)); 575ec0a687bSAndreas Gohr $this->info("Running $cmd"); 576ec0a687bSAndreas Gohr 577ec0a687bSAndreas Gohr $result = 0; 578ec0a687bSAndreas Gohr passthru($cmd, $result); 579ec0a687bSAndreas Gohr return $result; 580ec0a687bSAndreas Gohr } 581ec0a687bSAndreas Gohr 582c5c85a97SAndreas Gohr //endregion 58336c0b2b4SAndreas Gohr} 584