diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 5a26be8d..a7b60bc1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -73,6 +73,15 @@ class Builder * @var array */ protected $config; + + /** + * An array of key => value pairs that will be used for + * interpolation and environment variables + * @var array + * @see setInterpolationVars() + * @see getInterpolationVars() + */ + protected $interpolation_vars = array(); /** * Set up the builder. @@ -236,7 +245,47 @@ class Builder { $this->log("\033[0;31m" . $message . "\033[0m"); } + + /** + * Get an array key => value pairs that are used for interpolation + * @return array + */ + public function getInterpolationVars() + { + return $this->interpolation_vars; + } + + /** + * Replace every occurance of the interpolation vars in the given string + * Example: "This is build %PHPCI_BUILD%" => "This is build 182" + * @param string $input + * @return string + */ + public function interpolate($input) + { + $trans_table = array(); + foreach ($this->getInterpolationVars() as $key => $value) { + $trans_table['%'.$key.'%'] = $value; + } + return strtr($input, $trans_table); + } + /** + * Sets the variables that will be used for interpolation. This must be run + * from setupBuild() because prior to that, we don't know the buildPath + */ + protected function setInterpolationVars() + { + $this->interpolation_vars = array( + 'PHPCI' => 1, + 'PHPCI_COMMIT' => $this->build->getCommitId(), + 'PHPCI_PROJECT' => $this->build->getProject()->getId(), + 'PHPCI_BUILD' => $this->build->getId(), + 'PHPCI_PROJECT_TITLE' => $this->build->getProject()->getTitle(), + 'PHPCI_BUILD_PATH' => $this->buildPath, + ); + } + /** * Set up a working copy of the project for building. */ @@ -247,14 +296,13 @@ class Builder $this->ciDir = realpath(dirname(__FILE__) . '/../') . '/'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; + $this->setInterpolationVars(); + // Setup environment vars that will be accessible during exec() - putenv("PHPCI=1"); - putenv("PHPCI_COMMIT=".$commitId); - putenv("PHPCI_PROJECT=".$this->build->getProject()->getId()); - putenv("PHPCI_BUILD=".$this->build->getId()); - putenv("PHPCI_PROJECT_TITLE=".$this->build->getProject()->getTitle()); - putenv("PHPCI_BUILD_PATH=".$this->buildPath); - + foreach ($this->getInterpolationVars() as $key => $value) { + putenv($key.'='.$value); + } + // Create a working copy of the project: if (!$this->build->createWorkingCopy($this, $this->buildPath)) { return false; diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index 6385e5aa..35459aec 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -44,7 +44,7 @@ class InstallCommand extends Command $conf['b8']['database']['name'] = $this->ask('Enter the database name PHPCI should use: '); $conf['b8']['database']['username'] = $this->ask('Enter your MySQL username: '); $conf['b8']['database']['password'] = $this->ask('Enter your MySQL password: ', true); - $conf['phpci']['url'] = $this->ask('Your PHPCI URL (without trailing slash): '); + $conf['phpci']['url'] = $this->ask('Your PHPCI URL (without trailing slash): ', false, array(FILTER_VALIDATE_URL,"/[^\/]$/i")); $conf['phpci']['github']['id'] = $this->ask('(Optional) Github Application ID: ', true); $conf['phpci']['github']['secret'] = $this->ask('(Optional) Github Application Secret: ', true); @@ -71,12 +71,11 @@ class InstallCommand extends Command $gen->generate(); // Try to create a user account: - $adminEmail = $this->ask('Enter your email address (leave blank if updating): ', true); + $adminEmail = $this->ask('Enter your email address (leave blank if updating): ', true, FILTER_VALIDATE_EMAIL); if (empty($adminEmail)) { return; } - $adminPass = $this->ask('Enter your desired admin password: '); $adminName = $this->ask('Enter your name: '); @@ -97,7 +96,7 @@ class InstallCommand extends Command } } - protected function ask($question, $emptyOk = false) + protected function ask($question, $emptyOk = false, $validationFilter = null) { print $question . ' '; @@ -109,9 +108,51 @@ class InstallCommand extends Command $rtn = trim($rtn); if (!$emptyOk && empty($rtn)) { - $rtn = $this->ask($question, $emptyOk); + $rtn = $this->ask($question, $emptyOk, $validationFilter); + } elseif ($validationFilter != null && ! empty($rtn)) { + if (! $this -> controlFormat($rtn, $validationFilter, $statusMessage)) { + print $statusMessage; + $rtn = $this->ask($question, $emptyOk, $validationFilter); + } } return $rtn; } + protected function controlFormat($valueToInspect,$filter,&$statusMessage) + { + $filters = !(is_array($filter))? array($filter) : $filter; + $statusMessage = ''; + $status = true; + $options = array(); + + foreach ($filters as $filter) { + if (! is_int($filter)) { + $regexp = $filter; + $filter = FILTER_VALIDATE_REGEXP; + $options = array( + 'options' => array( + 'regexp' => $regexp, + ) + ); + } + if (! filter_var($valueToInspect, $filter, $options)) { + $status = false; + + switch ($filter) + { + case FILTER_VALIDATE_URL : + $statusMessage = 'Incorrect url format.' . PHP_EOL; + break; + case FILTER_VALIDATE_EMAIL : + $statusMessage = 'Incorrect e-mail format.' . PHP_EOL; + break; + case FILTER_VALIDATE_REGEXP : + $statusMessage = 'Incorrect format.' . PHP_EOL; + break; + } + } + } + + return $status; + } } diff --git a/PHPCI/Plugin/Env.php b/PHPCI/Plugin/Env.php index 1de016fb..e09d3dbf 100644 --- a/PHPCI/Plugin/Env.php +++ b/PHPCI/Plugin/Env.php @@ -41,7 +41,7 @@ class Env implements \PHPCI\Plugin $env_var = "$key=$value"; } - if (!putenv($env_var)) { + if (!putenv($this->phpci->interpolate($env_var))) { $success = false; $this->phpci->logFailure("Unable to set environment variable"); } diff --git a/PHPCI/Plugin/Mysql.php b/PHPCI/Plugin/Mysql.php index e67c31a4..5138116e 100644 --- a/PHPCI/Plugin/Mysql.php +++ b/PHPCI/Plugin/Mysql.php @@ -51,8 +51,8 @@ class Mysql implements \PHPCI\Plugin if (isset($buildSettings['mysql'])) { $sql = $buildSettings['mysql']; - $this->host = !empty($sql['host']) ? $sql['host'] : $this->host; - $this->user = !empty($sql['user']) ? $sql['user'] : $this->user; + $this->host = !empty($sql['host']) ? $sql['host'] : $this->phpci->interpolate($this->host); + $this->user = !empty($sql['user']) ? $sql['user'] : $this->phpci->interpolate($this->user); $this->pass = array_key_exists('pass', $sql) ? $sql['pass'] : $this->pass; } } @@ -71,10 +71,12 @@ class Mysql implements \PHPCI\Plugin foreach ($this->queries as $query) { if (!is_array($query)) { // Simple query - $this->pdo->query($query); + $this->pdo->query($this->phpci->interpolate($query)); } else if (isset($query['import'])) { // SQL file execution $this->executeFile($query['import']); + } else { + throw new \Exception("Invalid command"); } } } catch (\Exception $ex) { @@ -88,15 +90,15 @@ class Mysql implements \PHPCI\Plugin protected function executeFile($query) { if (!isset($query['file'])) { - throw new \Exception("Import statement must contiain an 'file' key"); + throw new \Exception("Import statement must contain a 'file' key"); } - $import_file = $this->phpci->buildPath . $query['file']; + $import_file = $this->phpci->buildPath . $this->phpci->interpolate($query['file']); if (!is_readable($import_file)) { throw new \Exception("Cannot open SQL import file: $import_file"); } - $database = isset($query['database'])? $query['database']: null; + $database = isset($query['database'])? $this->phpci->interpolate($query['database']): null; $import_command = $this->getImportCommand($import_file, $database); if (!$this->phpci->executeCommand($import_command)) { diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php new file mode 100644 index 00000000..9aaa7536 --- /dev/null +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -0,0 +1,89 @@ + +* @package PHPCI +* @subpackage Plugins +*/ +class PhpCsFixer implements \PHPCI\Plugin +{ + protected $phpci; + + protected $args = ''; + + protected $workingDir = ''; + protected $level = 'all'; + protected $dryRun = true; + protected $verbose = false; + protected $diff = false; + protected $levels = array('psr0', 'psr1', 'psr2', 'all'); + + public function __construct(\PHPCI\Builder $phpci, array $options = array()) + { + $this->phpci = $phpci; + $this->workingdir = $this->phpci->buildPath; + $this->buildArgs($options); + } + + public function execute() + { + $success = false; + + $curdir = getcwd(); + chdir($this->workingdir); + + $cmd = PHPCI_BIN_DIR . 'php-cs-fixer fix . %s'; + $success = $this->phpci->executeCommand($cmd, $this->args); + + chdir($curdir); + + return $success; + } + + public function buildArgs($options) + { + $argstring = ""; + + if ( array_key_exists('verbose', $options) && $options['verbose'] ) + { + $this->verbose = true; + $this->args .= ' --verbose'; + } + + if ( array_key_exists('diff', $options) && $options['diff'] ) + { + $this->diff = true; + $this->args .= ' --diff'; + } + + if ( array_key_exists('level', $options) && in_array($options['level'], $this->levels) ) + { + $this->level = $options['level']; + $this->args .= ' --level='.$options['level']; + } + + if ( array_key_exists('dryrun', $options) && $options['dryrun'] ) + { + $this->dryRun = true; + $this->args .= ' --dry-run'; + } + + if ( array_key_exists('workingdir', $options) + && $options['workingdir'] + && is_dir($this->phpci->buildPath.$options['workingdir']) ) + { + $this->workingdir = $this->phpci->buildPath.$options['workingdir']; + } + + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 03e9ec38..7b8c37b3 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,37 @@ { - "name": "block8/phpci", - "description": "Simple continuous integration for PHP projects.", + "name" : "block8/phpci", + "description" : "Simple continuous integration for PHP projects.", "minimum-stability": "dev", - "type": "library", - "keywords": ["php", "phpci", "ci", "continuous", "integration", "testing", "phpunit", "continuous integration", "jenkins", "travis"], - "homepage": "http://www.phptesting.org/", - "license": "BSD-2-Clause", + "type" : "library", + "keywords" : ["php", "phpci", "ci", "continuous", "integration", "testing", "phpunit", "continuous integration", "jenkins", "travis"], + "homepage" : "http://www.phptesting.org/", + "license" : "BSD-2-Clause", "authors": [ { - "name": "Dan Cryer", - "email": "dan.cryer@block8.co.uk", + "name" : "Dan Cryer", + "email" : "dan.cryer@block8.co.uk", "homepage": "http://www.block8.co.uk", - "role": "Developer" + "role" : "Developer" } ], "support": { - "email": "hello+phpci@block8.co.uk", + "email" : "hello+phpci@block8.co.uk", "issues": "https://github.com/Block8/PHPCI/issues", "source": "https://github.com/Block8/PHPCI" }, "require": { - "block8/b8framework": "dev-master", - "phpunit/phpunit": "3.*", - "phpmd/phpmd" : "1.*", - "sebastian/phpcpd": "1.*", + "block8/b8framework" : "dev-master", + "phpunit/phpunit" : "3.*", + "phpmd/phpmd" : "1.*", + "sebastian/phpcpd" : "1.*", "squizlabs/php_codesniffer": "1.*", "ircmaxell/password-compat": "1.x", - "phpspec/phpspec": "2.*", - "symfony/yaml": "2.2.x-dev", - "symfony/console": "2.2.*" + "phpspec/phpspec" : "2.*", + "symfony/yaml" : "2.2.x-dev", + "symfony/console" : "2.2.*", + "fabpot/php-cs-fixer" : "0.3.*@dev" } }