diff --git a/.gitignore b/.gitignore index 9cd314a..f7b8cb7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ /autoload.php /Pyrus_Developer-*.* *.komodoproject +tests/*package-test* +vendor* diff --git a/src/Pyrus/Developer/PackageFile/Commands.php b/src/Pyrus/Developer/PackageFile/Commands.php index ea33fbf..92c7907 100644 --- a/src/Pyrus/Developer/PackageFile/Commands.php +++ b/src/Pyrus/Developer/PackageFile/Commands.php @@ -432,175 +432,56 @@ function runTests($frontend, $args, $options) } } - function pear2Skeleton($frontend, $args, $options) + /** + * Create the PEAR2 skeleton + * + * @param mixed $frontend \Pyrus\ScriptFrontend\Commands + * @param array $args + * @param array $options + * + * @return void + * + * @uses Pyrus\Developer\PackageFile\Commands\PEAR2Skeleton + * @uses self::makePackageXml() + */ + public function pear2Skeleton($frontend, array $args, array $options) { if (!isset($args['channel'])) { $args['channel'] = 'pear2.php.net'; } - $info = $this->parsePackageName($args['package'], $args['channel']); - - if (file_exists($info['path'])) { - throw new \Pyrus\Developer\Creator\Exception('Path ' . $info['path'] . - ' already exists'); - } - mkdir($info['path']); - chdir($info['path']); - - mkdir('src'); - mkdir('src/' . $info['mainPath'], 0777, true); - file_put_contents('src/' . $info['mainPath'] . '/Main.php', ' - * @copyright ' . date('Y') . ' Your Name - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @version SVN: $Id$ - * @link ' . $info['svn'] . ' - */ - -/** - * Main class for ' . $info['package'] . ' - * - * @category Yourcategory - * @package ' . $info['package'] . ' - * @author Your Name - * @copyright ' . date('Y') . ' Your Name - * @license http://www.opensource.org/licenses/bsd-license.php New BSD License - * @link ' . $info['svn'] . ' - */ -namespace ' . $info['mainNamespace'] . '; -class Main -{ -} -'); - mkdir('data'); -// mkdir('customcommand'); -// mkdir('customrole'); -// mkdir('customtask'); - mkdir('tests'); - mkdir('docs'); - mkdir('examples'); - mkdir('www'); - file_put_contents('README', 'Package ' . $info['package'] . " summary.\n" . - "\n" . - "Package detailed description here (found in README)"); - file_put_contents('CREDITS', ";; put your info here\n" . - 'Your Name [handle] (lead)'); - file_put_contents('RELEASE-0.1.0', 'Package ' . $info['package'] . " release notes for version 0.1.0."); - file_put_contents('API-0.1.0', 'Package ' . $info['package'] . " API release notes for version 0.1.0."); - file_put_contents('extrasetup.php', "dependencies['required']->package['pear2.php.net/PEAR2_Autoload']->save(); -\$package->dependencies['required']->package['pear2.php.net/PEAR2_Exception']->save(); -\$package->dependencies['required']->package['pear2.php.net/PEAR2_MultiErrors']->save(); -\$package->dependencies['required']->package['pear2.php.net/PEAR2_HTTP_Request']->save(); - -\$compatible->dependencies['required']->package['pear2.php.net/PEAR2_Autoload']->save(); -\$compatible->dependencies['required']->package['pear2.php.net/PEAR2_Exception']->save(); -\$compatible->dependencies['required']->package['pear2.php.net/PEAR2_MultiErrors']->save(); -\$compatible->dependencies['required']->package['pear2.php.net/PEAR2_HTTP_Request']->save(); - -// ignore files -unset(\$package->files['www/config.inc.php']); -unset(\$package->files['www/.htaccess']); -*/ -?> -"); - file_put_contents('stub.php', "#!/usr/bin/env php -getMessage(), \"\n\"; - exit -1; -} -function " . $info['package'] . "_autoload(\$class) -{ - \$class = str_replace(array('_', '\\\'), '/', \$class); - if (file_exists('phar://' . __FILE__ . '/" . $info['package'] . "-@PACKAGE_VERSION@/php/' . \$class . '.php')) { - include 'phar://' . __FILE__ . '/" . $info['package'] . "-@PACKAGE_VERSION@/php/' . \$class . '.php'; - } -} -spl_autoload_register(\"" . $info['package'] . "_autoload\"); -\$phar = new Phar(__FILE__); -\$sig = \$phar->getSignature(); -define('" . $info['package'] . "_SIG', \$sig['hash']); -define('" . $info['package'] . "_SIGTYPE', \$sig['hash_type']); - -// your package-specific stuff here, for instance, here is what Pyrus does: - -/** - * \$frontend = new \Pyrus\ScriptFrontend\Commands; - * @array_shift(\$_SERVER['argv']); - * \$frontend->run(\$_SERVER['argv']); - */ -__HALT_COMPILER(); -"); + $info = $this->parsePackageName($args['package'], $args['channel']); - $options['stub'] = 'stub.php'; - $options['extrasetup'] = 'extrasetup.php'; - $options['packagexmlsetup'] = 'packagexmlsetup.php'; + $skeleton = new Commands\PEAR2Skeleton($info); + $skeleton->generate(); + + $options['stub'] = $skeleton->getStub(); + $options['extrasetup'] = $skeleton->getExtraSetup(); + $options['packagexmlsetup'] = $skeleton->getPackageXmlSetup(); $options['package'] = false; $options['nocompatible'] = false; - $this->makePackageXml($frontend, array('packagename' => $info['package'], 'channel' => $args['channel']), - $options); + + $this->makePackageXml( + $frontend, + array('packagename' => $info['package'], 'channel' => $args['channel']), + $options + ); } + /** + * Returns an array with: + * - path + * - mainNamespace + * - mainClass + * - mainPath + * - svn + * + * @param string $package E.g. PEAR2_Foo_Bar + * @param string $channel E.g. pear2.php.net + * + * @return array + * @see \Pyrus\Developer\PackageFile\Commands\PEAR2Skeleton + */ protected function parsePackageName($package, $channel) { $ret = array(); diff --git a/src/Pyrus/Developer/PackageFile/Commands/PEAR2Skeleton.php b/src/Pyrus/Developer/PackageFile/Commands/PEAR2Skeleton.php new file mode 100644 index 0000000..3abd034 --- /dev/null +++ b/src/Pyrus/Developer/PackageFile/Commands/PEAR2Skeleton.php @@ -0,0 +1,228 @@ + 'Package __PACKAGE__ summary.\n\n" . "Package detailed description here (found in README)', + 'CREDITS' => ";; put your info here\nYour Name [handle] (lead)", + 'RELEASE-0.1.0' => 'Package __PACKAGE__ release notes for version 0.1.0.', + 'API-0.1.0' => 'Package __PACKAGE__ API release notes for version 0.1.0.', + ); + + /** + * @var string $templatePath Path to templates for the above. + * @see self::__construct() + * @see self::generate() + * @see self::$extraSetupFile + * @see self::$packageXmlSetupFile + * @see self::$stubFile + */ + protected $templatePath; + + /** + * __construct + * + * @param array $info + * @param string $format + * + * @return $this + * @throws \Pyrus\Developer\Creator\Exception When the path of the package does + * not exist. + */ + public function __construct(array $info, $format = 'simple') + { + if (file_exists($info['path'])) { + throw new \Pyrus\Developer\Creator\Exception( + 'Path ' . $info['path'] . ' already exists' + ); + } + + if ($this->isInfoValid($info) === false) { + throw new \Pyrus\Developer\Creator\Exception( + "Info is missing a required key." + ); + } + + $this->info = $info; + + $this->templatePath = __DIR__ . '/templates'; + } + + /** + * Start creating. + * + * @return void + */ + public function generate() + { + // creates the base package directory + mkdir($this->info['path']); + chdir($this->info['path']); + + $this->createMainClass(); + + $this->createDirectories(); + $this->createReleaseFiles($this->info['package']); + + $extraSetup = file_get_contents($this->templatePath . '/extrasetup.php.tpl'); + file_put_contents($this->getExtraSetup(), $extraSetup); + + $packageXmlSetup = file_get_contents($this->templatePath . '/packagexmlsetup.php.tpl'); + file_put_contents($this->getPackageXmlSetup(), $packageXmlSetup); + + $this->createStub(); + } + + /** + * @return string + */ + public function getExtraSetup() + { + return $this->extraSetupFile; + } + + /** + * @return string + */ + public function getPackageXmlSetup() + { + return $this->packageXmlSetupFile; + } + + /** + * @return array + */ + public function getReleaseFiles() + { + return $this->releaseFiles; + } + + /** + * @return string + */ + public function getStub() + { + return $this->stubFile; + } + + /** + * Create repo/src/NameSpace/Main.php + * + * @return void + * @uses self::$info + */ + protected function createMainClass() + { + $mainClass = file($this->templatePath . '/Main.php.tpl'); + $mainClass = str_replace('__MAIN_CLASS__', $this->info['mainClass'], $mainClass); + $mainClass = str_replace('__PACKAGE__', $this->info['package'], $mainClass); + $mainClass = str_replace('__YEAR__', date('Y'), $mainClass); + $mainClass = str_replace('__VCS__', $this->info['svn'], $mainClass); + $mainClass = str_replace('__MAIN_NAMESPACE__', $this->info['mainNamespace'], $mainClass); + + mkdir('src/' . $this->info['mainPath'], 0777, true); + + file_put_contents('src/' . $this->info['mainPath'] . '/Main.php', $mainClass); + } + + protected function createDirectories() + { + $dirs = array('data', 'tests', 'docs', 'example', 'www' + // 'customcommand', 'customrole', 'customtask' + ); + foreach ($dirs as $dir) { + mkdir($dir); + } + } + + /** + * A small wrapper to create all the files necessary to create a package. + * + * @param string $packageName The name of the package. + * + * @return void + * @throws \Pyrus\Developer\Creator\Exception On write/permission problems. + * @uses self::$releaseFiles + */ + protected function createReleaseFiles($packageName) + { + foreach ($this->releaseFiles as $fileName => $fileContent) { + $fileContent = str_replace('__PACKAGE__', $packageName, $fileContent); + $status = @file_put_contents($fileName, $fileContent); + if ($status === false) { + throw new \Pyrus\Developer\Creator\Exception( + "Could not create {$fileName} for {$packageName}" + ); + } + } + } + + /** + * Create the stub.php file from the template. + * + * @return void + * @uses self::getStub() + */ + protected function createStub() + { + $stub = file_get_contents($this->templatePath . '/stub.php.tpl'); + $stub = str_replace('__PACKAGE__', $this->info['package'], $stub); + file_put_contents($this->getStub(), $stub); + } + + /** + * Validate the info passed into {@link self::__construct()}. + * + * @return boolean + * + * @uses self::$info + * @see self::__construct() + */ + protected function isInfoValid($info) + { + if (!isset($info['mainClass']) || empty($info['mainClass'])) { + return false; + } + if (!isset($info['package']) || empty($info['package'])) { + return false; + } + if (!isset($info['svn'])) { + return false; + } + if (!isset($info['mainPath'])) { + return false; + } + if (!isset($info['mainNamespace']) || empty($info['mainNamespace'])) { + return false; + } + return true; + } +} diff --git a/src/Pyrus/Developer/PackageFile/Commands/templates/Main.php.tpl b/src/Pyrus/Developer/PackageFile/Commands/templates/Main.php.tpl new file mode 100644 index 0000000..13fae16 --- /dev/null +++ b/src/Pyrus/Developer/PackageFile/Commands/templates/Main.php.tpl @@ -0,0 +1,29 @@ + + * @copyright __YEAR__ Your Name + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @version SVN: $Id$ + * @link __VCS__ + */ + +/** + * Main class for __PACKAGE__ + * + * @category Yourcategory + * @package __PACKAGE__ + * @author Your Name + * @copyright __YEAR__ Your Name + * @license http://www.opensource.org/licenses/bsd-license.php New BSD License + * @link __VCS__ + */ +namespace __MAIN_NAMESPACE__; +class Main +{ +} diff --git a/src/Pyrus/Developer/PackageFile/Commands/templates/extrasetup.php.tpl b/src/Pyrus/Developer/PackageFile/Commands/templates/extrasetup.php.tpl new file mode 100644 index 0000000..d0ea963 --- /dev/null +++ b/src/Pyrus/Developer/PackageFile/Commands/templates/extrasetup.php.tpl @@ -0,0 +1,25 @@ +dependencies['required']->package['pear2.php.net/PEAR2_Autoload']->save(); +$package->dependencies['required']->package['pear2.php.net/PEAR2_Exception']->save(); +$package->dependencies['required']->package['pear2.php.net/PEAR2_MultiErrors']->save(); +$package->dependencies['required']->package['pear2.php.net/PEAR2_HTTP_Request']->save(); + +$compatible->dependencies['required']->package['pear2.php.net/PEAR2_Autoload']->save(); +$compatible->dependencies['required']->package['pear2.php.net/PEAR2_Exception']->save(); +$compatible->dependencies['required']->package['pear2.php.net/PEAR2_MultiErrors']->save(); +$compatible->dependencies['required']->package['pear2.php.net/PEAR2_HTTP_Request']->save(); + +// ignore files +unset($package->files['www/config.inc.php']); +unset($package->files['www/.htaccess']); +*/ +?> diff --git a/src/Pyrus/Developer/PackageFile/Commands/templates/stub.php.tpl b/src/Pyrus/Developer/PackageFile/Commands/templates/stub.php.tpl new file mode 100644 index 0000000..ee7e6e7 --- /dev/null +++ b/src/Pyrus/Developer/PackageFile/Commands/templates/stub.php.tpl @@ -0,0 +1,48 @@ +#!/usr/bin/env php +getMessage() . PHP_EOL; + exit -1; +} +function __PACKAGE___autoload($class) +{ + $class = str_replace(array('_', '\\\'), '/', $class); + if (file_exists('phar://' . __FILE__ . '/__PACKAGE__-@PACKAGE_VERSION@/php/' . $class . '.php')) { + return include 'phar://' . __FILE__ . '/__PACKAGE__-@PACKAGE_VERSION@/php/' . $class . '.php'; + } +} +spl_autoload_register("__PACKAGE___autoload"); +$phar = new Phar(__FILE__); +$sig = $phar->getSignature(); +define('__PACKAGE___SIG', $sig['hash']); +define('__PACKAGE___SIGTYPE', $sig['hash_type']); + +// your package-specific stuff here, for instance, here is what Pyrus does: + +/** + * $frontend = new \Pyrus\ScriptFrontend\Commands; + * @array_shift($_SERVER['argv']); + * $frontend->run($_SERVER['argv']); + */ +__HALT_COMPILER(); diff --git a/tests/Pyrus/Developer/PackageFile/Commands/PEAR2SkeletonTestCase.php b/tests/Pyrus/Developer/PackageFile/Commands/PEAR2SkeletonTestCase.php new file mode 100644 index 0000000..3efef2c --- /dev/null +++ b/tests/Pyrus/Developer/PackageFile/Commands/PEAR2SkeletonTestCase.php @@ -0,0 +1,74 @@ +base = __DIR__ . '/package-test'; + @mkdir($this->base); + chdir($this->base); + } + + protected function tearDown() + { + exec("rm -rf {$this->base}/Foo"); + } + + /** + * Info array is just like the array returned from + * {@link Pyrus\Developer\PackageFile\Commands::parsePackageName()} + * + * @return void + */ + public function testPear2Skeleton() + { + $info = array(); + + $info['path'] = 'Foo'; + $info['mainPath'] = 'Foo'; + $info['mainClass'] = 'PEAR2\Foo\Main'; + $info['mainNamespace'] = 'PEAR2\Foo'; + $info['svn'] = 'http://svn.php.net/repository/pear2/PEAR2_Foo'; + $info['package'] = $this->packageName; + + $skeleton = new Commands\PEAR2Skeleton($info); + $skeleton->generate(); + + $this->assertFileExists($this->base . '/' . $info['path'] . '/src/' . $info['mainPath'] . '/Main.php'); + + $this->assertFileExists($this->base . '/' . $info['path'] . '/' . $skeleton->getStub()); + $this->assertFileExists($this->base . '/' . $info['path'] . '/' . $skeleton->getExtraSetup()); + $this->assertFileExists($this->base . '/' . $info['path'] . '/' . $skeleton->getPackageXmlSetup()); + + $releaseFiles = $skeleton->getReleaseFiles(); + foreach ($releaseFiles as $releaseFile => $fileContent) { + $this->assertFileExists($this->base . '/' . $info['path'] . '/' . $releaseFile); + } + } +}