diff --git a/README.md b/README.md index 2904a47..55c1575 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ 2.0 Work in progress, unstable and not yet ready for use. -- [ ] Update composer for symfony dependencies +- [x] Update composer for symfony dependencies - [ ] Add pake and phar generator - [ ] Update bin with new generated phar -- [ ] Convert to new command structure +- [x] Convert to new command structure - [ ] Update help files ## Description diff --git a/composer.json b/composer.json index 4557914..83b2e76 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,10 @@ { "name": "there4/markdown-resume", - "description": "Generate a responsive CSS3 and HTML5 resume with Markdown, with optional PDF output.", + "description": "Markdown Resume Generator", + "homepage": "https://github.com/there4/markdown-resume", + "keywords": ["markdown", "resume", "html5"], "license": "MIT", + "version": "2.0.0", "authors": [ { "name": "Craig Davis", @@ -23,6 +26,9 @@ "role": "Contributor" } ], + "support": { + "issues": "https://github.com/there4/markdown-resume/issues" + }, "minimum-stability": "dev", "require": { }, @@ -31,6 +37,10 @@ "symfony/config": "v2.3.4", "symfony/yaml": "v2.3.4", "leafo/lessphp": "v0.4.0", - "michelf/php-markdown": "1.4.0" + "michelf/php-markdown": "1.4.0", + "twig/twig": "v1.13.2", + "mustache/mustache": "2.5.1", + "michelf/php-smartypants": "1.6.0-beta1", + "simple-html-dom/simple-html-dom": "1.5.0" } } diff --git a/composer.lock b/composer.lock index 7e3827d..e28b552 100644 --- a/composer.lock +++ b/composer.lock @@ -3,9 +3,137 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "54ae642f6e4dd0e18885aed349b99457", + "hash": "7f8d3ab6c722a1dfa180e92c876ffc63", "packages": [ - + { + "name": "michelf/php-smartypants", + "version": "1.6.0-beta1", + "source": { + "type": "git", + "url": "https://github.com/michelf/php-smartypants.git", + "reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/michelf/php-smartypants/zipball/c0465c6d4c5ab853c2fa45df6c10bce7e35cc137", + "reference": "c0465c6d4c5ab853c2fa45df6c10bce7e35cc137", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-lib": "1.6.x-dev" + } + }, + "autoload": { + "psr-0": { + "Michelf": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Michel Fortin", + "email": "michel.fortin@michelf.ca", + "homepage": "http://michelf.ca/", + "role": "Developer" + }, + { + "name": "John Gruber", + "homepage": "http://daringfireball.net/" + } + ], + "description": "PHP SmartyPants", + "homepage": "http://michelf.ca/projects/php-smartypants/", + "keywords": [ + "dashes", + "quotes", + "spaces", + "typographer", + "typography" + ], + "time": "2013-07-31 18:13:10" + }, + { + "name": "mustache/mustache", + "version": "v2.5.1", + "source": { + "type": "git", + "url": "https://github.com/bobthecow/mustache.php.git", + "reference": "996c944fa2ddedddfaf0d276b913809d6a32fd85" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bobthecow/mustache.php/zipball/996c944fa2ddedddfaf0d276b913809d6a32fd85", + "reference": "996c944fa2ddedddfaf0d276b913809d6a32fd85", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Mustache": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Justin Hileman", + "email": "justin@justinhileman.info", + "homepage": "http://justinhileman.com" + } + ], + "description": "A Mustache implementation in PHP.", + "homepage": "https://github.com/bobthecow/mustache.php", + "keywords": [ + "mustache", + "templating" + ], + "time": "2014-01-09 00:36:09" + }, + { + "name": "simple-html-dom/simple-html-dom", + "version": "1.5.0", + "source": { + "type": "git", + "url": "https://github.com/Youpie/simple-html-dom.git", + "reference": "961610576c460546677a635062e9d3d7b6dab745" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Youpie/simple-html-dom/zipball/961610576c460546677a635062e9d3d7b6dab745", + "reference": "961610576c460546677a635062e9d3d7b6dab745", + "shasum": "" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "S.C. Chen", + "email": "me578022@gmail.com", + "homepage": "http://simplehtmldom.sourceforge.net/" + } + ], + "description": "A copy of the PHP Simple HTML DOM Parser project.", + "time": "2013-05-14 22:27:35" + } ], "packages-dev": [ { @@ -294,15 +422,64 @@ "description": "Symfony Yaml Component", "homepage": "http://symfony.com", "time": "2013-08-24 15:26:22" + }, + { + "name": "twig/twig", + "version": "v1.13.2", + "source": { + "type": "git", + "url": "https://github.com/fabpot/Twig.git", + "reference": "6d6a1009427d1f398c9d40904147bf9f723d5755" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fabpot/Twig/zipball/6d6a1009427d1f398c9d40904147bf9f723d5755", + "reference": "6d6a1009427d1f398c9d40904147bf9f723d5755", + "shasum": "" + }, + "require": { + "php": ">=5.2.4" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.13-dev" + } + }, + "autoload": { + "psr-0": { + "Twig_": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "http://twig.sensiolabs.org", + "keywords": [ + "templating" + ], + "time": "2013-08-03 15:35:31" } ], "aliases": [ ], "minimum-stability": "dev", - "stability-flags": [ - - ], + "stability-flags": { + "michelf/php-smartypants": 10 + }, "platform": [ ], diff --git a/pakefile b/pakefile index bfa0bad..4885fe4 100644 --- a/pakefile +++ b/pakefile @@ -45,8 +45,8 @@ function run_version() { } function run_version_file() { - $composer = json_decode(file_get_contents('composer.json')); - file_put_contents('./version', $composer->version); + $version = trim(shell_exec('git describe --abbrev=0 --tags')); + file_put_contents('./version', $version); } function run_lint() { diff --git a/bin/resume2.php b/resume2.php similarity index 64% rename from bin/resume2.php rename to resume2.php index 2310937..bf2f510 100755 --- a/bin/resume2.php +++ b/resume2.php @@ -6,29 +6,26 @@ if (!file_exists(__DIR__ . '/vendor/autoload.php')) { exit("\nPlease run `composer install` to install dependencies.\n\n"); } -// Bootstrap our Silex application with the Composer autoloader +// Bootstrap our application with the Composer autoloader $app = require __DIR__ . '/vendor/autoload.php'; // Setup the namespace for our own namespace -$app->add('FogBugz', __DIR__ . '/src'); +$app->add('Resume', __DIR__ . '/src'); // Instantiate our Console application -$console = new FogBugz\Cli\Working(); +$console = new Resume\Cli\Resume(); // If we're running from phar, we get these values from the stub if (!defined("IN_PHAR")) { $project = json_decode(file_get_contents(__DIR__ . '/composer.json')); } -// Config path can be set with a an ENV var -$configFile = getenv("FOGBUGZ_CONFIG") ? getenv("FOGBUGZ_CONFIG") : getenv("HOME") . "/.fogbugz.yml"; - $templatePath = __DIR__ . '/templates'; // Init the app with these params -$console->initialize($configFile, $templatePath, $project); +$console->initialize($templatePath, $project); // Execute the console app. $console->run(); -/* End of working.php */ +/* End of resume.php */ diff --git a/src/Resume/Cli/Resume.php b/src/Resume/Cli/Resume.php index d1b4fdd..29aee6f 100644 --- a/src/Resume/Cli/Resume.php +++ b/src/Resume/Cli/Resume.php @@ -1,5 +1,5 @@ configFile = $configFile; // Add the composer information for use in version info and such. $this->project = $project; - // Load our application config information - if (file_exists($configFile)) { - $this->config = Yaml::parse($configFile); - } else { - $runSetup = true; - $this->config = $this->getDefaultConfig(); - } - // https://github.com/symfony/Console/blob/master/Output/Output.php - $this->outputFormat - = $this->config['UseColor'] - ? OutputInterface::OUTPUT_NORMAL - : OutputInterface::OUTPUT_PLAIN; + // the alternative is OutputInterface::OUTPUT_PLAIN; + $this->outputFormat = OutputInterface::OUTPUT_NORMAL; // We do this now because we've loaded the project info from the composer file $this->setName($this->project->description); $this->setVersion($this->project->version); // Load our commands into the application - $this->add(new Command\AssignCommand()); - $this->add(new Command\CasesCommand()); - $this->add(new Command\CloseCommand()); - $this->add(new Command\CurrentCommand()); - $this->add(new Command\EstimateCommand()); - $this->add(new Command\FiltersCommand()); - $this->add(new Command\LoginCommand()); - $this->add(new Command\LogoutCommand()); - $this->add(new Command\NoteCommand()); - $this->add(new Command\OpenCommand()); - $this->add(new Command\ParentCommand()); - $this->add(new Command\ReactivateCommand()); - $this->add(new Command\RecentCommand()); - $this->add(new Command\ReopenCommand()); - $this->add(new Command\ResolveCommand()); - $this->add(new Command\SearchCommand()); $this->add(new Command\SelfUpdateCommand()); - $this->add(new Command\SetFilterCommand()); - $this->add(new Command\SetupCommand()); - $this->add(new Command\StartCommand()); - $this->add(new Command\StarCommand()); - $this->add(new Command\StopCommand()); - $this->add(new Command\UnstarCommand()); $this->add(new Command\VersionCommand()); - $this->add(new Command\ViewCommand()); // We'll use [Twig](http://twig.sensiolabs.org/) for template output $loader = new \Twig_Loader_Filesystem($templatePath); @@ -89,26 +51,6 @@ class Working extends Application $this->twig->addFilter('style', new \Twig_Filter_Function("FogBugz\Cli\TwigFormatters::style")); $this->twig->addFilter('repeat', new \Twig_Filter_Function("str_repeat")); $this->twig->addFilter('wrap', new \Twig_Filter_Function("wordwrap")); - - // If the config file is empty, run the setup script here - // If the config file version is a different major number, run the setup script here - $currentVersion = explode('.', $this->project->version); - $configVersion = explode('.', $this->config['ConfigVersion']); - $majorVersionChange = $currentVersion[0] != $configVersion[0]; - // We need to be able to skip setup for the list and help - $helpRequested = ( - empty($_SERVER['argv'][1]) || - ($_SERVER['argv'][1] == 'list') || - ($_SERVER['argv'][1] == 'help') - ); - if (($runSetup || $majorVersionChange) && !$helpRequested) { - $command = $this->find('setup'); - $arguments = array( - 'command' => 'setup' - ); - $input = new ArrayInput($arguments); - $command->run($input, new ConsoleOutput()); - } } public function getLongVersion() @@ -116,61 +58,6 @@ class Working extends Application return parent::getLongVersion().' by Craig Davis'; } - public function getDefaultConfig() - { - return array( - 'ConfigVersion' => '0.0.1', - 'UseColor' => true, - 'Host' => '', - 'User' => '', - 'AuthToken' => '', - 'RecentCases' => array() - ); - } - - public function getCurrent($user = '') - { - if ($user === '') { - $user = $this->fogbugz->user; - } - $xml = $this->fogbugz->viewPerson(array('sEmail' => $user)); - - return (int) $xml->people->person->ixBugWorkingOn; - } - - public function getRecent() - { - return - is_array($this->config['RecentCases']) - ? $this->config['RecentCases'] - : array(); - } - - public function pushRecent($case, $title) - { - $recentCases = $this->getRecent(); - array_push( - $recentCases, - array( - "id" => $case, - "title" => $title - ) - ); - // Only keep the last x number of cases in the list - $this->config['RecentCases'] = array_slice($recentCases, -1 * $this->recentCaseLimit); - $this->saveConfig(); - - return true; - } - - public function saveConfig() - { - // the second param is the depth for starting yaml inline formatting - $yaml = Yaml::dump($this->config, 2); - - return file_put_contents($this->configFile, $yaml); - } - public function registerStyles(&$output) { // https://github.com/symfony/Console/blob/master/Formatter/OutputFormatterStyle.php @@ -241,23 +128,10 @@ class Working extends Application } catch (\Exception $e) { exit($e->getMessage() . "\n"); } - - // Does the command require authentication? - if (property_exists($command, "requireAuth") && $command->requireAuth) { - $simple_input = new ArgvInput( - array( - $_SERVER['argv'][0], - $_SERVER['argv'][1], - "--quiet" - ) - ); - $login = $this->find('login'); - $returnCode = $login->run($simple_input, $output); - } } return parent::run($input, $output); } } -/* End of file Working.php */ +/* End of file Resume.php */ diff --git a/src/Resume/Cli/TwigFormatters.php b/src/Resume/Cli/TwigFormatters.php new file mode 100644 index 0000000..0a4189a --- /dev/null +++ b/src/Resume/Cli/TwigFormatters.php @@ -0,0 +1,37 @@ +this is a long title + $total_length = strlen($string); + $stripped_length = strlen(strip_tags($string)); + + $length = $length + $total_length - $stripped_length; + + return str_pad(substr($string, 0, $length), $length, " ", $padding); + } + + public static function style($string, $format) + { + return sprintf('<%2$s>%1$s', $string, $format); + } +} + +/* End of file TwigFormatters */ diff --git a/src/Resume/Command/HtmlCommand.php b/src/Resume/Command/HtmlCommand.php new file mode 100644 index 0000000..93d6f78 --- /dev/null +++ b/src/Resume/Command/HtmlCommand.php @@ -0,0 +1,22 @@ +setName('html') + ->setDescription('Generate an HTML resume from a markdown file'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + } +} + +/* End of file HtmlCommand.php */ diff --git a/src/Resume/Command/PdfCommand.php b/src/Resume/Command/PdfCommand.php new file mode 100644 index 0000000..a40d5d6 --- /dev/null +++ b/src/Resume/Command/PdfCommand.php @@ -0,0 +1,22 @@ +setName('pdf') + ->setDescription('Generate a PDF from a markdown file'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + } +} + +/* End of file PdfCommand.php */ diff --git a/src/Resume/Command/SelfUpdateCommand.php b/src/Resume/Command/SelfUpdateCommand.php new file mode 100644 index 0000000..966dd0b --- /dev/null +++ b/src/Resume/Command/SelfUpdateCommand.php @@ -0,0 +1,87 @@ +setName('selfupdate') + ->setDescription('Updates fb.phar to the latest version.') + ->setHelp( +<<self-update command checks github for newer +versions of the command line client and if found, installs the latest. + +EOT + ); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->app = $this->getApplication(); + $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0]; + $tempFilename = dirname($localFilename) . '/' . basename($localFilename, '.phar').'-temp.phar'; + + if (substr($localFilename, -4) === '.php') { + throw new \Exception('You must run this from the compiled phar file.'); + } + + // check for permissions in local filesystem before start connection process + if (!is_writable($tempDirectory = dirname($tempFilename))) { + throw new \Exception( + 'Self update failed: the "' . $tempDirectory + . '" directory used to download the temp file could not be written' + ); + } + + if (!is_writable($localFilename)) { + throw new \Exception( + 'Self update failed: the "' . $localFilename . '" file could not be written' + ); + } + + $protocol = extension_loaded('openssl') ? 'https' : 'http'; + $latest = trim(file_get_contents($protocol . $this->app->project->selfupdateversion, false)); + + if ($this->app->project->version !== $latest) { + $output->writeln(sprintf("Updating to version %s.", $latest)); + + $remoteFilename = $protocol . $this->app->project->selfupdatepath; + + $phar = file_get_contents($remoteFilename); + file_put_contents($tempFilename, $phar); + + if (!file_exists($tempFilename)) { + $output->writeln('The download of the new version failed for an unexpected reason'); + + return 1; + } + + try { + @chmod($tempFilename, 0777 & ~umask()); + // test the phar validity + $phar = new \Phar($tempFilename); + // free the variable to unlock the file + unset($phar); + rename($tempFilename, $localFilename); + } catch (\Exception $e) { + @unlink($tempFilename); + if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) { + throw $e; + } + $output->writeln('The download is corrupted ('.$e->getMessage().').'); + $output->writeln('Please re-run the self-update command to try again.'); + } + } else { + $output->writeln("You are using the latest version."); + } + } +} + +/* End of file SelfUpdateCommand.php */ diff --git a/src/Resume/Command/VersionCommand.php b/src/Resume/Command/VersionCommand.php index 71654f0..ac40dce 100644 --- a/src/Resume/Command/VersionCommand.php +++ b/src/Resume/Command/VersionCommand.php @@ -1,24 +1,17 @@ setName('version') - ->setDescription('Show version information') - ->requireAuth(false); + ->setDescription('Show current version information'); } protected function execute(InputInterface $input, OutputInterface $output) diff --git a/version b/version index 3a1f10e..2320ce7 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.2.5 \ No newline at end of file +2.0.0-wip