136c0b2b4SAndreas Gohr#!/usr/bin/env php 236c0b2b4SAndreas Gohr<?php 336c0b2b4SAndreas Gohr 436c0b2b4SAndreas Gohruse dokuwiki\Extension\CLIPlugin; 536c0b2b4SAndreas Gohruse dokuwiki\Extension\PluginController; 636c0b2b4SAndreas Gohruse splitbrain\phpcli\Exception as CliException; 736c0b2b4SAndreas Gohruse splitbrain\phpcli\Options; 836c0b2b4SAndreas Gohr 936c0b2b4SAndreas Gohr/** 1036c0b2b4SAndreas Gohr * @license GPL2 1136c0b2b4SAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 1236c0b2b4SAndreas Gohr */ 1336c0b2b4SAndreas Gohrclass cli_plugin_dev extends CLIPlugin 1436c0b2b4SAndreas Gohr{ 1536c0b2b4SAndreas Gohr 1636c0b2b4SAndreas Gohr /** 1736c0b2b4SAndreas Gohr * Register options and arguments on the given $options object 1836c0b2b4SAndreas Gohr * 1936c0b2b4SAndreas Gohr * @param Options $options 2036c0b2b4SAndreas Gohr * @return void 2136c0b2b4SAndreas Gohr */ 2236c0b2b4SAndreas Gohr protected function setup(Options $options) 2336c0b2b4SAndreas Gohr { 2436c0b2b4SAndreas Gohr $options->setHelp( 2536c0b2b4SAndreas Gohr "CLI to help with plugin and template development\n\n" . 2636c0b2b4SAndreas Gohr "Run this script from within the extension's directory." 2736c0b2b4SAndreas Gohr ); 2836c0b2b4SAndreas Gohr 2936c0b2b4SAndreas Gohr $options->registerCommand('init', 'initialize a new plugin or template'); 3036c0b2b4SAndreas Gohr $options->registerCommand('addTest', 'add the testing framework files and optionall a new test file'); 3136c0b2b4SAndreas Gohr $options->registerArgument('test', 'The name of the new test, leave out for general test.', false, 'addTest'); 3236c0b2b4SAndreas Gohr $options->registerCommand('addConf', 'add the configuration files'); 3336c0b2b4SAndreas Gohr $options->registerCommand('addLang', 'add the language files'); 3436c0b2b4SAndreas Gohr 3536c0b2b4SAndreas Gohr $options->registerCommand('addComponent', 'add a component'); 3636c0b2b4SAndreas Gohr $options->registerArgument('type', 'The type of the component. Needs to be one of ' . 3736c0b2b4SAndreas Gohr join(', ', PluginController::PLUGIN_TYPES), 3836c0b2b4SAndreas Gohr true, 'addComponent' 3936c0b2b4SAndreas Gohr ); 4036c0b2b4SAndreas Gohr $options->registerArgument('name', 'Optional name of the component', false, 'addComponent'); 4136c0b2b4SAndreas Gohr 4236c0b2b4SAndreas Gohr $options->registerCommand('deletedFiles', 'create the list of deleted files base on the git history'); 4336c0b2b4SAndreas Gohr } 4436c0b2b4SAndreas Gohr 4536c0b2b4SAndreas Gohr /** @inheritDoc */ 4636c0b2b4SAndreas Gohr protected function main(Options $options) 4736c0b2b4SAndreas Gohr { 4836c0b2b4SAndreas Gohr switch ($options->getCmd()) { 4936c0b2b4SAndreas Gohr case 'init': 5036c0b2b4SAndreas Gohr return $this->cmdInit(); 5136c0b2b4SAndreas Gohr case 'addTest': 5236c0b2b4SAndreas Gohr $args = $options->getArgs(); 5336c0b2b4SAndreas Gohr $test = array_shift($args); 5436c0b2b4SAndreas Gohr return $this->cmdAddTest($test); 5536c0b2b4SAndreas Gohr case 'addConf': 5636c0b2b4SAndreas Gohr return $this->cmdAddConf(); 5736c0b2b4SAndreas Gohr case 'addLang': 5836c0b2b4SAndreas Gohr return $this->cmdAddLang(); 5936c0b2b4SAndreas Gohr case 'addComponent': 6036c0b2b4SAndreas Gohr $args = $options->getArgs(); 6136c0b2b4SAndreas Gohr $type = array_shift($args); 6236c0b2b4SAndreas Gohr $component = array_shift($args); 6336c0b2b4SAndreas Gohr return $this->cmdAddComponent($type, $component); 6436c0b2b4SAndreas Gohr case 'deletedFiles': 6536c0b2b4SAndreas Gohr return $this->cmdDeletedFiles(); 6636c0b2b4SAndreas Gohr default: 6736c0b2b4SAndreas Gohr echo $options->help(); 6836c0b2b4SAndreas Gohr return 0; 6936c0b2b4SAndreas Gohr } 7036c0b2b4SAndreas Gohr } 7136c0b2b4SAndreas Gohr 7236c0b2b4SAndreas Gohr /** 7336c0b2b4SAndreas Gohr * Get the extension name from the current working directory 7436c0b2b4SAndreas Gohr * 7536c0b2b4SAndreas Gohr * @throws CliException if something's wrong 7636c0b2b4SAndreas Gohr * @param string $dir 7736c0b2b4SAndreas Gohr * @return string[] name, type 7836c0b2b4SAndreas Gohr */ 7936c0b2b4SAndreas Gohr protected function getTypedNameFromDir($dir) 8036c0b2b4SAndreas Gohr { 8136c0b2b4SAndreas Gohr $pdir = fullpath(DOKU_PLUGIN); 8236c0b2b4SAndreas Gohr $tdir = fullpath(tpl_incdir() . '../'); 8336c0b2b4SAndreas Gohr 8436c0b2b4SAndreas Gohr if (strpos($dir, $pdir) === 0) { 8536c0b2b4SAndreas Gohr $ldir = substr($dir, strlen($pdir)); 8636c0b2b4SAndreas Gohr $type = 'plugin'; 8736c0b2b4SAndreas Gohr } elseif (strpos($dir, $tdir) === 0) { 8836c0b2b4SAndreas Gohr $ldir = substr($dir, strlen($tdir)); 8936c0b2b4SAndreas Gohr $type = 'template'; 9036c0b2b4SAndreas Gohr } else { 9136c0b2b4SAndreas Gohr throw new CliException('Current directory needs to be in plugin or template directory'); 9236c0b2b4SAndreas Gohr } 9336c0b2b4SAndreas Gohr 9436c0b2b4SAndreas Gohr $ldir = trim($ldir, '/'); 9536c0b2b4SAndreas Gohr 9636c0b2b4SAndreas Gohr if (strpos($ldir, '/') !== false) { 9736c0b2b4SAndreas Gohr throw new CliException('Current directory has to be main extension directory'); 9836c0b2b4SAndreas Gohr } 9936c0b2b4SAndreas Gohr 10036c0b2b4SAndreas Gohr return [$ldir, $type]; 10136c0b2b4SAndreas Gohr } 10236c0b2b4SAndreas Gohr 10336c0b2b4SAndreas Gohr /** 10436c0b2b4SAndreas Gohr * Interactively ask for a value from the user 10536c0b2b4SAndreas Gohr * 10636c0b2b4SAndreas Gohr * @param string $prompt 10736c0b2b4SAndreas Gohr * @param bool $cache cache given value for next time? 10836c0b2b4SAndreas Gohr * @return string 10936c0b2b4SAndreas Gohr */ 11036c0b2b4SAndreas Gohr protected function readLine($prompt, $cache = false) 11136c0b2b4SAndreas Gohr { 11236c0b2b4SAndreas Gohr $value = ''; 11336c0b2b4SAndreas Gohr $default = ''; 11436c0b2b4SAndreas Gohr $cachename = getCacheName($prompt, '.readline'); 11536c0b2b4SAndreas Gohr if ($cache && file_exists($cachename)) { 11636c0b2b4SAndreas Gohr $default = file_get_contents($cachename); 11736c0b2b4SAndreas Gohr } 11836c0b2b4SAndreas Gohr 11936c0b2b4SAndreas Gohr while ($value === '') { 12036c0b2b4SAndreas Gohr echo $prompt; 12136c0b2b4SAndreas Gohr if ($default) echo ' [' . $default . ']'; 12236c0b2b4SAndreas Gohr echo ': '; 12336c0b2b4SAndreas Gohr 12436c0b2b4SAndreas Gohr $fh = fopen('php://stdin', 'r'); 12536c0b2b4SAndreas Gohr $value = trim(fgets($fh)); 12636c0b2b4SAndreas Gohr fclose($fh); 12736c0b2b4SAndreas Gohr 12836c0b2b4SAndreas Gohr if ($value === '') $value = $default; 12936c0b2b4SAndreas Gohr } 13036c0b2b4SAndreas Gohr 13136c0b2b4SAndreas Gohr if ($cache) { 13236c0b2b4SAndreas Gohr file_put_contents($cachename, $value); 13336c0b2b4SAndreas Gohr } 13436c0b2b4SAndreas Gohr 13536c0b2b4SAndreas Gohr return $value; 13636c0b2b4SAndreas Gohr } 13736c0b2b4SAndreas Gohr 13836c0b2b4SAndreas Gohr /** 13936c0b2b4SAndreas Gohr * Download a skeleton file and do the replacements 14036c0b2b4SAndreas Gohr * 14136c0b2b4SAndreas Gohr * @param string $skel Skeleton relative to the skel dir in the repo 14236c0b2b4SAndreas Gohr * @param string $target Target file relative to the main directory 14336c0b2b4SAndreas Gohr * @param array $replacements 14436c0b2b4SAndreas Gohr */ 14536c0b2b4SAndreas Gohr protected function loadSkeleton($skel, $target, $replacements) 14636c0b2b4SAndreas Gohr { 14736c0b2b4SAndreas Gohr if (file_exists($target)) { 14836c0b2b4SAndreas Gohr $this->error($target . ' already exists'); 14936c0b2b4SAndreas Gohr return; 15036c0b2b4SAndreas Gohr } 15136c0b2b4SAndreas Gohr 15236c0b2b4SAndreas Gohr $base = 'https://raw.githubusercontent.com/dokufreaks/dokuwiki-plugin-wizard/master/skel/'; 15336c0b2b4SAndreas Gohr $http = new \dokuwiki\HTTP\DokuHTTPClient(); 15436c0b2b4SAndreas Gohr $content = $http->get($base . $skel); 15536c0b2b4SAndreas Gohr 15636c0b2b4SAndreas Gohr $content = str_replace( 15736c0b2b4SAndreas Gohr array_keys($replacements), 15836c0b2b4SAndreas Gohr array_values($replacements), 15936c0b2b4SAndreas Gohr $content 16036c0b2b4SAndreas Gohr ); 16136c0b2b4SAndreas Gohr 16236c0b2b4SAndreas Gohr io_makeFileDir($target); 16336c0b2b4SAndreas Gohr file_put_contents($target, $content); 16436c0b2b4SAndreas Gohr $this->success('Added ' . $target); 16536c0b2b4SAndreas Gohr } 16636c0b2b4SAndreas Gohr 16736c0b2b4SAndreas Gohr /** 16836c0b2b4SAndreas Gohr * Prepare the string replacements 16936c0b2b4SAndreas Gohr * 17036c0b2b4SAndreas Gohr * @param array $replacements override defaults 17136c0b2b4SAndreas Gohr * @return array 17236c0b2b4SAndreas Gohr */ 17336c0b2b4SAndreas Gohr protected function prepareReplacements($replacements = []) 17436c0b2b4SAndreas Gohr { 17536c0b2b4SAndreas Gohr // defaults 17636c0b2b4SAndreas Gohr $data = [ 17736c0b2b4SAndreas Gohr '@@AUTHOR_NAME@@' => '', 17836c0b2b4SAndreas Gohr '@@AUTHOR_MAIL@@' => '', 17936c0b2b4SAndreas Gohr '@@PLUGIN_NAME@@' => '', 18036c0b2b4SAndreas Gohr '@@PLUGIN_DESC@@' => '', 18136c0b2b4SAndreas Gohr '@@PLUGIN_URL@@' => '', 18236c0b2b4SAndreas Gohr '@@PLUGIN_TYPE@@' => '', 18336c0b2b4SAndreas Gohr '@@INSTALL_DIR@@' => 'plugins', 18436c0b2b4SAndreas Gohr '@@DATE@@' => date('Y-m-d'), 18536c0b2b4SAndreas Gohr ]; 18636c0b2b4SAndreas Gohr 18736c0b2b4SAndreas Gohr // load from existing plugin.info 18836c0b2b4SAndreas Gohr $dir = fullpath(getcwd()); 18936c0b2b4SAndreas Gohr [$name, $type] = $this->getTypedNameFromDir($dir); 19036c0b2b4SAndreas Gohr if (file_exists("$type.info.txt")) { 19136c0b2b4SAndreas Gohr $info = confToHash("$type.info.txt"); 19236c0b2b4SAndreas Gohr $data['@@AUTHOR_NAME@@'] = $info['author']; 19336c0b2b4SAndreas Gohr $data['@@AUTHOR_MAIL@@'] = $info['email']; 19436c0b2b4SAndreas Gohr $data['@@PLUGIN_DESC@@'] = $info['desc']; 19536c0b2b4SAndreas Gohr $data['@@PLUGIN_URL@@'] = $info['url']; 19636c0b2b4SAndreas Gohr } 19736c0b2b4SAndreas Gohr $data['@@PLUGIN_NAME@@'] = $name; 19836c0b2b4SAndreas Gohr $data['@@PLUGIN_TYPE@@'] = $type; 19936c0b2b4SAndreas Gohr 20036c0b2b4SAndreas Gohr if ($type == 'template') { 20136c0b2b4SAndreas Gohr $data['@@INSTALL_DIR@@'] = 'tpl'; 20236c0b2b4SAndreas Gohr } 20336c0b2b4SAndreas Gohr 20436c0b2b4SAndreas Gohr // merge given overrides 20536c0b2b4SAndreas Gohr $data = array_merge($data, $replacements); 20636c0b2b4SAndreas Gohr 20736c0b2b4SAndreas Gohr // set inherited defaults 20836c0b2b4SAndreas Gohr if (empty($data['@@PLUGIN_URL@@'])) { 20936c0b2b4SAndreas Gohr $data['@@PLUGIN_URL@@'] = 21036c0b2b4SAndreas Gohr 'https://www.dokuwiki.org/' . 21136c0b2b4SAndreas Gohr $data['@@PLUGIN_TYPE@@'] . ':' . 21236c0b2b4SAndreas Gohr $data['@@PLUGIN_NAME@@']; 21336c0b2b4SAndreas Gohr } 21436c0b2b4SAndreas Gohr 21536c0b2b4SAndreas Gohr return $data; 21636c0b2b4SAndreas Gohr } 21736c0b2b4SAndreas Gohr 21836c0b2b4SAndreas Gohr /** 21936c0b2b4SAndreas Gohr * Replacements needed for action components. 22036c0b2b4SAndreas Gohr * 22136c0b2b4SAndreas Gohr * Not cool but that' what we need currently 22236c0b2b4SAndreas Gohr * 22336c0b2b4SAndreas Gohr * @return string[] 22436c0b2b4SAndreas Gohr */ 22536c0b2b4SAndreas Gohr protected function actionReplacements() 22636c0b2b4SAndreas Gohr { 22736c0b2b4SAndreas Gohr $fn = 'handleEventName'; 22836c0b2b4SAndreas Gohr $register = ' $controller->register_hook(\'EVENT_NAME\', \'AFTER|BEFORE\', $this, \'' . $fn . '\');'; 22936c0b2b4SAndreas Gohr $handler = ' public function ' . $fn . '(Doku_Event $event, $param)' . "\n" 23036c0b2b4SAndreas Gohr . " {\n" 23136c0b2b4SAndreas Gohr . " }\n"; 23236c0b2b4SAndreas Gohr 23336c0b2b4SAndreas Gohr return [ 23436c0b2b4SAndreas Gohr '@@REGISTER@@' => $register . "\n ", 23536c0b2b4SAndreas Gohr '@@HANDLERS@@' => $handler, 23636c0b2b4SAndreas Gohr ]; 23736c0b2b4SAndreas Gohr } 23836c0b2b4SAndreas Gohr 23936c0b2b4SAndreas Gohr /** 24036c0b2b4SAndreas Gohr * Intialize the current directory as a plugin or template 24136c0b2b4SAndreas Gohr * 24236c0b2b4SAndreas Gohr * @return int 24336c0b2b4SAndreas Gohr */ 24436c0b2b4SAndreas Gohr protected function cmdInit() 24536c0b2b4SAndreas Gohr { 24636c0b2b4SAndreas Gohr $dir = fullpath(getcwd()); 24736c0b2b4SAndreas Gohr if ((new FilesystemIterator($dir))->valid()) { 24836c0b2b4SAndreas Gohr throw new CliException('Current directory needs to be empty'); 24936c0b2b4SAndreas Gohr } 25036c0b2b4SAndreas Gohr 25136c0b2b4SAndreas Gohr [$name, $type] = $this->getTypedNameFromDir($dir); 25236c0b2b4SAndreas Gohr $user = $this->readLine('Your Name', true); 25336c0b2b4SAndreas Gohr $mail = $this->readLine('Your E-Mail', true); 25436c0b2b4SAndreas Gohr $desc = $this->readLine('Short description'); 25536c0b2b4SAndreas Gohr 25636c0b2b4SAndreas Gohr $replacements = [ 25736c0b2b4SAndreas Gohr '@@AUTHOR_NAME@@' => $user, 25836c0b2b4SAndreas Gohr '@@AUTHOR_MAIL@@' => $mail, 25936c0b2b4SAndreas Gohr '@@PLUGIN_NAME@@' => $name, 26036c0b2b4SAndreas Gohr '@@PLUGIN_DESC@@' => $desc, 26136c0b2b4SAndreas Gohr '@@PLUGIN_TYPE@@' => $type, 26236c0b2b4SAndreas Gohr ]; 26336c0b2b4SAndreas Gohr $replacements = $this->prepareReplacements($replacements); 26436c0b2b4SAndreas Gohr 26536c0b2b4SAndreas Gohr $this->loadSkeleton('info.skel', $type . '.info.txt', $replacements); 26636c0b2b4SAndreas Gohr $this->loadSkeleton('README.skel', 'README', $replacements); // fixme needs to be type specific 26736c0b2b4SAndreas Gohr $this->loadSkeleton('LICENSE.skel', 'LICENSE', $replacements); 26836c0b2b4SAndreas Gohr 269*8b06c9ddSAndreas Gohr try { 270*8b06c9ddSAndreas Gohr $this->git('init'); 271*8b06c9ddSAndreas Gohr } catch (CliException $e) { 272*8b06c9ddSAndreas Gohr $this->error($e->getMessage()); 273*8b06c9ddSAndreas Gohr } 274*8b06c9ddSAndreas Gohr 27536c0b2b4SAndreas Gohr return 0; 27636c0b2b4SAndreas Gohr } 27736c0b2b4SAndreas Gohr 27836c0b2b4SAndreas Gohr /** 27936c0b2b4SAndreas Gohr * Add test framework 28036c0b2b4SAndreas Gohr * 28136c0b2b4SAndreas Gohr * @param string $test Name of the Test to add 28236c0b2b4SAndreas Gohr * @return int 28336c0b2b4SAndreas Gohr */ 28436c0b2b4SAndreas Gohr protected function cmdAddTest($test = '') 28536c0b2b4SAndreas Gohr { 28636c0b2b4SAndreas Gohr $test = ucfirst(strtolower($test)); 28736c0b2b4SAndreas Gohr 28836c0b2b4SAndreas Gohr $replacements = $this->prepareReplacements(['@@TEST@@' => $test]); 28936c0b2b4SAndreas Gohr $this->loadSkeleton('.github/workflows/phpTestLinux.skel', '.github/workflows/phpTestLinux.yml', $replacements); 29036c0b2b4SAndreas Gohr if ($test) { 29136c0b2b4SAndreas Gohr $this->loadSkeleton('_test/StandardTest.skel', '_test/' . $test . 'Test.php', $replacements); 29236c0b2b4SAndreas Gohr } else { 29336c0b2b4SAndreas Gohr $this->loadSkeleton('_test/GeneralTest.skel', '_test/GeneralTest.php', $replacements); 29436c0b2b4SAndreas Gohr } 29536c0b2b4SAndreas Gohr 29636c0b2b4SAndreas Gohr return 0; 29736c0b2b4SAndreas Gohr } 29836c0b2b4SAndreas Gohr 29936c0b2b4SAndreas Gohr /** 30036c0b2b4SAndreas Gohr * Add configuration 30136c0b2b4SAndreas Gohr * 30236c0b2b4SAndreas Gohr * @return int 30336c0b2b4SAndreas Gohr */ 30436c0b2b4SAndreas Gohr protected function cmdAddConf() 30536c0b2b4SAndreas Gohr { 30636c0b2b4SAndreas Gohr $replacements = $this->prepareReplacements(); 30736c0b2b4SAndreas Gohr $this->loadSkeleton('conf/default.skel', 'conf/default.php', $replacements); 30836c0b2b4SAndreas Gohr $this->loadSkeleton('conf/metadata.skel', 'conf/metadata.php', $replacements); 30936c0b2b4SAndreas Gohr if (is_dir('lang')) { 31036c0b2b4SAndreas Gohr $this->loadSkeleton('lang/settings.skel', 'lang/en/settings.php', $replacements); 31136c0b2b4SAndreas Gohr } 31236c0b2b4SAndreas Gohr 31336c0b2b4SAndreas Gohr return 0; 31436c0b2b4SAndreas Gohr } 31536c0b2b4SAndreas Gohr 31636c0b2b4SAndreas Gohr /** 31736c0b2b4SAndreas Gohr * Add language 31836c0b2b4SAndreas Gohr * 31936c0b2b4SAndreas Gohr * @return int 32036c0b2b4SAndreas Gohr */ 32136c0b2b4SAndreas Gohr protected function cmdAddLang() 32236c0b2b4SAndreas Gohr { 32336c0b2b4SAndreas Gohr $replacements = $this->prepareReplacements(); 32436c0b2b4SAndreas Gohr $this->loadSkeleton('lang/lang.skel', 'lang/en/lang.php', $replacements); 32536c0b2b4SAndreas Gohr if (is_dir('conf')) { 32636c0b2b4SAndreas Gohr $this->loadSkeleton('lang/settings.skel', 'lang/en/settings.php', $replacements); 32736c0b2b4SAndreas Gohr } 32836c0b2b4SAndreas Gohr 32936c0b2b4SAndreas Gohr return 0; 33036c0b2b4SAndreas Gohr } 33136c0b2b4SAndreas Gohr 33236c0b2b4SAndreas Gohr /** 33336c0b2b4SAndreas Gohr * Add another component to the plugin 33436c0b2b4SAndreas Gohr * 33536c0b2b4SAndreas Gohr * @param string $type 33636c0b2b4SAndreas Gohr * @param string $component 33736c0b2b4SAndreas Gohr */ 33836c0b2b4SAndreas Gohr protected function cmdAddComponent($type, $component = '') 33936c0b2b4SAndreas Gohr { 34036c0b2b4SAndreas Gohr $dir = fullpath(getcwd()); 34136c0b2b4SAndreas Gohr list($plugin, $extension) = $this->getTypedNameFromDir($dir); 34236c0b2b4SAndreas Gohr if ($extension != 'plugin') throw new CliException('Components can only be added to plugins'); 34336c0b2b4SAndreas Gohr if (!in_array($type, PluginController::PLUGIN_TYPES)) { 34436c0b2b4SAndreas Gohr throw new CliException('Invalid type ' . $type); 34536c0b2b4SAndreas Gohr } 34636c0b2b4SAndreas Gohr 34736c0b2b4SAndreas Gohr if ($component) { 34836c0b2b4SAndreas Gohr $path = $type . '/' . $component . '.php'; 34936c0b2b4SAndreas Gohr $class = $type . '_plugin_' . $plugin . '_' . $component; 35036c0b2b4SAndreas Gohr $self = $plugin . '_' . $component; 35136c0b2b4SAndreas Gohr } else { 35236c0b2b4SAndreas Gohr $path = $type . '.php'; 35336c0b2b4SAndreas Gohr $class = $type . '_plugin_' . $plugin; 35436c0b2b4SAndreas Gohr $self = $plugin; 35536c0b2b4SAndreas Gohr } 35636c0b2b4SAndreas Gohr 35736c0b2b4SAndreas Gohr $replacements = $this->actionReplacements(); 35836c0b2b4SAndreas Gohr $replacements['@@PLUGIN_COMPONENT_NAME@@'] = $class; 35936c0b2b4SAndreas Gohr $replacements['@@SYNTAX_COMPONENT_NAME@@'] = $self; 36036c0b2b4SAndreas Gohr $replacements = $this->prepareReplacements($replacements); 36136c0b2b4SAndreas Gohr $this->loadSkeleton($type . '.skel', $path, $replacements); 36236c0b2b4SAndreas Gohr 36336c0b2b4SAndreas Gohr return 0; 36436c0b2b4SAndreas Gohr } 36536c0b2b4SAndreas Gohr 36636c0b2b4SAndreas Gohr /** 36736c0b2b4SAndreas Gohr * Generate a list of deleted files from git 36836c0b2b4SAndreas Gohr * 36936c0b2b4SAndreas Gohr * @link https://stackoverflow.com/a/6018049/172068 37036c0b2b4SAndreas Gohr */ 37136c0b2b4SAndreas Gohr protected function cmdDeletedFiles() 37236c0b2b4SAndreas Gohr { 373*8b06c9ddSAndreas Gohr if(!is_dir('.git')) throw new CliException('This extension seems not to be managed by git'); 37436c0b2b4SAndreas Gohr 375*8b06c9ddSAndreas Gohr $output = $this->git('log', '--no-renames', '--pretty=format:', '--name-only', '--diff-filter=D'); 37636c0b2b4SAndreas Gohr $output = array_map('trim', $output); 37736c0b2b4SAndreas Gohr $output = array_filter($output); 37836c0b2b4SAndreas Gohr $output = array_unique($output); 37936c0b2b4SAndreas Gohr $output = array_filter($output, function ($item) { 38036c0b2b4SAndreas Gohr return !file_exists($item); 38136c0b2b4SAndreas Gohr }); 38236c0b2b4SAndreas Gohr sort($output); 38336c0b2b4SAndreas Gohr 38436c0b2b4SAndreas Gohr if (!count($output)) { 38536c0b2b4SAndreas Gohr $this->info('No deleted files found'); 38636c0b2b4SAndreas Gohr return 0; 38736c0b2b4SAndreas Gohr } 38836c0b2b4SAndreas Gohr 38936c0b2b4SAndreas Gohr $content = "# This is a list of files that were present in previous releases\n" . 39036c0b2b4SAndreas Gohr "# but were removed later. They should not exist in your installation.\n" . 39136c0b2b4SAndreas Gohr join("\n", $output) . "\n"; 39236c0b2b4SAndreas Gohr 39336c0b2b4SAndreas Gohr file_put_contents('deleted.files', $content); 39436c0b2b4SAndreas Gohr $this->success('written deleted.files'); 39536c0b2b4SAndreas Gohr return 0; 39636c0b2b4SAndreas Gohr } 397*8b06c9ddSAndreas Gohr 398*8b06c9ddSAndreas Gohr /** 399*8b06c9ddSAndreas Gohr * Run git with the given arguments and return the output 400*8b06c9ddSAndreas Gohr * 401*8b06c9ddSAndreas Gohr * @throws CliException when the command can't be run 402*8b06c9ddSAndreas Gohr * @param string ...$args 403*8b06c9ddSAndreas Gohr * @return string[] 404*8b06c9ddSAndreas Gohr */ 405*8b06c9ddSAndreas Gohr protected function git(...$args) 406*8b06c9ddSAndreas Gohr { 407*8b06c9ddSAndreas Gohr $args = array_map('escapeshellarg', $args); 408*8b06c9ddSAndreas Gohr $cmd = 'git ' . join(' ', $args); 409*8b06c9ddSAndreas Gohr $output = []; 410*8b06c9ddSAndreas Gohr $result = 0; 411*8b06c9ddSAndreas Gohr 412*8b06c9ddSAndreas Gohr $this->info($cmd); 413*8b06c9ddSAndreas Gohr $last = exec($cmd, $output, $result); 414*8b06c9ddSAndreas Gohr if ($last === false || $result !== 0) { 415*8b06c9ddSAndreas Gohr throw new CliException('Running git failed'); 416*8b06c9ddSAndreas Gohr } 417*8b06c9ddSAndreas Gohr 418*8b06c9ddSAndreas Gohr return $output; 419*8b06c9ddSAndreas Gohr } 42036c0b2b4SAndreas Gohr} 421