diff --git a/PHPCI/Application.php b/PHPCI/Application.php index 9bacd78d..0723c2ad 100644 --- a/PHPCI/Application.php +++ b/PHPCI/Application.php @@ -32,11 +32,14 @@ class Application extends b8\Application $externalAction = in_array($this->controllerName, array('Bitbucket', 'Github', 'Gitlab', 'BuildStatus')); $skipValidation = ($externalAction || $sessionAction); - if($skipValidation || $this->validateSession()) { + if ($skipValidation || $this->validateSession()) { parent::handleRequest(); } } catch (\Exception $ex) { - $content = '

There was a problem with this request

Please paste the details below into a new bug report so that we can investigate and fix it.

'; + $content = '

There was a problem with this request

+

Please paste the details below into a + new bug report + so that we can investigate and fix it.

'; ob_start(); var_dump(array( diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 0667a551..42f98ee1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -52,12 +52,7 @@ class Builder /** * @var bool */ - protected $verbose = false; - - /** - * @var bool[] - */ - protected $plugins = array(); + protected $verbose = true; /** * @var \PHPCI\Model\Build @@ -84,7 +79,6 @@ class Builder * interpolation and environment variables * @var array * @see setInterpolationVars() - * @see getInterpolationVars() */ protected $interpolation_vars = array(); @@ -93,19 +87,21 @@ class Builder */ protected $store; + /** + * @var bool + */ + public $quiet = false; + /** * Set up the builder. * @param \PHPCI\Model\Build * @param callable */ - public function __construct(Build $build, $logCallback = null) + public function __construct(Build $build, callable $logCallback) { $this->build = $build; $this->store = Store\Factory::getStore('Build'); - - if (!is_null($logCallback) && is_callable($logCallback)) { - $this->logCallback = $logCallback; - } + $this->logCallback = $logCallback; } /** @@ -123,7 +119,13 @@ class Builder */ public function getConfig($key) { - return isset($this->config[$key]) ? $this->config[$key] : null; + $rtn = null; + + if (isset($this->config[$key])) { + $rtn = $this->config[$key]; + } + + return $rtn; } /** @@ -136,29 +138,11 @@ class Builder return Config::getInstance()->get($key); } - /** - * Access the build. - * @param Build - */ - public function getBuild() - { - return $this->build; - } - /** * @return string The title of the project being built. */ public function getBuildProjectTitle() { - return $this->getBuild()->getProject()->getTitle(); - } - - /** - * Indicates if the build has passed or failed. - * @return bool - */ - public function getSuccessStatus() - { - return $this->success; + return $this->build->getProject()->getTitle(); } /** @@ -173,47 +157,41 @@ class Builder $this->build->sendStatusPostback(); try { - if ($this->setupBuild()) { - // Run setup steps: - $this->executePlugins('setup'); + // Set up the build: + $this->setupBuild(); - // Run the any tests: - $this->executePlugins('test'); + // Run the core plugin stages: + foreach (array('setup', 'test', 'complete') as $stage) { + $this->executePlugins($stage); $this->log(''); - - // Run build complete steps: - $this->executePlugins('complete'); - - // Run success or failure plugins: - if ($this->success) { - $this->build->setStatus(2); - - $this->executePlugins('success'); - $this->logSuccess('BUILD SUCCESSFUL!'); - } else { - $this->build->setStatus(3); - - $this->executePlugins('failure'); - $this->logFailure('BUILD FAILED!'); - } - - $this->log(''); - } else { - $this->build->setStatus(3); } + + // Failed build? Execute failure plugins and then mark the build as failed. + if (!$this->success) { + $this->executePlugins('failure'); + throw new \Exception('BUILD FAILED!'); + } + + // If we got this far, the build was successful! + if ($this->success) { + $this->build->setStatus(2); + $this->executePlugins('success'); + $this->logSuccess('BUILD SUCCESSFUL!'); + } + } catch (\Exception $ex) { $this->logFailure($ex->getMessage()); $this->build->setStatus(3); } // Clean up: - $this->removeBuild(); + $this->log('Removing build.'); + shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); // Update the build in the database, ping any external services, etc. $this->build->sendStatusPostback(); $this->build->setFinished(new \DateTime()); $this->build->setLog($this->log); - $this->build->setPlugins(json_encode($this->plugins)); $this->store->save($this->build); } @@ -223,8 +201,10 @@ class Builder public function executeCommand() { $command = call_user_func_array('sprintf', func_get_args()); - - $this->log('Executing: ' . $command, ' '); + + if (!$this->quiet) { + $this->log('Executing: ' . $command, ' '); + } $status = 0; exec($command, $this->lastOutput, $status); @@ -233,7 +213,14 @@ class Builder $this->log($this->lastOutput, ' '); } - return ($status == 0) ? true : false; + + $rtn = false; + + if ($status == 0) { + $rtn = true; + } + + return $rtn; } /** @@ -251,25 +238,16 @@ class Builder */ public function log($message, $prefix = '') { - if (is_array($message)) { - foreach ($message as $item) { - if (is_callable($this->logCallback)) { - call_user_func_array($this->logCallback, array($prefix . $item)); - } - - $this->log .= $prefix . $item . PHP_EOL; - } - } else { - $message = $prefix . $message; - $this->log .= $message . PHP_EOL; + if (!is_array($message)) { + $message = array($message); + } - if (isset($this->logCallback) && is_callable($this->logCallback)) { - call_user_func_array($this->logCallback, array($message)); - } + foreach ($message as $item) { + call_user_func_array($this->logCallback, array($prefix . $item)); + $this->log .= $prefix . $item . PHP_EOL; } $this->build->setLog($this->log); - $this->build->setPlugins(json_encode($this->plugins)); $this->store->save($this->build); } @@ -291,15 +269,6 @@ 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" @@ -308,12 +277,9 @@ class Builder */ public function interpolate($input) { - $trans_table = array(); - foreach ($this->getInterpolationVars() as $key => $value) { - $trans_table['%'.$key.'%'] = $value; - $trans_table['%PHPCI_'.$key.'%'] = $value; - } - return strtr($input, $trans_table); + $keys = array_keys($this->interpolation_vars); + $values = array_values($this->interpolation_vars); + return str_replace($keys, $values, $input); } /** @@ -322,15 +288,28 @@ class Builder */ protected function setInterpolationVars() { - $this->interpolation_vars = array( - 'PHPCI' => 1, - 'COMMIT' => $this->build->getCommitId(), - 'PROJECT' => $this->build->getProject()->getId(), - 'BUILD' => $this->build->getId(), - 'PROJECT_TITLE' => $this->build->getProject()->getTitle(), - 'BUILD_PATH' => $this->buildPath, - 'BUILD_URI' => PHPCI_URL . "build/view/" . $this->build->getId(), - ); + $this->interpolation_vars = array(); + $this->interpolation_vars['%PHPCI%'] = 1; + $this->interpolation_vars['%COMMIT%'] = $this->build->getCommitId(); + $this->interpolation_vars['%PROJECT%'] = $this->build->getProjectId(); + $this->interpolation_vars['%BUILD%'] = $this->build->getId(); + $this->interpolation_vars['%PROJECT_TITLE%'] = $this->getBuildProjectTitle(); + $this->interpolation_vars['%BUILD_PATH%'] = $this->buildPath; + $this->interpolation_vars['%BUILD_URI%'] = PHPCI_URL . "build/view/" . $this->build->getId(); + $this->interpolation_vars['%PHPCI_COMMIT%'] = $this->interpolation_vars['%COMMIT%']; + $this->interpolation_vars['%PHPCI_PROJECT%'] = $this->interpolation_vars['%PROJECT%']; + $this->interpolation_vars['%PHPCI_BUILD%'] = $this->interpolation_vars['%BUILD%']; + $this->interpolation_vars['%PHPCI_PROJECT_TITLE%'] = $this->interpolation_vars['%PROJECT_TITLE%']; + $this->interpolation_vars['%PHPCI_BUILD_PATH%'] = $this->interpolation_vars['%BUILD_PATH%']; + $this->interpolation_vars['%PHPCI_BUILD_URI%'] = $this->interpolation_vars['%BUILD_URI%']; + + putenv('PHPCI=1'); + putenv('PHPCI_COMMIT='.$this->interpolation_vars['%COMMIT%']); + putenv('PHPCI_PROJECT='.$this->interpolation_vars['%PROJECT%']); + putenv('PHPCI_BUILD='.$this->interpolation_vars['%BUILD%']); + putenv('PHPCI_PROJECT_TITLE='.$this->interpolation_vars['%PROJECT_TITLE%']); + putenv('PHPCI_BUILD_PATH='.$this->interpolation_vars['%BUILD_PATH%']); + putenv('PHPCI_BUILD_URI='.$this->interpolation_vars['%BUILD_URI%']); } /** @@ -338,28 +317,20 @@ class Builder */ protected function setupBuild() { - $commitId = $this->build->getCommitId(); $buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId(); $this->ciDir = dirname(__FILE__) . '/../'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; $this->setInterpolationVars(); - // Setup environment vars that will be accessible during exec() - 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; + throw new \Exception('Could not create a working copy.'); } // Does the project's phpci.yml request verbose mode? if (!isset($this->config['build_settings']['verbose']) || !$this->config['build_settings']['verbose']) { $this->verbose = false; - } else { - $this->verbose = true; } // Does the project have any paths it wants plugins to ignore? @@ -390,78 +361,55 @@ class Builder $options['allow_failures'] = false; } - $class = str_replace('_', ' ', $plugin); - $class = ucwords($class); - $class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class); + // Try and execute it: + if ($this->executePlugin($plugin, $options)) { - if (!class_exists($class)) { - $this->logFailure('Plugin does not exist: ' . $plugin); + // Execution was successful: + $this->logSuccess('PLUGIN STATUS: SUCCESS!'); - if ($stage == 'test') { - $this->plugins[$plugin] = false; + } else { - if (!$options['allow_failures']) { - $this->success = false; - } - } - - continue; - } - - try { - $obj = new $class($this, $options); - - if (!$obj->execute()) { - if ($stage == 'test') { - $this->plugins[$plugin] = false; - - if (!$options['allow_failures']) { - $this->success = false; - } - } - - $this->logFailure('PLUGIN STATUS: FAILED'); - continue; - } - } catch (\Exception $ex) { - $this->logFailure('EXCEPTION: ' . $ex->getMessage()); - - if ($stage == 'test') { - $this->plugins[$plugin] = false; - - if (!$options['allow_failures']) { - $this->success = false; - } + // If we're in the "test" stage and the plugin is not allowed to fail, + // then mark the build as failed: + if ($stage == 'test' && !$options['allow_failures']) { + $this->success = false; } $this->logFailure('PLUGIN STATUS: FAILED'); - continue; } - - if ($stage == 'test') { - $this->plugins[$plugin] = true; - } - - $this->logSuccess('PLUGIN STATUS: SUCCESS!'); } } /** - * Clean up our working copy. - */ - protected function removeBuild() - { - $this->log('Removing build.'); - shell_exec(sprintf('rm -Rf "%s"', $this->buildPath)); - } - - /** - * Store build meta data + * Executes a given plugin, with options and returns the result. */ - public function storeBuildMeta($key, $value) + protected function executePlugin($plugin, $options) { - $value = json_encode($value); - $this->store->setMeta($this->build->getProjectId(), $this->build->getId(), $key, $value); + // Figure out the class name and check the plugin exists: + $class = str_replace('_', ' ', $plugin); + $class = ucwords($class); + $class = 'PHPCI\\Plugin\\' . str_replace(' ', '', $class); + + if (!class_exists($class)) { + $this->logFailure('Plugin does not exist: ' . $plugin); + return false; + } + + $rtn = true; + + // Try running it: + try { + $obj = new $class($this, $this->build, $options); + + if (!$obj->execute()) { + $rtn = false; + } + } catch (\Exception $ex) { + $this->logFailure('EXCEPTION: ' . $ex->getMessage()); + $rtn = false; + } + + return $rtn; } /** diff --git a/PHPCI/Command/DaemonCommand.php b/PHPCI/Command/DaemonCommand.php index 94ecb464..d6458f2b 100644 --- a/PHPCI/Command/DaemonCommand.php +++ b/PHPCI/Command/DaemonCommand.php @@ -66,7 +66,7 @@ class DaemonCommand extends Command protected function startDaemon() { - if ( file_exists(PHPCI_DIR.'/daemon/daemon.pid') ) { + if (file_exists(PHPCI_DIR.'/daemon/daemon.pid')) { echo "Already started\n"; return "alreadystarted"; } @@ -80,7 +80,7 @@ class DaemonCommand extends Command protected function stopDaemon() { - if ( !file_exists(PHPCI_DIR.'/daemon/daemon.pid') ) { + if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) { echo "Not started\n"; return "notstarted"; } @@ -94,14 +94,14 @@ class DaemonCommand extends Command protected function statusDaemon() { - if ( !file_exists(PHPCI_DIR.'/daemon/daemon.pid') ) { + if (!file_exists(PHPCI_DIR.'/daemon/daemon.pid')) { echo "Not running\n"; return "notrunning"; } $pid = trim(file_get_contents(PHPCI_DIR.'/daemon/daemon.pid')); $pidcheck = sprintf("/proc/%s", $pid); - if ( is_dir($pidcheck) ) { + if (is_dir($pidcheck)) { echo "Running\n"; return "running"; } diff --git a/PHPCI/Command/DaemoniseCommand.php b/PHPCI/Command/DaemoniseCommand.php index f46e6948..3c490d75 100644 --- a/PHPCI/Command/DaemoniseCommand.php +++ b/PHPCI/Command/DaemoniseCommand.php @@ -57,7 +57,7 @@ class DaemoniseCommand extends Command if (0 == $buildCount && $this->sleep < 15) { $this->sleep++; - } else if (1 < $this->sleep) { + } elseif (1 < $this->sleep) { $this->sleep--; } echo '.'.(0 === $buildCount?'':'build'); diff --git a/PHPCI/Command/GenerateCommand.php b/PHPCI/Command/GenerateCommand.php index 54a729ca..3a97f70c 100644 --- a/PHPCI/Command/GenerateCommand.php +++ b/PHPCI/Command/GenerateCommand.php @@ -14,6 +14,8 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use b8\Database; +use b8\Database\CodeGenerator; /** * Generate console command - Reads the database and generates models and stores. @@ -35,7 +37,7 @@ class GenerateCommand extends Command */ protected function execute(InputInterface $input, OutputInterface $output) { - $gen = new \b8\Database\CodeGenerator(\b8\Database::getConnection(), 'PHPCI', PHPCI_DIR . '/PHPCI/'); + $gen = new CodeGenerator(Database::getConnection(), 'PHPCI', PHPCI_DIR . '/PHPCI/', false); $gen->generateModels(); $gen->generateStores(); } diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index dea4e560..7f9daf6d 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -44,7 +44,8 @@ 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): ', false, array(FILTER_VALIDATE_URL,"/[^\/]$/i")); + $ask = 'Your PHPCI URL (without trailing slash): '; + $conf['phpci']['url'] = $this->ask($ask, 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); @@ -54,7 +55,9 @@ class InstallCommand extends Command $conf['phpci']['email_settings']['smtp_username'] = $this->ask('(Optional) Smtp Username: ', true); $conf['phpci']['email_settings']['smtp_password'] = $this->ask('(Optional) Smtp Password: ', true); $conf['phpci']['email_settings']['from_address'] = $this->ask('(Optional) Email address to send from: ', true); - $conf['phpci']['email_settings']['default_mailto_address'] = $this->ask('(Optional) Default address to email notifications to: ', true); + + $ask = '(Optional) Default address to email notifications to: '; + $conf['phpci']['email_settings']['default_mailto_address'] = $this->ask($ask, true); $dbUser = $conf['b8']['database']['username']; $dbPass = $conf['b8']['database']['password']; @@ -126,7 +129,7 @@ class InstallCommand extends Command return $rtn; } - protected function controlFormat($valueToInspect,$filter,&$statusMessage) + protected function controlFormat($valueToInspect, $filter, &$statusMessage) { $filters = !(is_array($filter))? array($filter) : $filter; $statusMessage = ''; @@ -148,13 +151,13 @@ class InstallCommand extends Command switch ($filter) { - case FILTER_VALIDATE_URL : + case FILTER_VALIDATE_URL: $statusMessage = 'Incorrect url format.' . PHP_EOL; break; - case FILTER_VALIDATE_EMAIL : + case FILTER_VALIDATE_EMAIL: $statusMessage = 'Incorrect e-mail format.' . PHP_EOL; break; - case FILTER_VALIDATE_REGEXP : + case FILTER_VALIDATE_REGEXP: $statusMessage = 'Incorrect format.' . PHP_EOL; break; } diff --git a/PHPCI/Command/RunCommand.php b/PHPCI/Command/RunCommand.php index abd30c6c..94d191d3 100644 --- a/PHPCI/Command/RunCommand.php +++ b/PHPCI/Command/RunCommand.php @@ -52,7 +52,9 @@ class RunCommand extends Command if ($input->getOption('verbose')) { $builder = new Builder($build, array($this, 'logCallback')); } else { - $builder = new Builder($build); + $builder = new Builder($build, function () { + // Empty stub function. + }); } $builder->execute(); diff --git a/PHPCI/Controller.php b/PHPCI/Controller.php index e344a613..d95c24e0 100644 --- a/PHPCI/Controller.php +++ b/PHPCI/Controller.php @@ -19,46 +19,49 @@ class Controller extends \b8\Controller */ protected $view; - public function init() {} + public function init() + { + // Extended by actual controllers. + } - public function __construct(Config $config, Request $request, Response $response) - { - parent::__construct($config, $request, $response); + public function __construct(Config $config, Request $request, Response $response) + { + parent::__construct($config, $request, $response); - $class = explode('\\', get_class($this)); - $this->className = substr(array_pop($class), 0, -10); - $this->setControllerView(); - } + $class = explode('\\', get_class($this)); + $this->className = substr(array_pop($class), 0, -10); + $this->setControllerView(); + } - protected function setControllerView() - { - if (View::exists($this->className)) { - $this->controllerView = new View($this->className); - } else { - $this->controllerView = new View\UserView('{@content}'); - } - } + protected function setControllerView() + { + if (View::exists($this->className)) { + $this->controllerView = new View($this->className); + } else { + $this->controllerView = new View\UserView('{@content}'); + } + } - protected function setView($action) - { - if (View::exists($this->className . '/' . $action)) { - $this->view = new View($this->className . '/' . $action); - } - } + protected function setView($action) + { + if (View::exists($this->className . '/' . $action)) { + $this->view = new View($this->className . '/' . $action); + } + } - public function handleAction($action, $actionParams) - { - $this->setView($action); - $response = parent::handleAction($action, $actionParams); + public function handleAction($action, $actionParams) + { + $this->setView($action); + $response = parent::handleAction($action, $actionParams); - if (is_string($response)) { - $this->controllerView->content = $response; - } elseif (isset($this->view)) { - $this->controllerView->content = $this->view->render(); - } + if (is_string($response)) { + $this->controllerView->content = $response; + } elseif (isset($this->view)) { + $this->controllerView->content = $this->view->render(); + } - $this->response->setContent($this->controllerView->render()); + $this->response->setContent($this->controllerView->render()); - return $this->response; - } -} \ No newline at end of file + return $this->response; + } +} diff --git a/PHPCI/Controller/BuildController.php b/PHPCI/Controller/BuildController.php index cd8007b1..8c183774 100644 --- a/PHPCI/Controller/BuildController.php +++ b/PHPCI/Controller/BuildController.php @@ -38,7 +38,7 @@ class BuildController extends \PHPCI\Controller $build = $this->buildStore->getById($buildId); $this->view->plugins = $this->getUiPlugins(); $this->view->build = $build; - $this->view->data = $this->getBuildData($buildId); + $this->view->data = $this->getBuildData($build); } protected function getUiPlugins() @@ -63,7 +63,7 @@ class BuildController extends \PHPCI\Controller */ public function data($buildId) { - die($this->getBuildData($buildId)); + die($this->getBuildData($this->buildStore->getById($buildId))); } /** @@ -86,10 +86,8 @@ class BuildController extends \PHPCI\Controller /** * Get build data from database and json encode it: */ - protected function getBuildData($buildId) + protected function getBuildData($build) { - $build = $this->buildStore->getById($buildId); - $data = array(); $data['status'] = (int)$build->getStatus(); $data['log'] = $this->cleanLog($build->getLog()); diff --git a/PHPCI/Controller/PluginController.php b/PHPCI/Controller/PluginController.php index 2d9d74fe..0dd3f2b4 100644 --- a/PHPCI/Controller/PluginController.php +++ b/PHPCI/Controller/PluginController.php @@ -68,7 +68,7 @@ class PluginController extends \PHPCI\Controller $this->setComposerJson($json); if ($this->canInstall) { - $res = shell_exec($this->composerPath . ' update --working-dir=' . APPLICATION_PATH . ' > /dev/null 2>&1 &'); + shell_exec($this->composerPath . ' update --working-dir=' . APPLICATION_PATH . ' > /dev/null 2>&1 &'); } header('Location: ' . PHPCI_URL . 'plugin?r=' . $package); @@ -89,7 +89,7 @@ class PluginController extends \PHPCI\Controller $this->setComposerJson($json); if ($this->canInstall) { - $res = shell_exec($this->composerPath . ' update --working-dir=' . APPLICATION_PATH . ' > /dev/null 2>&1 &'); + shell_exec($this->composerPath . ' update --working-dir=' . APPLICATION_PATH . ' > /dev/null 2>&1 &'); header('Location: ' . PHPCI_URL . 'plugin?i=' . $package); die; @@ -141,10 +141,10 @@ class PluginController extends \PHPCI\Controller public function packagistSearch() { - $q = $this->getParam('q', ''); + $searchQuery = $this->getParam('q', ''); $http = new \b8\HttpClient(); $http->setHeaders(array('User-Agent: PHPCI/1.0 (+http://www.phptesting.org)')); - $res = $http->get('https://packagist.org/search.json', array('q' => $q)); + $res = $http->get('https://packagist.org/search.json', array('q' => $searchQuery)); die(json_encode($res['body'])); } diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index 2d61b882..db684051 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -173,7 +173,7 @@ class ProjectController extends \PHPCI\Controller $values = $form->getValues(); if ($values['type'] == "gitlab") { - preg_match('`^(.*)@(.*):(.*)/(.*)\.git`',$values['reference'],$matches); + preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $values['reference'], $matches); $info = array(); $info["user"] = $matches[1]; $info["domain"] = $matches[2]; @@ -238,7 +238,8 @@ class ProjectController extends \PHPCI\Controller $values['key'] = $values['git_key']; if ($values['type'] == "gitlab") { $accessInfo = $project->getAccessInformation(); - $values['reference'] = $accessInfo["user"].'@'.$accessInfo["domain"].':' . $project->getReference().".git"; + $reference = $accessInfo["user"].'@'.$accessInfo["domain"].':' . $project->getReference().".git"; + $values['reference'] = $reference; } } @@ -259,12 +260,12 @@ class ProjectController extends \PHPCI\Controller $values['git_key'] = $values['key']; if ($values['type'] == "gitlab") { - preg_match('`^(.*)@(.*):(.*)/(.*)\.git`',$values['reference'],$matches); + preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $values['reference'], $matches); $info = array(); $info["user"] = $matches[1]; $info["domain"] = $matches[2]; $values['access_information'] = serialize($info); - $values['reference'] = $matches[3]."/".$matches[4]; + $values['reference'] = $matches[3] . "/" . $matches[4]; } $project->setValues($values); @@ -314,44 +315,9 @@ class ProjectController extends \PHPCI\Controller $form->addField($field); } - $referenceValidator = function ($val) use ($values) { - $type = $values['type']; - - switch($type) { - case 'hg': - if (!preg_match('/^(https?):\/\//', $val)) { - throw new \Exception('Mercurial repository URL must be start with http:// or https://.'); - } - break; - case 'remote': - if (!preg_match('/^(git|https?):\/\//', $val)) { - throw new \Exception('Repository URL must be start with git://, http:// or https://.'); - } - break; - case 'local': - if (!is_dir($val)) { - throw new \Exception('The path you specified does not exist.'); - } - break; - case 'gitlab': - if (!preg_match('`^(.*)@(.*):(.*)/(.*)\.git`', $val)) { - throw new \Exception('GitLab Repository name must be in the format "user@domain.tld:owner/repo.git".'); - } - break; - case 'github': - case 'bitbucket': - if (!preg_match('/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/', $val)) { - throw new \Exception('Repository name must be in the format "owner/repo".'); - } - break; - } - - return true; - }; - $field = new Form\Element\Text('reference'); $field->setRequired(true); - $field->setValidator($referenceValidator); + $field->setValidator($this->getReferenceValidator($values)); $field->setLabel('Repository Name / URL (Remote) or Path (Local)'); $field->setClass('form-control'); $field->setContainerClass('form-group'); @@ -401,4 +367,42 @@ class ProjectController extends \PHPCI\Controller return $rtn; } + + protected function getReferenceValidator($values) + { + return function ($val) use ($values) { + $type = $values['type']; + + $validators = array( + 'hg' => array( + 'regex' => '/^(https?):\/\//', + 'message' => 'Mercurial repository URL must be start with http:// or https://' + ), + 'remote' => array( + 'regex' => '/^(git|https?):\/\//', + 'message' => 'Repository URL must be start with git://, http:// or https://' + ), + 'gitlab' => array( + 'regex' => '`^(.*)@(.*):(.*)/(.*)\.git`', + 'message' => 'GitLab Repository name must be in the format "user@domain.tld:owner/repo.git"' + ), + 'github' => array( + 'regex' => '/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/', + 'message' => 'Repository name must be in the format "owner/repo"' + ), + 'bitbucket' => array( + 'regex' => '/^[a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-\.]+$/', + 'message' => 'Repository name must be in the format "owner/repo"' + ), + ); + + if (in_array($type, $validators) && !preg_match($validators[$type]['regex'], $val)) { + throw new \Exception($validators[$type]['message']); + } elseif ($type == 'local' && !is_dir($val)) { + throw new \Exception('The path you specified does not exist.'); + } + + return true; + }; + } } diff --git a/PHPCI/Controller/UserController.php b/PHPCI/Controller/UserController.php index e0cbd5e5..ad41aff6 100644 --- a/PHPCI/Controller/UserController.php +++ b/PHPCI/Controller/UserController.php @@ -10,8 +10,9 @@ namespace PHPCI\Controller; use b8; -use PHPCI\Model\User; use b8\Form; +use PHPCI\Controller; +use PHPCI\Model\User; /** * User Controller - Allows an administrator to view, add, edit and delete users. @@ -19,7 +20,7 @@ use b8\Form; * @package PHPCI * @subpackage Web */ -class UserController extends \PHPCI\Controller +class UserController extends Controller { /** * @var \PHPCI\Store\UserStore diff --git a/PHPCI/Model/Base/BuildBase.php b/PHPCI/Model/Base/BuildBase.php index e620452f..52a549d5 100644 --- a/PHPCI/Model/Base/BuildBase.php +++ b/PHPCI/Model/Base/BuildBase.php @@ -7,6 +7,7 @@ namespace PHPCI\Model\Base; use b8\Model; +use b8\Store\Factory; /** * Build Base Model @@ -43,12 +44,13 @@ class BuildBase extends Model 'finished' => null, 'plugins' => null, 'committer_email' => null, - ); + ); /** * @var array */ protected $getters = array( + // Direct property getters: 'id' => 'getId', 'project_id' => 'getProjectId', 'commit_id' => 'getCommitId', @@ -60,13 +62,16 @@ class BuildBase extends Model 'finished' => 'getFinished', 'plugins' => 'getPlugins', 'committer_email' => 'getCommitterEmail', + + // Foreign key getters: 'Project' => 'getProject', - ); + ); /** * @var array */ protected $setters = array( + // Direct property setters: 'id' => 'setId', 'project_id' => 'setProjectId', 'commit_id' => 'setCommitId', @@ -78,8 +83,10 @@ class BuildBase extends Model 'finished' => 'setFinished', 'plugins' => 'setPlugins', 'committer_email' => 'setCommitterEmail', + + // Foreign key setters: 'Project' => 'setProject', - ); + ); /** * @var array @@ -87,69 +94,63 @@ class BuildBase extends Model public $columns = array( 'id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'primary_key' => true, 'auto_increment' => true, 'default' => null, - ), + ), 'project_id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'default' => null, - ), + ), 'commit_id' => array( 'type' => 'varchar', - 'length' => '50', + 'length' => 50, 'nullable' => true, 'default' => null, - ), + ), 'status' => array( 'type' => 'tinyint', - 'length' => '4', - 'default' => '0', - ), + 'length' => 4, + ), 'log' => array( 'type' => 'longtext', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'branch' => array( 'type' => 'varchar', - 'length' => '50', + 'length' => 50, 'default' => 'master', - ), + ), 'created' => array( 'type' => 'datetime', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'started' => array( 'type' => 'datetime', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'finished' => array( 'type' => 'datetime', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'plugins' => array( 'type' => 'text', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'committer_email' => array( 'type' => 'varchar', - 'length' => '512', + 'length' => 512, 'nullable' => true, 'default' => null, - ), - ); + ), + ); /** * @var array @@ -158,7 +159,7 @@ class BuildBase extends Model 'PRIMARY' => array('unique' => true, 'columns' => 'id'), 'project_id' => array('columns' => 'project_id'), 'idx_status' => array('columns' => 'status'), - ); + ); /** * @var array @@ -171,8 +172,7 @@ class BuildBase extends Model 'table' => 'project', 'col' => 'id' ), - ); - + ); /** * Get the value of Id / id. @@ -183,7 +183,6 @@ class BuildBase extends Model { $rtn = $this->data['id']; - return $rtn; } @@ -196,7 +195,6 @@ class BuildBase extends Model { $rtn = $this->data['project_id']; - return $rtn; } @@ -209,7 +207,6 @@ class BuildBase extends Model { $rtn = $this->data['commit_id']; - return $rtn; } @@ -222,7 +219,6 @@ class BuildBase extends Model { $rtn = $this->data['status']; - return $rtn; } @@ -235,7 +231,6 @@ class BuildBase extends Model { $rtn = $this->data['log']; - return $rtn; } @@ -248,7 +243,6 @@ class BuildBase extends Model { $rtn = $this->data['branch']; - return $rtn; } @@ -261,11 +255,9 @@ class BuildBase extends Model { $rtn = $this->data['created']; - if (!empty($rtn)) { $rtn = new \DateTime($rtn); } - return $rtn; } @@ -279,11 +271,9 @@ class BuildBase extends Model { $rtn = $this->data['started']; - if (!empty($rtn)) { $rtn = new \DateTime($rtn); } - return $rtn; } @@ -297,11 +287,9 @@ class BuildBase extends Model { $rtn = $this->data['finished']; - if (!empty($rtn)) { $rtn = new \DateTime($rtn); } - return $rtn; } @@ -315,7 +303,6 @@ class BuildBase extends Model { $rtn = $this->data['plugins']; - return $rtn; } @@ -328,7 +315,6 @@ class BuildBase extends Model { $rtn = $this->data['committer_email']; - return $rtn; } @@ -342,6 +328,7 @@ class BuildBase extends Model { $this->_validateNotNull('Id', $value); $this->_validateInt('Id', $value); + if ($this->data['id'] === $value) { return; } @@ -361,6 +348,7 @@ class BuildBase extends Model { $this->_validateNotNull('ProjectId', $value); $this->_validateInt('ProjectId', $value); + if ($this->data['project_id'] === $value) { return; } @@ -377,8 +365,8 @@ class BuildBase extends Model */ public function setCommitId($value) { - $this->_validateString('CommitId', $value); + if ($this->data['commit_id'] === $value) { return; } @@ -398,6 +386,7 @@ class BuildBase extends Model { $this->_validateNotNull('Status', $value); $this->_validateInt('Status', $value); + if ($this->data['status'] === $value) { return; } @@ -414,8 +403,8 @@ class BuildBase extends Model */ public function setLog($value) { - $this->_validateString('Log', $value); + if ($this->data['log'] === $value) { return; } @@ -435,6 +424,7 @@ class BuildBase extends Model { $this->_validateNotNull('Branch', $value); $this->_validateString('Branch', $value); + if ($this->data['branch'] === $value) { return; } @@ -451,8 +441,8 @@ class BuildBase extends Model */ public function setCreated($value) { - $this->_validateDate('Created', $value); + if ($this->data['created'] === $value) { return; } @@ -469,8 +459,8 @@ class BuildBase extends Model */ public function setStarted($value) { - $this->_validateDate('Started', $value); + if ($this->data['started'] === $value) { return; } @@ -487,8 +477,8 @@ class BuildBase extends Model */ public function setFinished($value) { - $this->_validateDate('Finished', $value); + if ($this->data['finished'] === $value) { return; } @@ -505,8 +495,8 @@ class BuildBase extends Model */ public function setPlugins($value) { - $this->_validateString('Plugins', $value); + if ($this->data['plugins'] === $value) { return; } @@ -523,8 +513,8 @@ class BuildBase extends Model */ public function setCommitterEmail($value) { - $this->_validateString('CommitterEmail', $value); + if ($this->data['committer_email'] === $value) { return; } @@ -553,7 +543,7 @@ class BuildBase extends Model $rtn = $this->cache->get($cacheKey, null); if (empty($rtn)) { - $rtn = \b8\Store\Factory::getStore('Project')->getById($key); + $rtn = Factory::getStore('Project')->getById($key); $this->cache->set($cacheKey, $rtn); } @@ -600,6 +590,6 @@ class BuildBase extends Model */ public function getBuildBuildMetas() { - return \b8\Store\Factory::getStore('BuildMeta')->getByBuildId($this->getId()); + return Factory::getStore('BuildMeta')->getByBuildId($this->getId()); } } diff --git a/PHPCI/Model/Base/BuildMetaBase.php b/PHPCI/Model/Base/BuildMetaBase.php index 939c66fd..9ef0f457 100644 --- a/PHPCI/Model/Base/BuildMetaBase.php +++ b/PHPCI/Model/Base/BuildMetaBase.php @@ -7,6 +7,7 @@ namespace PHPCI\Model\Base; use b8\Model; +use b8\Store\Factory; /** * BuildMeta Base Model @@ -37,31 +38,37 @@ class BuildMetaBase extends Model 'build_id' => null, 'meta_key' => null, 'meta_value' => null, - ); + ); /** * @var array */ protected $getters = array( + // Direct property getters: 'id' => 'getId', 'project_id' => 'getProjectId', 'build_id' => 'getBuildId', 'meta_key' => 'getMetaKey', 'meta_value' => 'getMetaValue', + + // Foreign key getters: 'Build' => 'getBuild', - ); + ); /** * @var array */ protected $setters = array( + // Direct property setters: 'id' => 'setId', 'project_id' => 'setProjectId', 'build_id' => 'setBuildId', 'meta_key' => 'setMetaKey', 'meta_value' => 'setMetaValue', + + // Foreign key setters: 'Build' => 'setBuild', - ); + ); /** * @var array @@ -69,34 +76,32 @@ class BuildMetaBase extends Model public $columns = array( 'id' => array( 'type' => 'int', - 'length' => '10', + 'length' => 10, 'primary_key' => true, 'auto_increment' => true, 'default' => null, - ), + ), 'project_id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'default' => null, - ), + ), 'build_id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'nullable' => true, 'default' => null, - ), + ), 'meta_key' => array( 'type' => 'varchar', - 'length' => '255', - 'default' => '', - ), + 'length' => 255, + ), 'meta_value' => array( 'type' => 'text', - 'length' => '', 'nullable' => true, 'default' => null, - ), - ); + ), + ); /** * @var array @@ -104,7 +109,7 @@ class BuildMetaBase extends Model public $indexes = array( 'PRIMARY' => array('unique' => true, 'columns' => 'id'), 'idx_meta_id' => array('unique' => true, 'columns' => 'build_id, meta_key'), - ); + ); /** * @var array @@ -117,8 +122,7 @@ class BuildMetaBase extends Model 'table' => 'build', 'col' => 'id' ), - ); - + ); /** * Get the value of Id / id. @@ -129,7 +133,6 @@ class BuildMetaBase extends Model { $rtn = $this->data['id']; - return $rtn; } @@ -142,7 +145,6 @@ class BuildMetaBase extends Model { $rtn = $this->data['project_id']; - return $rtn; } @@ -155,7 +157,6 @@ class BuildMetaBase extends Model { $rtn = $this->data['build_id']; - return $rtn; } @@ -168,7 +169,6 @@ class BuildMetaBase extends Model { $rtn = $this->data['meta_key']; - return $rtn; } @@ -181,7 +181,6 @@ class BuildMetaBase extends Model { $rtn = $this->data['meta_value']; - return $rtn; } @@ -195,6 +194,7 @@ class BuildMetaBase extends Model { $this->_validateNotNull('Id', $value); $this->_validateInt('Id', $value); + if ($this->data['id'] === $value) { return; } @@ -214,6 +214,7 @@ class BuildMetaBase extends Model { $this->_validateNotNull('ProjectId', $value); $this->_validateInt('ProjectId', $value); + if ($this->data['project_id'] === $value) { return; } @@ -230,8 +231,8 @@ class BuildMetaBase extends Model */ public function setBuildId($value) { - $this->_validateInt('BuildId', $value); + if ($this->data['build_id'] === $value) { return; } @@ -251,6 +252,7 @@ class BuildMetaBase extends Model { $this->_validateNotNull('MetaKey', $value); $this->_validateString('MetaKey', $value); + if ($this->data['meta_key'] === $value) { return; } @@ -267,8 +269,8 @@ class BuildMetaBase extends Model */ public function setMetaValue($value) { - $this->_validateString('MetaValue', $value); + if ($this->data['meta_value'] === $value) { return; } @@ -297,7 +299,7 @@ class BuildMetaBase extends Model $rtn = $this->cache->get($cacheKey, null); if (empty($rtn)) { - $rtn = \b8\Store\Factory::getStore('Build')->getById($key); + $rtn = Factory::getStore('Build')->getById($key); $this->cache->set($cacheKey, $rtn); } diff --git a/PHPCI/Model/Base/ProjectBase.php b/PHPCI/Model/Base/ProjectBase.php index 6fc1a422..f23e1d7f 100644 --- a/PHPCI/Model/Base/ProjectBase.php +++ b/PHPCI/Model/Base/ProjectBase.php @@ -7,6 +7,7 @@ namespace PHPCI\Model\Base; use b8\Model; +use b8\Store\Factory; /** * Project Base Model @@ -39,12 +40,13 @@ class ProjectBase extends Model 'type' => null, 'token' => null, 'access_information' => null, - ); + ); /** * @var array */ protected $getters = array( + // Direct property getters: 'id' => 'getId', 'title' => 'getTitle', 'reference' => 'getReference', @@ -52,12 +54,15 @@ class ProjectBase extends Model 'type' => 'getType', 'token' => 'getToken', 'access_information' => 'getAccessInformation', - ); + + // Foreign key getters: + ); /** * @var array */ protected $setters = array( + // Direct property setters: 'id' => 'setId', 'title' => 'setTitle', 'reference' => 'setReference', @@ -65,7 +70,9 @@ class ProjectBase extends Model 'type' => 'setType', 'token' => 'setToken', 'access_information' => 'setAccessInformation', - ); + + // Foreign key setters: + ); /** * @var array @@ -73,59 +80,56 @@ class ProjectBase extends Model public $columns = array( 'id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'primary_key' => true, 'auto_increment' => true, 'default' => null, - ), + ), 'title' => array( 'type' => 'varchar', - 'length' => '250', - 'default' => '', - ), + 'length' => 250, + ), 'reference' => array( 'type' => 'varchar', - 'length' => '250', - 'default' => '', - ), + 'length' => 250, + ), 'git_key' => array( 'type' => 'text', - 'length' => '', 'nullable' => true, 'default' => null, - ), + ), 'type' => array( 'type' => 'varchar', - 'length' => '50', - 'default' => '1', - ), + 'length' => 50, + 'default' => 1, + ), 'token' => array( 'type' => 'varchar', - 'length' => '50', + 'length' => 50, 'nullable' => true, 'default' => null, - ), + ), 'access_information' => array( 'type' => 'varchar', - 'length' => '250', + 'length' => 250, 'nullable' => true, 'default' => null, - ), - ); + ), + ); /** * @var array */ public $indexes = array( 'PRIMARY' => array('unique' => true, 'columns' => 'id'), - ); + 'idx_project_title' => array('columns' => 'title'), + ); /** * @var array */ public $foreignKeys = array( - ); - + ); /** * Get the value of Id / id. @@ -136,7 +140,6 @@ class ProjectBase extends Model { $rtn = $this->data['id']; - return $rtn; } @@ -149,7 +152,6 @@ class ProjectBase extends Model { $rtn = $this->data['title']; - return $rtn; } @@ -162,7 +164,6 @@ class ProjectBase extends Model { $rtn = $this->data['reference']; - return $rtn; } @@ -175,7 +176,6 @@ class ProjectBase extends Model { $rtn = $this->data['git_key']; - return $rtn; } @@ -188,7 +188,6 @@ class ProjectBase extends Model { $rtn = $this->data['type']; - return $rtn; } @@ -201,7 +200,6 @@ class ProjectBase extends Model { $rtn = $this->data['token']; - return $rtn; } @@ -214,7 +212,6 @@ class ProjectBase extends Model { $rtn = $this->data['access_information']; - return $rtn; } @@ -228,6 +225,7 @@ class ProjectBase extends Model { $this->_validateNotNull('Id', $value); $this->_validateInt('Id', $value); + if ($this->data['id'] === $value) { return; } @@ -247,6 +245,7 @@ class ProjectBase extends Model { $this->_validateNotNull('Title', $value); $this->_validateString('Title', $value); + if ($this->data['title'] === $value) { return; } @@ -266,6 +265,7 @@ class ProjectBase extends Model { $this->_validateNotNull('Reference', $value); $this->_validateString('Reference', $value); + if ($this->data['reference'] === $value) { return; } @@ -282,8 +282,8 @@ class ProjectBase extends Model */ public function setGitKey($value) { - $this->_validateString('GitKey', $value); + if ($this->data['git_key'] === $value) { return; } @@ -303,6 +303,7 @@ class ProjectBase extends Model { $this->_validateNotNull('Type', $value); $this->_validateString('Type', $value); + if ($this->data['type'] === $value) { return; } @@ -319,8 +320,8 @@ class ProjectBase extends Model */ public function setToken($value) { - $this->_validateString('Token', $value); + if ($this->data['token'] === $value) { return; } @@ -337,8 +338,8 @@ class ProjectBase extends Model */ public function setAccessInformation($value) { - $this->_validateString('AccessInformation', $value); + if ($this->data['access_information'] === $value) { return; } @@ -357,6 +358,6 @@ class ProjectBase extends Model */ public function getProjectBuilds() { - return \b8\Store\Factory::getStore('Build')->getByProjectId($this->getId()); + return Factory::getStore('Build')->getByProjectId($this->getId()); } } diff --git a/PHPCI/Model/Base/UserBase.php b/PHPCI/Model/Base/UserBase.php index 8fad4ea1..e8035660 100644 --- a/PHPCI/Model/Base/UserBase.php +++ b/PHPCI/Model/Base/UserBase.php @@ -7,6 +7,7 @@ namespace PHPCI\Model\Base; use b8\Model; +use b8\Store\Factory; /** * User Base Model @@ -37,29 +38,35 @@ class UserBase extends Model 'hash' => null, 'is_admin' => null, 'name' => null, - ); + ); /** * @var array */ protected $getters = array( + // Direct property getters: 'id' => 'getId', 'email' => 'getEmail', 'hash' => 'getHash', 'is_admin' => 'getIsAdmin', 'name' => 'getName', - ); + + // Foreign key getters: + ); /** * @var array */ protected $setters = array( + // Direct property setters: 'id' => 'setId', 'email' => 'setEmail', 'hash' => 'setHash', 'is_admin' => 'setIsAdmin', 'name' => 'setName', - ); + + // Foreign key setters: + ); /** * @var array @@ -67,33 +74,30 @@ class UserBase extends Model public $columns = array( 'id' => array( 'type' => 'int', - 'length' => '11', + 'length' => 11, 'primary_key' => true, 'auto_increment' => true, 'default' => null, - ), + ), 'email' => array( 'type' => 'varchar', - 'length' => '250', - 'default' => '', - ), + 'length' => 250, + ), 'hash' => array( 'type' => 'varchar', - 'length' => '250', - 'default' => '', - ), + 'length' => 250, + ), 'is_admin' => array( 'type' => 'tinyint', - 'length' => '1', - 'default' => '0', - ), + 'length' => 1, + ), 'name' => array( 'type' => 'varchar', - 'length' => '250', + 'length' => 250, 'nullable' => true, 'default' => null, - ), - ); + ), + ); /** * @var array @@ -101,14 +105,13 @@ class UserBase extends Model public $indexes = array( 'PRIMARY' => array('unique' => true, 'columns' => 'id'), 'idx_email' => array('unique' => true, 'columns' => 'email'), - ); + ); /** * @var array */ public $foreignKeys = array( - ); - + ); /** * Get the value of Id / id. @@ -119,7 +122,6 @@ class UserBase extends Model { $rtn = $this->data['id']; - return $rtn; } @@ -132,7 +134,6 @@ class UserBase extends Model { $rtn = $this->data['email']; - return $rtn; } @@ -145,7 +146,6 @@ class UserBase extends Model { $rtn = $this->data['hash']; - return $rtn; } @@ -158,7 +158,6 @@ class UserBase extends Model { $rtn = $this->data['is_admin']; - return $rtn; } @@ -171,7 +170,6 @@ class UserBase extends Model { $rtn = $this->data['name']; - return $rtn; } @@ -185,6 +183,7 @@ class UserBase extends Model { $this->_validateNotNull('Id', $value); $this->_validateInt('Id', $value); + if ($this->data['id'] === $value) { return; } @@ -204,6 +203,7 @@ class UserBase extends Model { $this->_validateNotNull('Email', $value); $this->_validateString('Email', $value); + if ($this->data['email'] === $value) { return; } @@ -223,6 +223,7 @@ class UserBase extends Model { $this->_validateNotNull('Hash', $value); $this->_validateString('Hash', $value); + if ($this->data['hash'] === $value) { return; } @@ -242,6 +243,7 @@ class UserBase extends Model { $this->_validateNotNull('IsAdmin', $value); $this->_validateInt('IsAdmin', $value); + if ($this->data['is_admin'] === $value) { return; } @@ -258,8 +260,8 @@ class UserBase extends Model */ public function setName($value) { - $this->_validateString('Name', $value); + if ($this->data['name'] === $value) { return; } diff --git a/PHPCI/Model/Build.php b/PHPCI/Model/Build.php index e60ff64e..bc814560 100644 --- a/PHPCI/Model/Build.php +++ b/PHPCI/Model/Build.php @@ -9,8 +9,8 @@ namespace PHPCI\Model; +use b8\Store\Factory; use PHPCI\Model\Base\BuildBase; -use PHPCI\Builder; /** * Build Model @@ -21,6 +21,11 @@ use PHPCI\Builder; */ class Build extends BuildBase { + const STATUS_NEW = 0; + const STATUS_RUNNING = 1; + const STATUS_SUCCESS = 2; + const STATUS_FAILED = 3; + /** * Get link to commit from another source (i.e. Github) */ @@ -46,9 +51,19 @@ class Build extends BuildBase } /** - * Create a working copy by cloning, copying, or similar. - */ - public function createWorkingCopy(Builder $builder, $buildPath) + * Store build metadata + */ + public function storeMeta($key, $value) { + $value = json_encode($value); + Factory::getStore('Build')->setMeta($this->getProjectId(), $this->getId(), $key, $value); + } + + /** + * Is this build successful? + */ + public function isSuccessful() + { + return ($this->getStatus() === self::STATUS_SUCCESS); } } diff --git a/PHPCI/Model/Build/LocalBuild.php b/PHPCI/Model/Build/LocalBuild.php index 07698d42..6804f437 100644 --- a/PHPCI/Model/Build/LocalBuild.php +++ b/PHPCI/Model/Build/LocalBuild.php @@ -29,44 +29,68 @@ class LocalBuild extends Build $reference = $this->getProject()->getReference(); $reference = substr($reference, -1) == '/' ? substr($reference, 0, -1) : $reference; $buildPath = substr($buildPath, 0, -1); - $yamlParser = new YamlParser(); - - if(is_file($reference.'/config')) { - //We're probably looing at a bare repository. We'll open the config and check - $gitConfig = parse_ini_file($reference.'/config',TRUE); - if($gitConfig["core"]["bare"]) { - // Looks like we're right. We need to extract the archive! - $guid = uniqid(); - $builder->executeCommand('mkdir "/tmp/%s" && git --git-dir="%s" archive master | tar -x -C "/tmp/%s"', $guid, $reference, $guid); - $reference = '/tmp/'.$guid; - } + + // If there's a /config file in the reference directory, it is probably a bare repository + // which we'll extract into our build path directly. + if(is_file($reference.'/config') && $this->handleBareRepository($builder, $reference, $buildPath) === true) { + return true; } - if (!is_file($reference . '/phpci.yml')) { - $builder->logFailure('Project does not contain a phpci.yml file.'); + $buildSettings = $this->handleConfig($builder, $reference); + + if ($buildSettings === false) { return false; } - $yamlFile = file_get_contents($reference . '/phpci.yml'); - $builder->setConfigArray($yamlParser->parse($yamlFile)); - - $buildSettings = $builder->getConfig('build_settings'); - if (isset($buildSettings['prefer_symlink']) && $buildSettings['prefer_symlink'] === true) { - if (is_link($buildPath) && is_file($buildPath)) { - unlink($buildPath); - } - - $builder->log(sprintf('Symlinking: %s to %s', $reference, $buildPath)); - - if (!symlink($reference, $buildPath)) { - $builder->logFailure('Failed to symlink.'); - return false; - } + return $this->handleSymlink($builder, $reference, $buildPath); } else { $builder->executeCommand('cp -Rf "%s" "%s/"', $reference, $buildPath); } return true; } + + protected function handleBareRepository(Builder $builder, $reference, $buildPath) + { + $gitConfig = parse_ini_file($reference.'/config', true); + + // If it is indeed a bare repository, then extract it into our build path: + if($gitConfig['core']['bare']) { + $builder->executeCommand('git --git-dir="%s" archive master | tar -x -C "%s"', $reference, $buildPath); + return true; + } + + return false; + } + + protected function handleSymlink(Builder $builder, $reference, $buildPath) + { + if (is_link($buildPath) && is_file($buildPath)) { + unlink($buildPath); + } + + $builder->log(sprintf('Symlinking: %s to %s', $reference, $buildPath)); + + if (!symlink($reference, $buildPath)) { + $builder->logFailure('Failed to symlink.'); + return false; + } + + return true; + } + + protected function handleConfig(Builder $builder, $reference) + { + /** @todo Add support for database-based yml definition */ + if (!is_file($reference . '/phpci.yml')) { + $builder->logFailure('Project does not contain a phpci.yml file.'); + return false; + } + + $yamlParser = new YamlParser(); + $yamlFile = file_get_contents($reference . '/phpci.yml'); + $builder->setConfigArray($yamlParser->parse($yamlFile)); + return $builder->getConfig('build_settings'); + } } diff --git a/PHPCI/Model/Build/MercurialBuild.php b/PHPCI/Model/Build/MercurialBuild.php index de95c06b..dbfcf4e2 100644 --- a/PHPCI/Model/Build/MercurialBuild.php +++ b/PHPCI/Model/Build/MercurialBuild.php @@ -52,8 +52,8 @@ class MercurialBuild extends Build /** * Use an mercurial clone. */ - protected function cloneByHttp(Builder $builder, $to) + protected function cloneByHttp(Builder $builder, $cloneTo) { - return $builder->executeCommand('hg clone %s "%s" -r %s', $this->getCloneUrl(), $to, $this->getBranch()); + return $builder->executeCommand('hg clone %s "%s" -r %s', $this->getCloneUrl(), $cloneTo, $this->getBranch()); } } diff --git a/PHPCI/Model/Build/RemoteGitBuild.php b/PHPCI/Model/Build/RemoteGitBuild.php index 490b92ef..c4b03d2c 100644 --- a/PHPCI/Model/Build/RemoteGitBuild.php +++ b/PHPCI/Model/Build/RemoteGitBuild.php @@ -63,21 +63,21 @@ class RemoteGitBuild extends Build /** * Use an HTTP-based git clone. */ - protected function cloneByHttp(Builder $builder, $to) + protected function cloneByHttp(Builder $builder, $cloneTo) { - return $builder->executeCommand('git clone -b %s %s "%s"', $this->getBranch(), $this->getCloneUrl(), $to); + return $builder->executeCommand('git clone -b %s %s "%s"', $this->getBranch(), $this->getCloneUrl(), $cloneTo); } /** * Use an SSH-based git clone. */ - protected function cloneBySsh(Builder $builder, $to) + protected function cloneBySsh(Builder $builder, $cloneTo) { // Copy the project's keyfile to disk: - $keyPath = realpath($to); + $keyPath = realpath($cloneTo); if ($keyPath === false) { - $keyPath = dirname($to); + $keyPath = dirname($cloneTo); } $keyFile = $keyPath . '.key'; @@ -87,7 +87,7 @@ class RemoteGitBuild extends Build // Use the key file to do an SSH clone: $cmd = 'eval `ssh-agent -s` && ssh-add "%s" && git clone -b %s %s "%s" && ssh-agent -k'; - $success = $builder->executeCommand($cmd, $keyFile, $this->getBranch(), $this->getCloneUrl(), $to); + $success = $builder->executeCommand($cmd, $keyFile, $this->getBranch(), $this->getCloneUrl(), $cloneTo); // Remove the key file: unlink($keyFile); diff --git a/PHPCI/Plugin.php b/PHPCI/Plugin.php index 5aa06e9e..a924b39a 100644 --- a/PHPCI/Plugin.php +++ b/PHPCI/Plugin.php @@ -9,12 +9,15 @@ namespace PHPCI; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHPCI Plugin Interface - Used by all build plugins. * @author Dan Cryer */ interface Plugin { - public function __construct(\PHPCI\Builder $phpci, array $options = array()); + public function __construct(Builder $phpci, Build $build, array $options = array()); public function execute(); } diff --git a/PHPCI/Plugin/Atoum.php b/PHPCI/Plugin/Atoum.php index 80dce4c3..7a837b0a 100644 --- a/PHPCI/Plugin/Atoum.php +++ b/PHPCI/Plugin/Atoum.php @@ -2,15 +2,19 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + class Atoum implements \PHPCI\Plugin { private $args; private $config; private $directory; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; if (isset($options['executable'])) { $this->executable = $this->phpci->buildPath . DIRECTORY_SEPARATOR.$options['executable']; @@ -50,7 +54,7 @@ class Atoum implements \PHPCI\Plugin $status = true; exec($cmd, $output); - if (count(preg_grep("/Success \(/", $output)) == 0 ) { + if (count(preg_grep("/Success \(/", $output)) == 0) { $status = false; $this->phpci->log($output, ' '); } diff --git a/PHPCI/Plugin/Behat.php b/PHPCI/Plugin/Behat.php index c9c832ce..704d76cf 100644 --- a/PHPCI/Plugin/Behat.php +++ b/PHPCI/Plugin/Behat.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Behat BDD Plugin * @author Dan Cryer @@ -18,10 +21,16 @@ namespace PHPCI\Plugin; class Behat implements \PHPCI\Plugin { protected $phpci; + protected $features; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->features = ''; + + if (!empty($options['features'])) { + $this->features = $options['features']; + } } /** @@ -32,14 +41,14 @@ class Behat implements \PHPCI\Plugin $curdir = getcwd(); chdir($this->phpci->buildPath); - $phpspec = $this->phpci->findBinary('phpspec'); + $behat = $this->phpci->findBinary('behat'); - if (!$phpspec) { - $this->phpci->logFailure('Could not find phpspec.'); + if (!$behat) { + $this->phpci->logFailure('Could not find behat.'); return false; } - $success = $this->phpci->executeCommand($phpspec); + $success = $this->phpci->executeCommand($behat . ' --no-time --format="failed" %s', $this->features); chdir($curdir); return $success; diff --git a/PHPCI/Plugin/Campfire.php b/PHPCI/Plugin/Campfire.php index f3dfced2..17b7f077 100644 --- a/PHPCI/Plugin/Campfire.php +++ b/PHPCI/Plugin/Campfire.php @@ -1,6 +1,10 @@ phpci = $phpci; + $this->build = $build; $this->message = $options['message']; - $this->userAgent = "Phpci/1.0 (http://www.phptesting.org/)"; + $this->userAgent = "PHPCI/1.0 (+http://www.phptesting.org/)"; $this->cookie = "phpcicookie"; $buildSettings = $phpci->getConfig('build_settings'); @@ -36,14 +37,14 @@ class Campfire implements \PHPCI\Plugin $this->authToken = $campfire['authToken']; $this->roomId = $campfire['roomId']; } else { - throw new \Exception("No connexion parameters given for Campfire plugin"); + throw new \Exception("No connection parameters given for Campfire plugin"); } } public function execute() { - $url = PHPCI_URL."build/view/".$this->phpci->getBuild()->getId(); + $url = PHPCI_URL."build/view/".$this->build->getId(); $message = str_replace("%buildurl%", $url, $this->message); $this->joinRoom($this->roomId); $status = $this->speak($message, $this->roomId); @@ -52,19 +53,15 @@ class Campfire implements \PHPCI\Plugin return $status; } + public function joinRoom($roomId) { - $this->_getPageByPost('/room/'.$roomId.'/join.json'); + $this->getPageByPost('/room/'.$roomId.'/join.json'); } public function leaveRoom($roomId) { - $this->_getPageByPost('/room/'.$roomId.'/leave.json'); - } - - public function logout() - { - // New API is stateless, no concept of logout + $this->getPageByPost('/room/'.$roomId.'/leave.json'); } public function speak($message, $roomId, $isPaste = false) @@ -76,12 +73,11 @@ class Campfire implements \PHPCI\Plugin $type = 'TextMessage'; } - return $this->_getPageByPost($page, - array('message' => array('type' => $type, 'body' => $message))); + return $this->getPageByPost($page, array('message' => array('type' => $type, 'body' => $message))); } - private function _getPageByPost($page, $data = null) + private function getPageByPost($page, $data = null) { $url = $this->url . $page; // The new API allows JSON, so we can pass @@ -89,21 +85,21 @@ class Campfire implements \PHPCI\Plugin $json = json_encode($data); // cURL init & config - $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); - curl_setopt($ch, CURLOPT_POST, 1); - curl_setopt($ch, CURLOPT_USERAGENT, $this->userAgent); - curl_setopt($ch, CURLOPT_VERBOSE, $this->verbose); - curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); - curl_setopt($ch, CURLOPT_USERPWD, $this->authToken . ':x'); - curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-type: application/json")); - curl_setopt($ch, CURLOPT_COOKIEFILE, $this->cookie); + $handle = curl_init(); + curl_setopt($handle, CURLOPT_URL, $url); + curl_setopt($handle, CURLOPT_RETURNTRANSFER, true); + curl_setopt($handle, CURLOPT_POST, 1); + curl_setopt($handle, CURLOPT_USERAGENT, $this->userAgent); + curl_setopt($handle, CURLOPT_VERBOSE, $this->verbose); + curl_setopt($handle, CURLOPT_FOLLOWLOCATION, 1); + curl_setopt($handle, CURLOPT_USERPWD, $this->authToken . ':x'); + curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-type: application/json")); + curl_setopt($handle, CURLOPT_COOKIEFILE, $this->cookie); - curl_setopt($ch, CURLOPT_POSTFIELDS, $json); - $output = curl_exec($ch); + curl_setopt($handle, CURLOPT_POSTFIELDS, $json); + $output = curl_exec($handle); - curl_close($ch); + curl_close($handle); // We tend to get one space with an otherwise blank response $output = trim($output); diff --git a/PHPCI/Plugin/CleanBuild.php b/PHPCI/Plugin/CleanBuild.php index a9709d8a..bfe96761 100644 --- a/PHPCI/Plugin/CleanBuild.php +++ b/PHPCI/Plugin/CleanBuild.php @@ -9,6 +9,8 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * Clean build removes Composer related files and allows PHPCI users to clean up their build directory. * Useful as a precursor to copy_build. @@ -21,9 +23,8 @@ class CleanBuild implements \PHPCI\Plugin protected $remove; protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $path = $phpci->buildPath; $this->phpci = $phpci; $this->remove = isset($options['remove']) && is_array($options['remove']) ? $options['remove'] : array(); } diff --git a/PHPCI/Plugin/Codeception.php b/PHPCI/Plugin/Codeception.php index 827facf1..f2e580c7 100644 --- a/PHPCI/Plugin/Codeception.php +++ b/PHPCI/Plugin/Codeception.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Codeception Plugin - Enables full acceptance, unit, and functional testing. * @author Don Gilbert @@ -25,7 +28,7 @@ class Codeception implements \PHPCI\Plugin */ protected $xmlConfigFile; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; @@ -81,4 +84,4 @@ class Codeception implements \PHPCI\Plugin } return $success; } -} \ No newline at end of file +} diff --git a/PHPCI/Plugin/Composer.php b/PHPCI/Plugin/Composer.php index ff1cbce4..1af4abf6 100644 --- a/PHPCI/Plugin/Composer.php +++ b/PHPCI/Plugin/Composer.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Composer Plugin - Provides access to Composer functionality. * @author Dan Cryer @@ -22,7 +25,7 @@ class Composer implements \PHPCI\Plugin protected $preferDist; protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; $this->phpci = $phpci; @@ -43,7 +46,8 @@ class Composer implements \PHPCI\Plugin return false; } - $cmd = $composerLocation . ' --no-ansi --no-interaction '. ($this->preferDist ? '--prefer-dist' : null) .' --working-dir="%s" %s'; + $cmd = $composerLocation . ' --no-ansi --no-interaction '; + $cmd .= ($this->preferDist ? '--prefer-dist' : null) . ' --working-dir="%s" %s'; return $this->phpci->executeCommand($cmd, $this->directory, $this->action); } diff --git a/PHPCI/Plugin/CopyBuild.php b/PHPCI/Plugin/CopyBuild.php index 15a5d56a..1ba06558 100644 --- a/PHPCI/Plugin/CopyBuild.php +++ b/PHPCI/Plugin/CopyBuild.php @@ -9,6 +9,8 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * Copy Build Plugin - Copies the entire build to another directory. * @author Dan Cryer @@ -20,7 +22,7 @@ class CopyBuild implements \PHPCI\Plugin protected $directory; protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; $this->phpci = $phpci; diff --git a/PHPCI/Plugin/Email.php b/PHPCI/Plugin/Email.php index 5e94cd8b..7b80d795 100644 --- a/PHPCI/Plugin/Email.php +++ b/PHPCI/Plugin/Email.php @@ -9,6 +9,8 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * Email Plugin - Provides simple email capability to PHPCI. @@ -18,7 +20,6 @@ namespace PHPCI\Plugin; */ class Email implements \PHPCI\Plugin { - /** * @var \PHPCI\Builder */ @@ -39,23 +40,15 @@ class Email implements \PHPCI\Plugin */ protected $mailer; - public function __construct(\PHPCI\Builder $phpci, - array $options = array(), - \Swift_Mailer $mailer = null) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $phpCiSettings = $phpci->getSystemConfig('phpci'); $this->phpci = $phpci; + $this->build = $build; $this->options = $options; $this->emailConfig = isset($phpCiSettings['email_settings']) ? $phpCiSettings['email_settings'] : array(); - // Either a mailer will have been passed in or we load from the - // config. - if ($mailer === null) { - $this->loadSwiftMailerFromConfig(); - } - else { - $this->mailer = $mailer; - } + $this->loadSwiftMailerFromConfig(); } /** @@ -71,20 +64,17 @@ class Email implements \PHPCI\Plugin return false; } - $sendFailures = array(); - $subjectTemplate = "PHPCI - %s - %s"; $projectName = $this->phpci->getBuildProjectTitle(); - $logText = $this->phpci->getBuild()->getLog(); + $logText = $this->build->getLog(); - if($this->phpci->getSuccessStatus()) { + if ($this->build->isSuccessful()) { $sendFailures = $this->sendSeparateEmails( $addresses, sprintf($subjectTemplate, $projectName, "Passing Build"), sprintf("Log Output:
%s
", $logText) ); - } - else { + } else { $sendFailures = $this->sendSeparateEmails( $addresses, sprintf($subjectTemplate, $projectName, "Failing Build"), @@ -93,14 +83,9 @@ class Email implements \PHPCI\Plugin } // This is a success if we've not failed to send anything. - $this->phpci->log(sprintf( - "%d emails sent", - (count($addresses) - count($sendFailures))) - ); - $this->phpci->log(sprintf( - "%d emails failed to send", - count($sendFailures)) - ); + $this->phpci->log(sprintf("%d emails sent", (count($addresses) - count($sendFailures)))); + $this->phpci->log(sprintf("%d emails failed to send", count($sendFailures))); + return (count($sendFailures) == 0); } @@ -126,9 +111,9 @@ class Email implements \PHPCI\Plugin public function sendSeparateEmails(array $toAddresses, $subject, $body) { $failures = array(); - foreach($toAddresses as $address) { + foreach ($toAddresses as $address) { $newFailures = $this->sendEmail($address, $subject, $body); - foreach($newFailures as $failure) { + foreach ($newFailures as $failure) { $failures[] = $failure; } } @@ -151,13 +136,11 @@ class Email implements \PHPCI\Plugin protected function getMailConfig($configName) { - if (isset($this->emailConfig[$configName]) - && $this->emailConfig[$configName] != "") - { + if (isset($this->emailConfig[$configName]) && $this->emailConfig[$configName] != "") { return $this->emailConfig[$configName]; - } - // Check defaults - else { + } else { + // Check defaults + switch($configName) { case 'smtp_address': return "localhost"; @@ -178,7 +161,7 @@ class Email implements \PHPCI\Plugin protected function getEmailAddresses() { $addresses = array(); - $committer = $this->phpci->getBuild()->getCommitterEmail(); + $committer = $this->build->getCommitterEmail(); if (isset($this->options['committer']) && !empty($committer)) { $addresses[] = $committer; @@ -196,4 +179,4 @@ class Email implements \PHPCI\Plugin } return $addresses; } -} \ No newline at end of file +} diff --git a/PHPCI/Plugin/Env.php b/PHPCI/Plugin/Env.php index e09d3dbf..09ffbb5a 100644 --- a/PHPCI/Plugin/Env.php +++ b/PHPCI/Plugin/Env.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Environment variable plugin * @author Steve Kamerman @@ -20,7 +23,7 @@ class Env implements \PHPCI\Plugin protected $phpci; protected $env_vars; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->env_vars = $options; diff --git a/PHPCI/Plugin/Grunt.php b/PHPCI/Plugin/Grunt.php index ca024276..477a4849 100644 --- a/PHPCI/Plugin/Grunt.php +++ b/PHPCI/Plugin/Grunt.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Grunt Plugin - Provides access to grunt functionality. * @author Tobias Tom @@ -24,14 +27,31 @@ class Grunt implements \PHPCI\Plugin protected $grunt; protected $gruntfile; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $path = $phpci->buildPath; - $this->phpci = $phpci; - $this->directory = isset($options['directory']) ? $path . '/' . $options['directory'] : $path; - $this->task = isset($options['task']) ? $options['task'] : null; - $this->grunt = isset($options['grunt']) ? $options['grunt'] : $this->phpci->findBinary('grunt'); - $this->gruntfile = isset($options['gruntfile']) ? $options['gruntfile'] : 'Gruntfile.js'; + $path = $phpci->buildPath; + $this->phpci = $phpci; + $this->directory = $path; + $this->task = null; + $this->grunt = $this->phpci->findBinary('grunt'); + $this->gruntfile = 'Gruntfile.js'; + + // Handle options: + if (isset($options['directory'])) { + $this->directory = $path . '/' . $options['directory']; + } + + if (isset($options['task'])) { + $this->task = $options['task']; + } + + if (isset($options['grunt'])) { + $this->grunt = $options['grunt']; + } + + if (isset($options['gruntfile'])) { + $this->gruntfile = $options['gruntfile']; + } } /** @@ -40,7 +60,7 @@ class Grunt implements \PHPCI\Plugin public function execute() { // if npm does not work, we cannot use grunt, so we return false - if ( !$this->phpci->executeCommand( 'cd %s && npm install', $this->directory ) ) { + if (!$this->phpci->executeCommand('cd %s && npm install', $this->directory)) { return false; } diff --git a/PHPCI/Plugin/Irc.php b/PHPCI/Plugin/Irc.php index 64e8f523..a4a3310b 100644 --- a/PHPCI/Plugin/Irc.php +++ b/PHPCI/Plugin/Irc.php @@ -1,6 +1,10 @@ @@ -16,8 +20,7 @@ class Irc implements \PHPCI\Plugin private $room; private $nick; - - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->message = $options['message']; @@ -53,7 +56,9 @@ class Irc implements \PHPCI\Plugin fputs($sock, 'PRIVMSG ' . $this->room . ' :' . $msg . "\r\n"); while ($res = fgets($sock)) { - $this->phpci->log($res); + // We don't need to do anything, + // but the IRC server doesn't appear to post the message + // unless we wait for responses. } fclose($sock); diff --git a/PHPCI/Plugin/Lint.php b/PHPCI/Plugin/Lint.php index c8c1b880..ebab146e 100644 --- a/PHPCI/Plugin/Lint.php +++ b/PHPCI/Plugin/Lint.php @@ -11,6 +11,7 @@ namespace PHPCI\Plugin; use PHPCI\Builder; use PHPCI\Model\Build; + /** * PHP Lint Plugin - Provides access to PHP lint functionality. * @author Dan Cryer @@ -24,7 +25,7 @@ class Lint implements \PHPCI\Plugin protected $ignore; protected $phpci; - public function __construct(Builder $phpci, Build $build, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->directories = array(''); @@ -64,6 +65,19 @@ class Lint implements \PHPCI\Plugin return $success; } + protected function lintItem($php, $item, $itemPath) + { + $success = true; + + if ($item->isFile() && $item->getExtension() == 'php' && !$this->lintFile($php, $itemPath)) { + $success = false; + } elseif ($item->isDir() && $this->recursive && !$this->lintDirectory($php, $itemPath . '/')) { + $success = false; + } + + return $success; + } + protected function lintDirectory($php, $path) { $success = true; @@ -80,9 +94,7 @@ class Lint implements \PHPCI\Plugin continue; } - if ($item->isFile() && $item->getExtension() == 'php' && !$this->lintFile($php, $itemPath)) { - $success = false; - } else if ($item->isDir() && $this->recursive && !$this->lintDirectory($php, $itemPath . '/')) { + if (!$this->lintItem($php, $item, $itemPath)) { $success = false; } } diff --git a/PHPCI/Plugin/Mysql.php b/PHPCI/Plugin/Mysql.php index e6ac7d54..e2fda714 100755 --- a/PHPCI/Plugin/Mysql.php +++ b/PHPCI/Plugin/Mysql.php @@ -10,6 +10,8 @@ namespace PHPCI\Plugin; use PDO; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * MySQL Plugin - Provides access to a MySQL database. @@ -37,24 +39,33 @@ class Mysql implements \PHPCI\Plugin */ protected $pdo; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; - $this->queries = $options; + $this->phpci = $phpci; + $this->queries = $options; - $config = \b8\Database::getConnection('write')->getDetails(); + $config = \b8\Database::getConnection('write')->getDetails(); $this->host =(defined('PHPCI_DB_HOST')) ? PHPCI_DB_HOST : null; $this->user = $config['user']; $this->pass = $config['pass']; $buildSettings = $phpci->getConfig('build_settings'); - if (isset($buildSettings['mysql'])) { - $sql = $buildSettings['mysql']; - $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; + if (!isset($buildSettings['mysql'])) { + return; + } + + if (!empty($buildSettings['mysql']['host'])) { + $this->host = $this->phpci->interpolate($buildSettings['mysql']['host']); + } + + if (!empty($buildSettings['mysql']['user'])) { + $this->user = $this->phpci->interpolate($buildSettings['mysql']['user']); + } + + if (array_key_exists('pass', $buildSettings['mysql'])) { + $this->pass = $buildSettings['mysql']['pass']; } } @@ -73,7 +84,7 @@ class Mysql implements \PHPCI\Plugin if (!is_array($query)) { // Simple query $this->pdo->query($this->phpci->interpolate($query)); - } else if (isset($query['import'])) { + } elseif (isset($query['import'])) { // SQL file execution $this->executeFile($query['import']); } else { @@ -96,15 +107,15 @@ class Mysql implements \PHPCI\Plugin $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"); + throw new \Exception("Cannot open SQL import file: $import_file"); } - $database = isset($query['database'])? $this->phpci->interpolate($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)) { - throw new \Exception("Unable to execute SQL file"); - } + if (!$this->phpci->executeCommand($import_command)) { + throw new \Exception("Unable to execute SQL file"); + } return true; } @@ -115,7 +126,8 @@ class Mysql implements \PHPCI\Plugin * @param string $database If specified, this database is selected before execution * @return string */ - protected function getImportCommand($import_file, $database=null) { + protected function getImportCommand($import_file, $database = null) + { $decompression = array( 'bz2' => '| bzip2 --decompress', 'gz' => '| gzip --decompress', @@ -136,4 +148,4 @@ class Mysql implements \PHPCI\Plugin ); return strtr('cat :import_file :decomp_cmd | mysql -u:user -p:pass :database', $args); } -} \ No newline at end of file +} diff --git a/PHPCI/Plugin/PackageBuild.php b/PHPCI/Plugin/PackageBuild.php index 333de105..d2332ed3 100644 --- a/PHPCI/Plugin/PackageBuild.php +++ b/PHPCI/Plugin/PackageBuild.php @@ -9,6 +9,8 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * Create a ZIP or TAR.GZ archive of the entire build. * @author Dan Cryer @@ -22,9 +24,10 @@ class PackageBuild implements \PHPCI\Plugin protected $format; protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; + $this->build = $build; $this->phpci = $phpci; $this->directory = isset($options['directory']) ? $options['directory'] : $path; $this->filename = isset($options['filename']) ? $options['filename'] : 'build'; @@ -37,7 +40,7 @@ class PackageBuild implements \PHPCI\Plugin public function execute() { $path = $this->phpci->buildPath; - $build = $this->phpci->getBuild(); + $build = $this->build; if ($this->directory == $path) { return false; diff --git a/PHPCI/Plugin/Pdepend.php b/PHPCI/Plugin/Pdepend.php index bb2fdea2..70b5e530 100644 --- a/PHPCI/Plugin/Pdepend.php +++ b/PHPCI/Plugin/Pdepend.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Pdepend Plugin - Allows Pdepend report * @author Johan van der Heide @@ -44,16 +47,17 @@ class Pdepend implements \PHPCI\Plugin */ protected $location; - - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; $this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath; - $this->summary = $phpci->getBuildProjectTitle() . '-summary.xml'; - $this->pyramid = $phpci->getBuildProjectTitle() . '-pyramid.svg'; - $this->chart = $phpci->getBuildProjectTitle() . '-chart.svg'; + $title = $phpci->getBuildProjectTitle(); + $this->summary = $title . '-summary.xml'; + $this->pyramid = $title . '-pyramid.svg'; + $this->chart = $title . '-chart.svg'; $this->location = $this->phpci->buildPath . '..' . DIRECTORY_SEPARATOR . 'pdepend'; } diff --git a/PHPCI/Plugin/Pgsql.php b/PHPCI/Plugin/Pgsql.php index e746dd72..45155ecf 100644 --- a/PHPCI/Plugin/Pgsql.php +++ b/PHPCI/Plugin/Pgsql.php @@ -10,6 +10,8 @@ namespace PHPCI\Plugin; use PDO; +use PHPCI\Builder; +use PHPCI\Model\Build; /** * PgSQL Plugin - Provides access to a PgSQL database. @@ -26,7 +28,7 @@ class Pgsql implements \PHPCI\Plugin protected $user; protected $pass; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->queries = $options; diff --git a/PHPCI/Plugin/PhpCodeSniffer.php b/PHPCI/Plugin/PhpCodeSniffer.php index 98d0c603..44fa5893 100755 --- a/PHPCI/Plugin/PhpCodeSniffer.php +++ b/PHPCI/Plugin/PhpCodeSniffer.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Code Sniffer Plugin - Allows PHP Code Sniffer testing. * @author Dan Cryer @@ -62,22 +65,88 @@ class PhpCodeSniffer implements \PHPCI\Plugin * @param \PHPCI\Builder $phpci * @param array $options */ - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; - $this->suffixes = isset($options['suffixes']) ? (array)$options['suffixes'] : array('php'); - $this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath; - $this->standard = isset($options['standard']) ? $options['standard'] : 'PSR2'; - $this->tab_width = isset($options['tab_width']) ? $options['tab_width'] : ''; - $this->encoding = isset($options['encoding']) ? $options['encoding'] : ''; - $this->path = (isset($options['path'])) ? $options['path'] : ''; - $this->ignore = (isset($options['ignore'])) ? (array)$options['ignore'] : $this->phpci->ignore; + $this->build = $build; + $this->suffixes = array('php'); + $this->directory = $phpci->buildPath; + $this->standard = 'PSR2'; + $this->tab_width = ''; + $this->encoding = ''; + $this->path = ''; + $this->ignore = $this->phpci->ignore; + + if (isset($options['suffixes'])) { + $this->suffixes = (array)$options['suffixes']; + } + + if (isset($options['directory'])) { + $this->directory = $options['directory']; + } + + if (isset($options['standard'])) { + $this->standard = $options['standard']; + } + + if (!empty($options['tab_width'])) { + $this->tab_width = ' --tab-width='.$options['tab_width']; + } + + if (!empty($options['encoding'])) { + $this->encoding = ' --encoding=' . $options['encoding']; + } + + if (isset($options['path'])) { + $this->path = $options['path']; + } + + if (isset($options['ignore'])) { + $this->ignore = $options['ignore']; + } } /** * Runs PHP Code Sniffer in a specified directory, to a specified standard. */ public function execute() + { + list($ignore, $standard, $suffixes) = $this->getFlags(); + + $phpcs = $this->phpci->findBinary('phpcs'); + + if (!$phpcs) { + $this->phpci->logFailure('Could not find phpcs.'); + return false; + } + + $cmd = $phpcs . ' %s %s %s %s %s "%s"'; + $success = $this->phpci->executeCommand( + $cmd, + $standard, + $suffixes, + $ignore, + $this->tab_width, + $this->encoding, + $this->phpci->buildPath . $this->path + ); + + $output = $this->phpci->getLastOutput(); + + $matches = array(); + if (preg_match_all('/WARNING/', $output, $matches)) { + $this->build->storeMeta('phpcs-warnings', count($matches[0])); + } + + $matches = array(); + if (preg_match_all('/ERROR/', $output, $matches)) { + $this->build->storeMeta('phpcs-errors', count($matches[0])); + } + + return $success; + } + + protected function getFlags() { $ignore = ''; if (count($this->ignore)) { @@ -95,38 +164,6 @@ class PhpCodeSniffer implements \PHPCI\Plugin $suffixes = ' --extensions=' . implode(',', $this->suffixes); } - $tab_width = ''; - if (strlen($this->tab_width)) { - $tab_width = ' --tab-width='.$this->tab_width; - } - - $encoding = ''; - if (strlen($this->encoding)) { - $encoding = ' --encoding='.$this->encoding; - } - - $phpcs = $this->phpci->findBinary('phpcs'); - - if (!$phpcs) { - $this->phpci->logFailure('Could not find phpcs.'); - return false; - } - - $cmd = $phpcs . ' %s %s %s %s %s "%s"'; - $success = $this->phpci->executeCommand($cmd, $standard, $suffixes, $ignore, $tab_width, $encoding, $this->phpci->buildPath . $this->path); - - $output = $this->phpci->getLastOutput(); - - $matches = array(); - if (preg_match_all('/WARNING/', $output, $matches)) { - $this->phpci->storeBuildMeta('phpcs-warnings', count($matches[0])); - } - - $matches = array(); - if (preg_match_all('/ERROR/', $output, $matches)) { - $this->phpci->storeBuildMeta('phpcs-errors', count($matches[0])); - } - - return $success; + return array($ignore, $standard, $suffixes); } } diff --git a/PHPCI/Plugin/PhpCpd.php b/PHPCI/Plugin/PhpCpd.php index 5764258f..816bf261 100755 --- a/PHPCI/Plugin/PhpCpd.php +++ b/PHPCI/Plugin/PhpCpd.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Copy / Paste Detector - Allows PHP Copy / Paste Detector testing. * @author Dan Cryer @@ -32,14 +35,24 @@ class PhpCpd implements \PHPCI\Plugin */ protected $ignore; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { - $this->phpci = $phpci; - $this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath; - $this->standard = isset($options['standard']) ? $options['standard'] : 'PSR2'; - $this->path = (isset($options['path'])) ? $options['path'] : ''; - $this->ignore = (isset($options['ignore'])) ? (array)$options['ignore'] : $this->phpci->ignore; + $this->phpci = $phpci; + $this->path = $phpci->buildPath; + $this->standard = 'PSR1'; + $this->ignore = $phpci->ignore; + if (!empty($options['path'])) { + $this->path = $phpci->buildPath . $options['path']; + } + + if (!empty($options['standard'])) { + $this->standard = $options['standard']; + } + + if (!empty($options['ignore'])) { + $this->ignore = $this->phpci->ignore; + } } /** diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php index 6c42fcb8..ca07e9ef 100644 --- a/PHPCI/Plugin/PhpCsFixer.php +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP CS Fixer - Works with the PHP CS Fixer for testing coding standards. * @author Gabriel Baker @@ -19,16 +22,13 @@ class PhpCsFixer implements \PHPCI\Plugin { protected $phpci; - protected $args = ''; - protected $workingDir = ''; - protected $level = 'all'; - protected $dryRun = true; - protected $verbose = false; - protected $diff = false; + protected $level = ' --level=all'; + protected $verbose = ''; + protected $diff = ''; protected $levels = array('psr0', 'psr1', 'psr2', 'all'); - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; $this->workingdir = $this->phpci->buildPath; @@ -37,8 +37,6 @@ class PhpCsFixer implements \PHPCI\Plugin public function execute() { - $success = false; - $curdir = getcwd(); chdir($this->workingdir); @@ -49,8 +47,8 @@ class PhpCsFixer implements \PHPCI\Plugin return false; } - $cmd = $phpcsfixer . ' fix . %s'; - $success = $this->phpci->executeCommand($cmd, $this->args); + $cmd = $phpcsfixer . ' fix . %s %s %s'; + $success = $this->phpci->executeCommand($cmd, $this->verbose, $this->diff, $this->level); chdir($curdir); @@ -59,38 +57,21 @@ class PhpCsFixer implements \PHPCI\Plugin public function buildArgs($options) { - $argstring = ""; - - if ( array_key_exists('verbose', $options) && $options['verbose'] ) - { - $this->verbose = true; - $this->args .= ' --verbose'; + if (isset($options['verbose']) && $options['verbose']) { + $this->verbose = ' --verbose'; } - if ( array_key_exists('diff', $options) && $options['diff'] ) - { - $this->diff = true; - $this->args .= ' --diff'; + if (isset($options['diff']) && $options['diff']) { + $this->diff = ' --diff'; } - if ( array_key_exists('level', $options) && in_array($options['level'], $this->levels) ) - { - $this->level = $options['level']; - $this->args .= ' --level='.$options['level']; + if (isset($options['level']) && in_array($options['level'], $this->levels)) { + $this->level = ' --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']; + if (isset($options['workingdir']) && $options['workingdir']) { + $this->workingdir = $this->phpci->buildPath . $options['workingdir']; } } -} \ No newline at end of file +} diff --git a/PHPCI/Plugin/PhpLoc.php b/PHPCI/Plugin/PhpLoc.php index 6742de2b..809b6409 100644 --- a/PHPCI/Plugin/PhpLoc.php +++ b/PHPCI/Plugin/PhpLoc.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Loc - Allows PHP Copy / Lines of Code testing. * @author Johan van der Heide @@ -26,9 +29,10 @@ class PhpLoc implements \PHPCI\Plugin */ protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; $this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath; } @@ -63,9 +67,9 @@ class PhpLoc implements \PHPCI\Plugin $data[$v] = (int)$matches[2][$k]; } - $this->phpci->storeBuildMeta('phploc', $data); + $this->build->storeMeta('phploc', $data); } return $success; } -} \ No newline at end of file +} diff --git a/PHPCI/Plugin/PhpMessDetector.php b/PHPCI/Plugin/PhpMessDetector.php index f1743b8d..c6291a6e 100755 --- a/PHPCI/Plugin/PhpMessDetector.php +++ b/PHPCI/Plugin/PhpMessDetector.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Mess Detector Plugin - Allows PHP Mess Detector testing. * @author Dan Cryer @@ -49,21 +52,21 @@ class PhpMessDetector implements \PHPCI\Plugin * @param \PHPCI\Builder $phpci * @param array $options */ - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + $this->build = $build; + $this->suffixes = array('php'); + $this->ignore = $phpci->ignore; + $this->path = ''; + $this->rules = array('codesize', 'unusedcode', 'naming'); - $this->suffixes = isset($options['suffixes']) ? (array)$options['suffixes'] : array('php'); + if (!empty($options['path'])) { + $this->path = $options['path']; + } - $this->ignore = (isset($options['ignore'])) ? (array)$options['ignore'] : $this->phpci->ignore; - - $this->path = (isset($options['path'])) ? $options['path'] : ''; - - $this->rules = isset($options['rules']) ? (array)$options['rules'] : array('codesize', 'unusedcode', 'naming'); - foreach ($this->rules as &$rule) { - if ($rule[0] !== '/' && strpos($rule, '/') !== FALSE) { - $rule = $this->phpci->buildPath . $rule; - } + foreach (array('rules', 'ignore', 'suffixes') as $key) { + $this->overrideSetting($options, $key); } } @@ -82,6 +85,12 @@ class PhpMessDetector implements \PHPCI\Plugin $suffixes = ' --suffixes ' . implode(',', $this->suffixes); } + foreach ($this->rules as &$rule) { + if ($rule[0] !== '/' && strpos($rule, '/') !== false) { + $rule = $this->phpci->buildPath . $rule; + } + } + $phpmd = $this->phpci->findBinary('phpmd'); if (!$phpmd) { @@ -90,10 +99,24 @@ class PhpMessDetector implements \PHPCI\Plugin } $cmd = $phpmd . ' "%s" text %s %s %s'; - $success = $this->phpci->executeCommand($cmd, $this->phpci->buildPath . $this->path, implode(',', $this->rules), $ignore, $suffixes); + $success = $this->phpci->executeCommand( + $cmd, + $this->phpci->buildPath . $this->path, + implode(',', $this->rules), + $ignore, + $suffixes + ); + $errors = count(array_filter(explode(PHP_EOL, $this->phpci->getLastOutput()))); - $this->phpci->storeBuildMeta('phpmd-warnings', $errors); + $this->build->storeMeta('phpmd-warnings', $errors); return $success; } + + protected function overrideSetting($options, $key) + { + if (isset($options[$key]) && is_array($options['key'])) { + $this->{$key} = $options[$key]; + } + } } diff --git a/PHPCI/Plugin/PhpParallelLint.php b/PHPCI/Plugin/PhpParallelLint.php index dc880a5c..b7a8cd24 100644 --- a/PHPCI/Plugin/PhpParallelLint.php +++ b/PHPCI/Plugin/PhpParallelLint.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Php Parallel Lint Plugin - Provides access to PHP lint functionality. * @author Vaclav Makes @@ -21,7 +24,7 @@ class PhpParallelLint implements \PHPCI\Plugin protected $preferDist; protected $phpci; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $path = $phpci->buildPath; $this->phpci = $phpci; diff --git a/PHPCI/Plugin/PhpSpec.php b/PHPCI/Plugin/PhpSpec.php index fbe981cc..afd36699 100644 --- a/PHPCI/Plugin/PhpSpec.php +++ b/PHPCI/Plugin/PhpSpec.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Spec Plugin - Allows PHP Spec testing. * @author Dan Cryer @@ -18,10 +21,15 @@ namespace PHPCI\Plugin; class PhpSpec implements \PHPCI\Plugin { protected $phpci; + protected $bootstrap; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; + + if (!empty($options['bootstrap'])) { + $this->bootstrap = $this->buildPath . $options['bootstrap']; + } } /** @@ -32,14 +40,19 @@ class PhpSpec implements \PHPCI\Plugin $curdir = getcwd(); chdir($this->phpci->buildPath); - $phpspec = $this->phpci->findBinary('phpspec'); + $phpspec = $this->phpci->findBinary(array('phpspec', 'phpspec.php')); if (!$phpspec) { $this->phpci->logFailure('Could not find phpspec.'); return false; } - $success = $this->phpci->executeCommand($phpspec); + if ($this->bootstrap) { + $success = $this->phpci->executeCommand($phpspec . ' -f d'); + } else { + $success = $this->phpci->executeCommand($phpspec . ' -f d --bootstrap "%s"', $this->bootstrap); + } + chdir($curdir); return $success; diff --git a/PHPCI/Plugin/PhpUnit.php b/PHPCI/Plugin/PhpUnit.php index dce241cf..9b905fb6 100755 --- a/PHPCI/Plugin/PhpUnit.php +++ b/PHPCI/Plugin/PhpUnit.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * PHP Unit Plugin - Allows PHP Unit testing. * @author Dan Cryer @@ -43,7 +46,7 @@ class PhpUnit implements \PHPCI\Plugin */ protected $xmlConfigFile; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; diff --git a/PHPCI/Plugin/Shell.php b/PHPCI/Plugin/Shell.php index 83595ad8..d86b6e1b 100644 --- a/PHPCI/Plugin/Shell.php +++ b/PHPCI/Plugin/Shell.php @@ -9,6 +9,9 @@ namespace PHPCI\Plugin; +use PHPCI\Builder; +use PHPCI\Model\Build; + /** * Shell Plugin - Allows execute shell commands. * @author Kinn Coelho JuliĆ£o @@ -25,7 +28,7 @@ class Shell implements \PHPCI\Plugin */ protected $command; - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(Builder $phpci, Build $build, array $options = array()) { $this->phpci = $phpci; diff --git a/PHPCI/Store/Base/BuildMetaStoreBase.php b/PHPCI/Store/Base/BuildMetaStoreBase.php index b96b3875..01bb6964 100644 --- a/PHPCI/Store/Base/BuildMetaStoreBase.php +++ b/PHPCI/Store/Base/BuildMetaStoreBase.php @@ -6,7 +6,10 @@ namespace PHPCI\Store\Base; +use b8\Database; +use b8\Exception\HttpException; use b8\Store; +use PHPCI\Model\BuildMeta; /** * BuildMeta Base Store @@ -22,21 +25,19 @@ class BuildMetaStoreBase extends Store return $this->getById($value, $useConnection); } - - public function getById($value, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $query = 'SELECT * FROM build_meta WHERE id = :id LIMIT 1'; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); if ($stmt->execute()) { if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { - return new \PHPCI\Model\BuildMeta($data); + return new BuildMeta($data); } } @@ -46,7 +47,7 @@ class BuildMetaStoreBase extends Store public function getByBuildId($value, $limit = null, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $add = ''; @@ -55,26 +56,17 @@ class BuildMetaStoreBase extends Store $add .= ' LIMIT ' . $limit; } - $query = 'SELECT COUNT(*) AS cnt FROM build_meta WHERE build_id = :build_id' . $add; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); - $stmt->bindValue(':build_id', $value); - - if ($stmt->execute()) { - $res = $stmt->fetch(\PDO::FETCH_ASSOC); - $count = (int)$res['cnt']; - } else { - $count = 0; - } + $count = null; $query = 'SELECT * FROM build_meta WHERE build_id = :build_id' . $add; - $stmt = \b8\Database::getConnection('read')->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':build_id', $value); if ($stmt->execute()) { $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); $map = function ($item) { - return new \PHPCI\Model\BuildMeta($item); + return new BuildMeta($item); }; $rtn = array_map($map, $res); diff --git a/PHPCI/Store/Base/BuildStoreBase.php b/PHPCI/Store/Base/BuildStoreBase.php index 89b3a4f9..f0e66085 100644 --- a/PHPCI/Store/Base/BuildStoreBase.php +++ b/PHPCI/Store/Base/BuildStoreBase.php @@ -6,7 +6,10 @@ namespace PHPCI\Store\Base; +use b8\Database; +use b8\Exception\HttpException; use b8\Store; +use PHPCI\Model\Build; /** * Build Base Store @@ -22,21 +25,19 @@ class BuildStoreBase extends Store return $this->getById($value, $useConnection); } - - public function getById($value, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $query = 'SELECT * FROM build WHERE id = :id LIMIT 1'; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); if ($stmt->execute()) { if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { - return new \PHPCI\Model\Build($data); + return new Build($data); } } @@ -46,7 +47,7 @@ class BuildStoreBase extends Store public function getByProjectId($value, $limit = null, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $add = ''; @@ -55,26 +56,17 @@ class BuildStoreBase extends Store $add .= ' LIMIT ' . $limit; } - $query = 'SELECT COUNT(*) AS cnt FROM build WHERE project_id = :project_id' . $add; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); - $stmt->bindValue(':project_id', $value); - - if ($stmt->execute()) { - $res = $stmt->fetch(\PDO::FETCH_ASSOC); - $count = (int)$res['cnt']; - } else { - $count = 0; - } + $count = null; $query = 'SELECT * FROM build WHERE project_id = :project_id' . $add; - $stmt = \b8\Database::getConnection('read')->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':project_id', $value); if ($stmt->execute()) { $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); $map = function ($item) { - return new \PHPCI\Model\Build($item); + return new Build($item); }; $rtn = array_map($map, $res); @@ -87,7 +79,7 @@ class BuildStoreBase extends Store public function getByStatus($value, $limit = null, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $add = ''; @@ -96,26 +88,17 @@ class BuildStoreBase extends Store $add .= ' LIMIT ' . $limit; } - $query = 'SELECT COUNT(*) AS cnt FROM build WHERE status = :status' . $add; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); - $stmt->bindValue(':status', $value); - - if ($stmt->execute()) { - $res = $stmt->fetch(\PDO::FETCH_ASSOC); - $count = (int)$res['cnt']; - } else { - $count = 0; - } + $count = null; $query = 'SELECT * FROM build WHERE status = :status' . $add; - $stmt = \b8\Database::getConnection('read')->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':status', $value); if ($stmt->execute()) { $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); $map = function ($item) { - return new \PHPCI\Model\Build($item); + return new Build($item); }; $rtn = array_map($map, $res); diff --git a/PHPCI/Store/Base/ProjectStoreBase.php b/PHPCI/Store/Base/ProjectStoreBase.php index 9a807373..8b78c055 100644 --- a/PHPCI/Store/Base/ProjectStoreBase.php +++ b/PHPCI/Store/Base/ProjectStoreBase.php @@ -6,7 +6,10 @@ namespace PHPCI\Store\Base; +use b8\Database; +use b8\Exception\HttpException; use b8\Store; +use PHPCI\Model\Project; /** * Project Base Store @@ -22,24 +25,54 @@ class ProjectStoreBase extends Store return $this->getById($value, $useConnection); } - - public function getById($value, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $query = 'SELECT * FROM project WHERE id = :id LIMIT 1'; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); if ($stmt->execute()) { if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { - return new \PHPCI\Model\Project($data); + return new Project($data); } } return null; } + + public function getByTitle($value, $limit = null, $useConnection = 'read') + { + if (is_null($value)) { + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + } + + $add = ''; + + if ($limit) { + $add .= ' LIMIT ' . $limit; + } + + $count = null; + + $query = 'SELECT * FROM project WHERE title = :title' . $add; + $stmt = Database::getConnection($useConnection)->prepare($query); + $stmt->bindValue(':title', $value); + + if ($stmt->execute()) { + $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + $map = function ($item) { + return new Project($item); + }; + $rtn = array_map($map, $res); + + return array('items' => $rtn, 'count' => $count); + } else { + return array('items' => array(), 'count' => 0); + } + } } diff --git a/PHPCI/Store/Base/UserStoreBase.php b/PHPCI/Store/Base/UserStoreBase.php index 49c0ed35..c4268804 100644 --- a/PHPCI/Store/Base/UserStoreBase.php +++ b/PHPCI/Store/Base/UserStoreBase.php @@ -6,7 +6,10 @@ namespace PHPCI\Store\Base; +use b8\Database; +use b8\Exception\HttpException; use b8\Store; +use PHPCI\Model\User; /** * User Base Store @@ -22,21 +25,19 @@ class UserStoreBase extends Store return $this->getById($value, $useConnection); } - - public function getById($value, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $query = 'SELECT * FROM user WHERE id = :id LIMIT 1'; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':id', $value); if ($stmt->execute()) { if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { - return new \PHPCI\Model\User($data); + return new User($data); } } @@ -46,16 +47,16 @@ class UserStoreBase extends Store public function getByEmail($value, $useConnection = 'read') { if (is_null($value)) { - throw new \b8\Exception\HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); + throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } $query = 'SELECT * FROM user WHERE email = :email LIMIT 1'; - $stmt = \b8\Database::getConnection($useConnection)->prepare($query); + $stmt = Database::getConnection($useConnection)->prepare($query); $stmt->bindValue(':email', $value); if ($stmt->execute()) { if ($data = $stmt->fetch(\PDO::FETCH_ASSOC)) { - return new \PHPCI\Model\User($data); + return new User($data); } } diff --git a/PHPCI/View/Home/index.phtml b/PHPCI/View/Home/index.phtml index 1e186694..452ec7c6 100644 --- a/PHPCI/View/Home/index.phtml +++ b/PHPCI/View/Home/index.phtml @@ -12,31 +12,8 @@
Projects
diff --git a/bootstrap.php b/bootstrap.php index 4db3815e..b84f6428 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -27,20 +27,22 @@ $autoload = function ($class) { spl_autoload_register($autoload, true, true); -// Define our APPLICATION_PATH, if not already defined: -if (!defined('APPLICATION_PATH')) { - define('APPLICATION_PATH', dirname(__FILE__) . '/'); -} -if (!file_exists(APPLICATION_PATH . 'PHPCI/config.yml')) { - header('Location: install.php'); - die; + +if (!file_exists(dirname(__FILE__) . '/PHPCI/config.yml')) { + if (defined('PHPCI_IS_CONSOLE') && PHPCI_IS_CONSOLE) { + file_put_contents('php://stderr', 'Please install PHPCI with "composer install" before using console'); + exit(1); + } else { + header('Location: install.php'); + die; + } } // Load Composer autoloader: -require_once(APPLICATION_PATH . 'vendor/autoload.php'); +require_once(dirname(__FILE__) . '/vendor/autoload.php'); // Load configuration if present: $conf = array(); @@ -49,9 +51,6 @@ $conf['b8']['app']['default_controller'] = 'Home'; $conf['b8']['view']['path'] = dirname(__FILE__) . '/PHPCI/View/'; $config = new b8\Config($conf); -$config->loadYaml(APPLICATION_PATH . 'PHPCI/config.yml'); +$config->loadYaml(dirname(__FILE__) . '/PHPCI/config.yml'); -// Define our PHPCI_URL, if not already defined: -if (!defined('PHPCI_URL')) { - define('PHPCI_URL', $config->get('phpci.url', '') . '/'); -} +require_once(dirname(__FILE__) . '/vars.php'); diff --git a/console b/console index dd44b13b..3a56e7cd 100755 --- a/console +++ b/console @@ -8,16 +8,7 @@ * @link http://www.phptesting.org/ */ -define('PHPCI_BIN_DIR', dirname(__FILE__) . '/vendor/bin/'); -define('PHPCI_DIR', dirname(__FILE__) . '/'); -define('ENABLE_SHELL_PLUGIN', false); - -// If this is the first time ./console has been run, we probably don't have Composer or any of our dependencies yet. -// So we need to install and run Composer. -if (!file_exists(PHPCI_DIR . 'vendor/autoload.php')) { - file_put_contents('php://stderr', 'Please install PHPCI with "composer install" before using console'); - exit( 1 ); -} +define('PHPCI_IS_CONSOLE', true); require('bootstrap.php'); diff --git a/daemonise b/daemonise index 63ac409a..0f1a6d1d 100755 --- a/daemonise +++ b/daemonise @@ -8,9 +8,7 @@ * @link http://www.phptesting.org/ */ -define('PHPCI_BIN_DIR', dirname(__FILE__) . '/vendor/bin/'); -define('PHPCI_DIR', dirname(__FILE__) . '/'); -define('ENABLE_SHELL_PLUGIN', false); +define('PHPCI_IS_CONSOLE', true); require('bootstrap.php'); diff --git a/phpci.yml b/phpci.yml index 90b34255..42b2dba3 100644 --- a/phpci.yml +++ b/phpci.yml @@ -2,27 +2,20 @@ build_settings: verbose: false ignore: - "vendor" - - "assets" - - "build" - "Tests" - - "composer.phar" + - "PHPCI/Command" # PHPMD complains about un-used parameters, but they are required. + - "public/install.php" # PHPCS really doesn't like PHP mixed with HTML (and so it shouldn't) irc: server: "irc.freenode.net" port: 6667 room: "#phpci" nick: "phpcidev" -setup: - composer: - action: "install" - test: php_mess_detector: - allow_failures: true php_code_sniffer: standard: "PSR2" php_loc: - allow_failures: true success: irc: diff --git a/public/index.php b/public/index.php index e1754b62..134e9a7b 100644 --- a/public/index.php +++ b/public/index.php @@ -16,4 +16,3 @@ require_once('../bootstrap.php'); $fc = new PHPCI\Application($config, new b8\Http\Request()); print $fc->handleRequest(); - diff --git a/public/install.php b/public/install.php index 8003d353..e08e647e 100644 --- a/public/install.php +++ b/public/install.php @@ -1,15 +1,10 @@ -

Important! You need to run composer to install dependencies before running the installer.

+

+ Important! + You need to run composer to install dependencies before running the installer. +

-

Important! ./PHPCI/config.yml needs to be writeable to continue.

+

+ Important! + ./PHPCI/config.yml needs to be writeable to continue. +

@@ -391,30 +401,3 @@ switch ($installStage) { - -get('phpci.url', '') . '/'); +} + +// Define PHPCI_BIN_DIR +if (!defined('PHPCI_BIN_DIR')) { + define('PHPCI_BIN_DIR', PHPCI_DIR . 'vendor/bin/'); +} + +// Should PHPCI run the Shell plugin? +if (!defined('ENABLE_SHELL_PLUGIN')) { + define('ENABLE_SHELL_PLUGIN', false); +} + +// If this is not already defined, we're not running in the console: +if (!defined('PHPCI_IS_CONSOLE')) { + define('PHPCI_IS_CONSOLE', false); +} \ No newline at end of file