Holy cleanup, batman.

This commit is contained in:
Dan Cryer 2013-10-10 01:01:06 +01:00
parent 4cbfc06022
commit 77fae9a56d
58 changed files with 976 additions and 856 deletions

View file

@ -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 = '<h1>There was a problem with this request</h1><p>Please paste the details below into a <a href="https://github.com/Block8/PHPCI/issues/new">new bug report</a> so that we can investigate and fix it.</p>';
$content = '<h1>There was a problem with this request</h1>
<p>Please paste the details below into a
<a href="https://github.com/Block8/PHPCI/issues/new">new bug report</a>
so that we can investigate and fix it.</p>';
ob_start();
var_dump(array(

View file

@ -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;
}
/**

View file

@ -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";
}

View file

@ -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');

View file

@ -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();
}

View file

@ -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;
}

View file

@ -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();

View file

@ -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;
}
}
return $this->response;
}
}

View file

@ -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());

View file

@ -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']));
}

View file

@ -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;
};
}
}

View file

@ -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

View file

@ -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());
}
}

View file

@ -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);
}

View file

@ -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());
}
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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');
}
}

View file

@ -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());
}
}

View file

@ -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);

View file

@ -9,12 +9,15 @@
namespace PHPCI;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* PHPCI Plugin Interface - Used by all build plugins.
* @author Dan Cryer <dan@block8.co.uk>
*/
interface Plugin
{
public function __construct(\PHPCI\Builder $phpci, array $options = array());
public function __construct(Builder $phpci, Build $build, array $options = array());
public function execute();
}

View file

@ -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, ' ');
}

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Behat BDD Plugin
* @author Dan Cryer <dan@block8.co.uk>
@ -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;

View file

@ -1,6 +1,10 @@
<?php
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Campfire Plugin - Allows Campfire API actions.
* strongly based on icecube (http://labs.mimmin.com/icecube)
@ -10,10 +14,6 @@ namespace PHPCI\Plugin;
*/
class Campfire implements \PHPCI\Plugin
{
private $args;
private $config;
private $directory;
private $url;
private $authToken;
private $userAgent;
@ -21,12 +21,13 @@ class Campfire implements \PHPCI\Plugin
private $verbose;
private $roomId;
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->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);

View file

@ -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();
}

View file

@ -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 <don@dongilbert.net>
@ -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;
}
}
}

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Composer Plugin - Provides access to Composer functionality.
* @author Dan Cryer <dan@block8.co.uk>
@ -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);
}

View file

@ -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 <dan@block8.co.uk>
@ -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;

View file

@ -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: <br><pre>%s</pre>", $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;
}
}
}

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Environment variable plugin
* @author Steve Kamerman <stevekamerman@gmail.com>
@ -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;

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Grunt Plugin - Provides access to grunt functionality.
* @author Tobias Tom <t.tom@succont.de>
@ -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;
}

View file

@ -1,6 +1,10 @@
<?php
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* IRC Plugin - Sends a notification to an IRC channel
* @author Dan Cryer <dan@block8.co.uk>
@ -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);

View file

@ -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 <dan@block8.co.uk>
@ -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;
}
}

View file

@ -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);
}
}
}

View file

@ -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 <dan@block8.co.uk>
@ -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;

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* Pdepend Plugin - Allows Pdepend report
* @author Johan van der Heide <info@japaveh.nl>
@ -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';
}

View file

@ -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;

View file

@ -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 <dan@block8.co.uk>
@ -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);
}
}

View file

@ -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 <dan@block8.co.uk>
@ -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;
}
}
/**

View file

@ -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 <gabriel@autonomicpilot.co.uk>
@ -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'];
}
}
}
}

View file

@ -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 <info@japaveh.nl>
@ -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;
}
}
}

View file

@ -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 <dan@block8.co.uk>
@ -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];
}
}
}

View file

@ -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 <vaclav@makes.cz>
@ -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;

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* PHP Spec Plugin - Allows PHP Spec testing.
* @author Dan Cryer <dan@block8.co.uk>
@ -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;

View file

@ -9,6 +9,9 @@
namespace PHPCI\Plugin;
use PHPCI\Builder;
use PHPCI\Model\Build;
/**
* PHP Unit Plugin - Allows PHP Unit testing.
* @author Dan Cryer <dan@block8.co.uk>
@ -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;

View file

@ -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 <kinncj@gmail.com>
@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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);
}
}

View file

@ -12,31 +12,8 @@
<?php if (count($projects)): ?>
<h5>Projects</h5>
<ul class="nav nav-pills nav-stacked">
<?php
foreach($projects as $project):
$status = 'icon-build-ok';
$build = $project->getLatestBuild('master');
if (isset($build)) {
switch($build->getStatus())
{
case 0:
$status = 'icon-build-pending';
break;
case 1:
$status = 'icon-build-running';
break;
case 3:
$status = 'icon-build-failed';
break;
case 2:
default:
$status = 'icon-build-ok';
break;
}
}
?>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><i class="<?= $status; ?>"></i> <?php print $project->getTitle(); ?></a></li>
<?php foreach($projects as $project): ?>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><?php print $project->getTitle(); ?></a></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>

View file

@ -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');

11
console
View file

@ -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');

View file

@ -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');

View file

@ -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:

View file

@ -16,4 +16,3 @@ require_once('../bootstrap.php');
$fc = new PHPCI\Application($config, new b8\Http\Request());
print $fc->handleRequest();

View file

@ -1,15 +1,10 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 'On');
require_once(dirname(__FILE__) . '/../vars.php');
$installStage = 'start';
$formAction = '';
$config = array();
define('PHPCI_DIR', realpath('../') . '/');
$ciUrl = ($_SERVER['HTTPS'] == "on" ? 'https' : 'http') . '://';
$ciUrl .= $_SERVER['HTTP_HOST'];
$ciUrl .= str_replace('/install.php', '', $_SERVER['REQUEST_URI']);
@ -22,12 +17,37 @@ $composerInstalled = true;
$isWriteable = true;
$phpOK = true;
$checkWriteable = function ($path) {
if ($path{strlen($path)-1}=='/') {
return is__writable($path.uniqid(mt_rand()).'.tmp');
} elseif (is_dir($path)) {
return is__writable($path.'/'.uniqid(mt_rand()).'.tmp');
}
// check tmp file for read/write capabilities
$remove = file_exists($path);
$file = @fopen($path, 'a');
if ($file === false) {
return false;
}
fclose($file);
if (!$remove) {
unlink($path);
}
return true;
};
if (!file_exists(PHPCI_DIR . 'vendor/autoload.php')) {
$composerInstalled = false;
$installOK = false;
}
if (!is__writable(PHPCI_DIR . 'PHPCI/config.yml')) {
if (!$checkWriteable(PHPCI_DIR . 'PHPCI/config.yml')) {
$isWriteable = false;
$installOK = false;
}
@ -160,16 +180,8 @@ switch ($installStage) {
body
{
background: #224466; /* Old browsers */
background: -moz-radial-gradient(center, ellipse cover, #224466 0%, #112233 100%); /* FF3.6+ */
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,#224466), color-stop(100%,#112233)); /* Chrome,Safari4+ */
background: -webkit-radial-gradient(center, ellipse cover, #224466 0%,#112233 100%); /* Chrome10+,Safari5.1+ */
background: -o-radial-gradient(center, ellipse cover, #224466 0%,#112233 100%); /* Opera 12+ */
background: -ms-radial-gradient(center, ellipse cover, #224466 0%,#112233 100%); /* IE10+ */
background: radial-gradient(ellipse at center, #224466 0%,#112233 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#224466', endColorstr='#112233',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
background: radial-gradient(ellipse at center, #224466 0%,#112233 100%);
min-height: 100%;
font-family: Roboto, Arial, Sans-Serif;
font-style: normal;
font-weight: 300;
@ -178,15 +190,7 @@ switch ($installStage) {
#form-box
{
background: #fcfcfc; /* Old browsers */
background: -moz-linear-gradient(top, #fcfcfc 50%, #e0e0e0 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(50%,#fcfcfc), color-stop(100%,#e0e0e0)); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, #fcfcfc 50%,#e0e0e0 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, #fcfcfc 50%,#e0e0e0 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, #fcfcfc 50%,#e0e0e0 100%); /* IE10+ */
background: linear-gradient(to bottom, #fcfcfc 50%,#e0e0e0 100%); /* W3C */
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fcfcfc', endColorstr='#e0e0e0',GradientType=0 ); /* IE6-9 */
background: linear-gradient(to bottom, #fcfcfc 50%,#e0e0e0 100%);
border-radius: 5px;
box-shadow: 0 0 30px rgba(0,0,0, 0.3);
margin: 0 auto;
@ -235,12 +239,18 @@ switch ($installStage) {
<?php endif; ?>
<?php if (!$composerInstalled): ?>
<p class="alert alert-danger"><strong>Important!</strong> You need to run composer to install dependencies before running the installer.</p>
<p class="alert alert-danger">
<strong>Important!</strong>
You need to run composer to install dependencies before running the installer.
</p>
<?php endif; ?>
<?php if (!$isWriteable): ?>
<p class="alert alert-danger"><strong>Important!</strong> ./PHPCI/config.yml needs to be writeable to continue.</p>
<p class="alert alert-danger">
<strong>Important!</strong>
./PHPCI/config.yml needs to be writeable to continue.
</p>
<?php endif; ?>
<?php if (!$phpOK): ?>
@ -391,30 +401,3 @@ switch ($installStage) {
</div>
</body>
</html>
<?php
/** Supporting functions */
function is__writable($path) {
if ($path{strlen($path)-1}=='/') {
return is__writable($path.uniqid(mt_rand()).'.tmp');
} elseif (is_dir($path)) {
return is__writable($path.'/'.uniqid(mt_rand()).'.tmp');
}
// check tmp file for read/write capabilities
$rm = file_exists($path);
$f = @fopen($path, 'a');
if ($f === false) {
return false;
}
fclose($f);
if (!$rm) {
unlink($path);
}
return true;
}

27
vars.php Normal file
View file

@ -0,0 +1,27 @@
<?php
// Define our APPLICATION_PATH, if not already defined:
if (!defined('APPLICATION_PATH')) {
define('APPLICATION_PATH', dirname(__FILE__) . '/');
define('PHPCI_DIR', APPLICATION_PATH);
}
// Define our PHPCI_URL, if not already defined:
if (!defined('PHPCI_URL')) {
define('PHPCI_URL', $config->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);
}