Merge remote-tracking branch 'block8/master'

This commit is contained in:
Marc Aschmann 2014-08-05 13:44:32 +02:00
commit a5d5be1a8b
36 changed files with 1339 additions and 202 deletions

View file

@ -9,6 +9,7 @@
namespace PHPCI\Command;
use PHPCI\Service\UserService;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
@ -37,7 +38,9 @@ class CreateAdminCommand extends Command
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$userStore = Factory::getStore('User');
$userService = new UserService($userStore);
require(PHPCI_DIR . 'bootstrap.php');
// Try to create a user account:
@ -51,15 +54,7 @@ class CreateAdminCommand extends Command
$adminName = $this->ask('Admin name: ');
try {
$user = new \PHPCI\Model\User();
$user->setEmail($adminEmail);
$user->setName($adminName);
$user->setIsAdmin(1);
$user->setHash(password_hash($adminPass, PASSWORD_DEFAULT));
$store = \b8\Store\Factory::getStore('User');
$store->save($user);
$userService->createUser($adminName, $adminEmail, $adminPass, 1);
print 'User account created!' . PHP_EOL;
} catch (\Exception $ex) {
print 'There was a problem creating your account. :(' . PHP_EOL;

View file

@ -21,7 +21,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Helper\DialogHelper;
use PHPCI\Model\User;
use PHPCI\Service\UserService;
/**
@ -236,16 +236,11 @@ class InstallCommand extends Command
$adminName = $dialog->ask($output, 'Enter your name: ');
try {
$user = new User();
$user->setEmail($adminEmail);
$user->setName($adminName);
$user->setIsAdmin(1);
$user->setHash(password_hash($adminPass, PASSWORD_DEFAULT));
$this->reloadConfig();
$store = Factory::getStore('User');
$store->save($user);
$userStore = Factory::getStore('User');
$userService = new UserService($userStore);
$userService->createUser($adminName, $adminEmail, $adminPass, 1);
$output->writeln('<info>User account created!</info>');
} catch (\Exception $ex) {

View file

@ -13,6 +13,7 @@ use b8;
use b8\Exception\HttpException\NotFoundException;
use PHPCI\BuildFactory;
use PHPCI\Model\Build;
use PHPCI\Service\BuildService;
/**
* Build Controller - Allows users to run and view builds.
@ -26,10 +27,16 @@ class BuildController extends \PHPCI\Controller
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @var \PHPCI\Service\BuildService
*/
protected $buildService;
public function init()
{
$this->buildStore = b8\Store\Factory::getStore('Build');
$this->buildStore = b8\Store\Factory::getStore('Build');
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -123,17 +130,7 @@ class BuildController extends \PHPCI\Controller
throw new NotFoundException('Build with ID: ' . $buildId . ' does not exist.');
}
$build = new Build();
$build->setProjectId($copy->getProjectId());
$build->setCommitId($copy->getCommitId());
$build->setStatus(Build::STATUS_NEW);
$build->setBranch($copy->getBranch());
$build->setCreated(new \DateTime());
$build->setCommitterEmail($copy->getCommitterEmail());
$build->setCommitMessage($copy->getCommitMessage());
$build->setExtra(json_encode($copy->getExtra()));
$build = $this->buildStore->save($build);
$build = $this->buildService->createDuplicateBuild($copy);
header('Location: '.PHPCI_URL.'build/view/' . $build->getId());
exit;
@ -154,7 +151,7 @@ class BuildController extends \PHPCI\Controller
throw new NotFoundException('Build with ID: ' . $buildId . ' does not exist.');
}
$this->buildStore->delete($build);
$this->buildService->deleteBuild($build);
header('Location: '.PHPCI_URL.'project/view/' . $build->getProjectId());
exit;

View file

@ -20,6 +20,8 @@ use PHPCI\Helper\Github;
use PHPCI\Helper\SshKey;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\Service\BuildService;
use PHPCI\Service\ProjectService;
/**
* Project Controller - Allows users to create, edit and view projects.
@ -29,20 +31,32 @@ use PHPCI\Model\Project;
*/
class ProjectController extends \PHPCI\Controller
{
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @var \PHPCI\Service\ProjectService
*/
protected $projectService;
/**
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @var \PHPCI\Store\ProjectStore
* @var \PHPCI\Service\BuildService
*/
protected $projectStore;
protected $buildService;
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->projectService = new ProjectService($this->projectStore);
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -88,15 +102,7 @@ class ProjectController extends \PHPCI\Controller
throw new NotFoundException('Project with id: ' . $projectId . ' not found');
}
$build = new Build();
$build->setProjectId($projectId);
$build->setCommitId('Manual');
$build->setStatus(Build::STATUS_NEW);
$build->setBranch($project->getBranch());
$build->setCreated(new \DateTime());
$build->setCommitterEmail($_SESSION['user']->getEmail());
$build = $this->buildStore->save($build);
$build = $this->buildService->createBuild($project, null, null, $_SESSION['user']->getEmail());
header('Location: '.PHPCI_URL.'build/view/' . $build->getId());
exit;
@ -112,7 +118,7 @@ class ProjectController extends \PHPCI\Controller
}
$project = $this->projectStore->getById($projectId);
$this->projectStore->delete($project);
$this->projectService->deleteProject($project);
header('Location: '.PHPCI_URL);
exit;
@ -179,35 +185,24 @@ class ProjectController extends \PHPCI\Controller
return $view->render();
} else {
return $this->addProject($form);
$title = $this->getParam('title', 'New Project');
$reference = $this->getParam('reference', null);
$type = $this->getParam('type', null);
$options = array(
'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', 0),
'branch' => $this->getParam('branch', null),
);
$project = $this->projectService->createProject($title, $type, $reference, $options);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
}
}
protected function addProject(Form $form)
{
$values = $form->getValues();
$matches = array();
if ($values['type'] == "gitlab" && 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['ssh_private_key'] = $values['key'];
$values['ssh_public_key'] = $values['pubkey'];
$project = new Project();
$project->setValues($values);
$project = $this->projectStore->save($project);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
}
/**
* Edit a project. Handles both the form and processing.
*/
@ -252,21 +247,19 @@ class ProjectController extends \PHPCI\Controller
return $view->render();
}
$values = $form->getValues();
$values['ssh_private_key'] = $values['key'];
$values['ssh_public_key'] = $values['pubkey'];
$title = $this->getParam('title', 'New Project');
$reference = $this->getParam('reference', null);
$type = $this->getParam('type', null);
if ($values['type'] == "gitlab") {
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];
}
$options = array(
'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', 0),
'branch' => $this->getParam('branch', null),
);
$project->setValues($values);
$project = $this->projectStore->save($project);
$project = $this->projectService->updateProject($project, $title, $type, $reference, $options);
header('Location: '.PHPCI_URL.'project/view/' . $project->getId());
die;
@ -337,7 +330,7 @@ class ProjectController extends \PHPCI\Controller
$field = Form\Element\Checkbox::create('allow_public_status', $label, false);
$field->setContainerClass('form-group');
$field->setCheckedValue(1);
$field->setValue(1);
$field->setValue(0);
$form->addField($field);
$field = new Form\Element\Submit();

View file

@ -81,6 +81,8 @@ class SettingsController extends Controller
public function email()
{
$this->settings['phpci']['email_settings'] = $this->getParams();
$this->settings['phpci']['email_settings']['smtp_encryption'] = $this->getParam('smtp_encryption', 0);
$error = $this->storeSettings();
if ($error) {

View file

@ -15,6 +15,7 @@ use b8\Exception\HttpException\NotFoundException;
use b8\Form;
use PHPCI\Controller;
use PHPCI\Model\User;
use PHPCI\Service\UserService;
/**
* User Controller - Allows an administrator to view, add, edit and delete users.
@ -29,9 +30,15 @@ class UserController extends Controller
*/
protected $userStore;
/**
* @var \PHPCI\Service\UserService
*/
protected $userService;
public function init()
{
$this->userStore = b8\Store\Factory::getStore('User');
$this->userService = new UserService($this->userStore);
}
/**
@ -53,16 +60,11 @@ class UserController extends Controller
$values = $user->getDataArray();
if ($this->request->getMethod() == 'POST') {
$values = $this->getParams();
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
if (!empty($values['password'])) {
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
}
$this->view->updated = true;
$user->setValues($values);
$_SESSION['user'] = $this->userStore->save($user);
$_SESSION['user'] = $this->userService->updateUser($name, $email, $password);
}
$form = new Form();
@ -132,13 +134,13 @@ class UserController extends Controller
return $view->render();
}
$values = $form->getValues();
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
$user = new User();
$user->setValues($values);
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0);
$user = $this->userStore->save($user);
$this->userService->createUser($name, $email, $password, $isAdmin);
header('Location: '.PHPCI_URL.'user');
die;
@ -172,18 +174,12 @@ class UserController extends Controller
return $view->render();
}
if (!empty($values['password'])) {
$values['hash'] = password_hash($values['password'], PASSWORD_DEFAULT);
}
$name = $this->getParam('name', null);
$email = $this->getParam('email', null);
$password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0);
$user->setValues($values);
$isAdmin = $this->getParam('is_admin');
if (empty($isAdmin)) {
$user->setIsAdmin(0);
}
$this->userStore->save($user);
$this->userService->updateUser($user, $name, $email, $password, $isAdmin);
header('Location: '.PHPCI_URL.'user');
die;
@ -258,7 +254,7 @@ class UserController extends Controller
throw new NotFoundException('User with ID: ' . $userId . ' does not exist.');
}
$this->userStore->delete($user);
$this->userService->deleteUser($user);
header('Location: '.PHPCI_URL.'user');
die;

View file

@ -13,6 +13,7 @@ use b8;
use b8\Store;
use PHPCI\BuildFactory;
use PHPCI\Model\Build;
use PHPCI\Service\BuildService;
/**
* Webhook Controller - Processes webhook pings from BitBucket, Github, Gitlab, etc.
@ -29,9 +30,21 @@ class WebhookController extends \PHPCI\Controller
*/
protected $buildStore;
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @var \PHPCI\Service\BuildService
*/
protected $buildService;
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->buildService = new BuildService($this->buildStore);
}
/**
@ -238,22 +251,15 @@ class WebhookController extends \PHPCI\Controller
return true;
}
// If not, create a new build job for it:
$build = new Build();
$build->setProjectId($projectId);
$build->setCommitId($commitId);
$build->setStatus(Build::STATUS_NEW);
$build->setLog('');
$build->setCreated(new \DateTime());
$build->setBranch($branch);
$build->setCommitterEmail($committer);
$build->setCommitMessage($commitMessage);
$project = $this->projectStore->getById($projectId);
if (!is_null($extra)) {
$build->setExtra(json_encode($extra));
if (empty($project)) {
throw new \Exception('Project does not exist:' . $projectId);
}
$build = BuildFactory::getBuild($this->buildStore->save($build));
// If not, create a new build job for it:
$build = $this->buildService->createBuild($project, $commitId, $branch, $committer, $commitMessage, $extra);
$build = BuildFactory::getBuild($build);
// Send a status postback if the build type provides one:
$build->sendStatusPostback();

View file

@ -30,6 +30,7 @@ abstract class BaseCommandExecutor implements CommandExecutor
protected $verbose;
protected $lastOutput;
protected $lastError;
public $logExecOutput = true;
@ -78,16 +79,40 @@ abstract class BaseCommandExecutor implements CommandExecutor
}
$status = 0;
exec($command, $this->lastOutput, $status);
$descriptorSpec = array(
0 => array("pipe", "r"), // stdin
1 => array("pipe", "w"), // stdout
2 => array("pipe", "w"), // stderr
);
foreach ($this->lastOutput as &$lastOutput) {
$lastOutput = trim($lastOutput, '"');
$pipes = array();
$process = proc_open($command, $descriptorSpec, $pipes, dirname($this->buildPath), null);
if (is_resource($process)) {
fclose($pipes[0]);
$this->lastOutput = stream_get_contents($pipes[1]);
$this->lastError = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$status = proc_close($process);
}
if ($this->logExecOutput && !empty($this->lastOutput) && ($this->verbose|| $status != 0)) {
$this->lastOutput = array_filter(explode(PHP_EOL, $this->lastOutput));
$shouldOutput = ($this->logExecOutput && ($this->verbose || $status != 0));
if ($shouldOutput && !empty($this->lastOutput)) {
$this->logger->log($this->lastOutput);
}
if (!empty($this->lastError)) {
$this->logger->log("\033[0;31m" . $this->lastError . "\033[0m", LogLevel::ERROR);
}
$rtn = false;
if ($status == 0) {
@ -105,6 +130,14 @@ abstract class BaseCommandExecutor implements CommandExecutor
return implode(PHP_EOL, $this->lastOutput);
}
/**
* Returns the stderr output from the last command run.
*/
public function getLastError()
{
return $this->lastError;
}
/**
* Find a binary required by a plugin.
* @param string $binary
@ -170,8 +203,11 @@ abstract class BaseCommandExecutor implements CommandExecutor
$composer = $path.'/composer.json';
if (is_file($composer)) {
$json = json_decode(file_get_contents($composer));
if (isset($json->config->{"bin-dir"})) {
return $path.'/'.$json->config->{"bin-dir"};
} elseif (is_dir($path . '/vendor/bin')) {
return $path . '/vendor/bin';
}
}
}

View file

@ -40,7 +40,7 @@ class MailerFactory
return \Swift_Mailer::newInstance($transport);
}
protected function getMailConfig($configName)
public function getMailConfig($configName)
{
if (isset($this->emailConfig[$configName]) && $this->emailConfig[$configName] != "") {
return $this->emailConfig[$configName];

View file

@ -29,7 +29,7 @@ class SshKey
mkdir($tempPath);
}
$return = array();
$return = array('private_key' => '', 'public_key' => '');
if ($this->canGenerateKeys()) {
shell_exec('ssh-keygen -q -t rsa -b 2048 -f '.$keyFile.' -N "" -C "deploy@phpci"');
@ -37,15 +37,13 @@ class SshKey
$pub = file_get_contents($keyFile . '.pub');
$prv = file_get_contents($keyFile);
if (empty($pub)) {
$pub = '';
if (!empty($pub)) {
$return['public_key'] = $pub;
}
if (empty($prv)) {
$prv = '';
if (!empty($prv)) {
$return['private_key'] = $prv;
}
$return = array('private_key' => $prv, 'public_key' => $pub);
}
return $return;

View file

@ -20,6 +20,11 @@ class User
public function __call($method, $params = array())
{
$user = $_SESSION['user'];
if (!is_object($user)) {
return null;
}
return call_user_func_array(array($user, $method), $params);
}
}

View file

@ -9,7 +9,7 @@
namespace PHPCI\Logging;
use b8\Store;
use b8\Store\Factory;
use Monolog\Handler\AbstractProcessingHandler;
use PHPCI\Model\Build;
@ -40,5 +40,7 @@ class BuildDBLogHandler extends AbstractProcessingHandler
$this->logValue .= $message . PHP_EOL;
$this->build->setLog($this->logValue);
Factory::getStore('Build')->save($this->build);
}
}

View file

@ -0,0 +1,49 @@
<?php
use Phinx\Migration\AbstractMigration;
class FixDatabaseColumns extends AbstractMigration
{
/**
* Migrate Up.
*/
public function up()
{
$build = $this->table('build');
$build->changeColumn('project_id', 'integer', array('null' => false));
$build->changeColumn('commit_id', 'string', array('limit' => 50, 'null' => false));
$build->changeColumn('status', 'integer', array('null' => false));
$build->changeColumn('log', 'text', array('null' => true, 'default' => ''));
$build->changeColumn('branch', 'string', array('limit' => 50, 'null' => false, 'default' => 'master'));
$build->changeColumn('created', 'datetime', array('null' => true));
$build->changeColumn('started', 'datetime', array('null' => true));
$build->changeColumn('finished', 'datetime', array('null' => true));
$build->changeColumn('committer_email', 'string', array('limit' => 512, 'null' => true));
$build->changeColumn('commit_message', 'text', array('null' => true));
$build->changeColumn('extra', 'text', array('null' => true));
$buildMeta = $this->table('build_meta');
$buildMeta->changeColumn('project_id', 'integer', array('null' => false));
$buildMeta->changeColumn('build_id', 'integer', array('null' => false));
$buildMeta->changeColumn('meta_key', 'string', array('limit' => 250, 'null' => false));
$buildMeta->changeColumn('meta_value', 'text', array('null' => false));
$project = $this->table('project');
$project->changeColumn('title', 'string', array('limit' => 250, 'null' => false));
$project->changeColumn('reference', 'string', array('limit' => 250, 'null' => false));
$project->changeColumn('branch', 'string', array('limit' => 50, 'null' => false, 'default' => 'master'));
$project->changeColumn('ssh_private_key', 'text', array('null' => true, 'default' => null));
$project->changeColumn('ssh_public_key', 'text', array('null' => true, 'default' => null));
$project->changeColumn('type', 'string', array('limit' => 50, 'null' => false));
$project->changeColumn('access_information', 'string', array('limit' => 250, 'null' => true, 'default' => null));
$project->changeColumn('last_commit', 'string', array('limit' => 250, 'null' => true, 'default' => null));
$project->changeColumn('ssh_public_key', 'text', array('null' => true, 'default' => null));
$project->changeColumn('allow_public_status', 'integer', array('null' => false, 'default' => 0));
$user = $this->table('user');
$user->changeColumn('email', 'string', array('limit' => 250, 'null' => false));
$user->changeColumn('hash', 'string', array('limit' => 250, 'null' => false));
$user->changeColumn('is_admin', 'integer', array('null' => false, 'default' => 0));
$user->changeColumn('name', 'string', array('limit' => 250, 'null' => false));
}
}

View file

@ -36,6 +36,7 @@ class ProjectBase extends Model
'id' => null,
'title' => null,
'reference' => null,
'branch' => null,
'ssh_private_key' => null,
'ssh_public_key' => null,
'type' => null,
@ -200,17 +201,15 @@ class ProjectBase extends Model
}
/**
* Get the value of Branch / branch.
*
* @return string
*/
* Get the value of Branch / branch.
*
* @return string
*/
public function getBranch()
{
if (empty($this->data['branch'])) {
return $this->getType() === 'hg' ? 'default' : 'master';
} else {
return $this->data['branch'];
}
$rtn = $this->data['branch'];
return $rtn;
}
/**
@ -365,6 +364,7 @@ class ProjectBase extends Model
*/
public function setBranch($value)
{
$this->_validateNotNull('Branch', $value);
$this->_validateString('Branch', $value);
if ($this->data['branch'] === $value) {

View file

@ -38,15 +38,6 @@ class Build extends BuildBase
return '#';
}
/**
* @return string
*/
public function getProjectTitle()
{
$project = $this->getProject();
return $project ? $project->getTitle() : "";
}
/**
* Get link to branch from another source (i.e. Github)
*/
@ -55,6 +46,11 @@ class Build extends BuildBase
return '#';
}
public function getFileLinkTemplate()
{
return null;
}
/**
* Send status updates to any relevant third parties (i.e. Github)
*/
@ -63,6 +59,15 @@ class Build extends BuildBase
return;
}
/**
* @return string
*/
public function getProjectTitle()
{
$project = $this->getProject();
return $project ? $project->getTitle() : "";
}
/**
* Store build metadata
*/
@ -160,11 +165,6 @@ class Build extends BuildBase
return $config;
}
public function getFileLinkTemplate()
{
return null;
}
public function getExtra($key = null)
{
$data = json_decode($this->data['extra'], true);

View file

@ -109,8 +109,19 @@ class GithubBuild extends RemoteGitBuild
public function getFileLinkTemplate()
{
$link = 'https://github.com/' . $this->getProject()->getReference() . '/';
$link .= 'blob/' . $this->getBranch() . '/';
$reference = $this->getProject()->getReference();
$branch = $this->getBranch();
if ($this->getExtra('build_type') == 'pull_request') {
$matches = array();
preg_match('/\/([a-zA-Z0-9_\-]+\/[a-zA-Z0-9_\-]+)/', $this->getExtra('remote_url'), $matches);
$reference = $matches[1];
$branch = $this->getExtra('remote_branch');
}
$link = 'https://github.com/' . $reference . '/';
$link .= 'blob/' . $branch . '/';
$link .= '{FILE}';
$link .= '#L{LINE}';

View file

@ -61,7 +61,17 @@ class GitlabBuild extends RemoteGitBuild
if (!empty($key)) {
$user = $this->getProject()->getAccessInformation("user");
$domain = $this->getProject()->getAccessInformation("domain");
return $user . '@' . $domain . ':' . $this->getProject()->getReference() . '.git';
$port = $this->getProject()->getAccessInformation('port');
$url = $user . '@' . $domain . ':';
if (!empty($port)) {
$url .= $port . '/';
}
$url .= $this->getProject()->getReference() . '.git';
return $url;
}
}
}

View file

@ -44,9 +44,25 @@ class Project extends ProjectBase
return null;
}
public function setAccessInformation($value)
{
if (is_array($value)) {
$value = json_encode($value);
}
parent::setAccessInformation($value);
}
public function getAccessInformation($key = null)
{
$data = unserialize($this->data['access_information']);
$info = $this->data['access_information'];
// Handle old-format (serialized) access information first:
if (!empty($info) && substr($info, 0, 1) != '{') {
$data = unserialize($info);
} else {
$data = json_decode($info, true);
}
if (is_null($key)) {
$rtn = $data;
@ -58,4 +74,18 @@ class Project extends ProjectBase
return $rtn;
}
/**
* Get the value of Branch / branch.
*
* @return string
*/
public function getBranch()
{
if (empty($this->data['branch'])) {
return $this->getType() === 'hg' ? 'default' : 'master';
} else {
return $this->data['branch'];
}
}
}

View file

@ -43,7 +43,11 @@ class PhpLoc implements PHPCI\Plugin, PHPCI\ZeroConfigPlugin
{
$this->phpci = $phpci;
$this->build = $build;
$this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath;
$this->directory = $phpci->buildPath;
if (isset($options['directory'])) {
$this->directory .= $options['directory'];
}
}
/**

View file

@ -0,0 +1,111 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\Store\BuildStore;
class BuildService
{
/**
* @var \PHPCI\Store\BuildStore
*/
protected $buildStore;
/**
* @param BuildStore $buildStore
*/
public function __construct(BuildStore $buildStore)
{
$this->buildStore = $buildStore;
}
/**
* @param Project $project
* @param string|null $commitId
* @param string|null $branch
* @param string|null $committerEmail
* @param string|null $commitMessage
* @param string|null $extra
* @return \PHPCI\Model\Build
*/
public function createBuild(
Project $project,
$commitId = null,
$branch = null,
$committerEmail = null,
$commitMessage = null,
$extra = null
) {
$build = new Build();
$build->setCreated(new \DateTime());
$build->setProject($project);
$build->setStatus(0);
if (!is_null($commitId)) {
$build->setCommitId($commitId);
} else {
$build->setCommitId('Manual');
}
if (!is_null($branch)) {
$build->setBranch($branch);
} else {
$build->setBranch($project->getBranch());
}
if (!is_null($committerEmail)) {
$build->setCommitterEmail($committerEmail);
}
if (!is_null($commitMessage)) {
$build->setCommitMessage($commitMessage);
}
if (!is_null($extra)) {
$build->setExtra(json_encode($extra));
}
return $this->buildStore->save($build);
}
/**
* @param Build $copyFrom
* @return \PHPCI\Model\Build
*/
public function createDuplicateBuild(Build $copyFrom)
{
$data = $copyFrom->getDataArray();
// Clean up unwanted properties from the original build:
unset($data['id']);
unset($data['status']);
unset($data['log']);
unset($data['started']);
unset($data['finished']);
$build = new Build();
$build->setValues($data);
$build->setCreated(new \DateTime());
return $this->buildStore->save($build);
}
/**
* Delete a given build.
* @param Build $build
* @return bool
*/
public function deleteBuild(Build $build)
{
return $this->buildStore->delete($build);
}
}

View file

@ -0,0 +1,124 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\Project;
use PHPCI\Store\ProjectStore;
class ProjectService
{
/**
* @var \PHPCI\Store\ProjectStore
*/
protected $projectStore;
/**
* @param ProjectStore $projectStore
*/
public function __construct(ProjectStore $projectStore)
{
$this->projectStore = $projectStore;
}
/**
* Create a new project model and use the project store to save it.
* @param string $title
* @param string $type
* @param string $reference
* @param array $options
* @return \PHPCI\Model\Project
*/
public function createProject($title, $type, $reference, $options = array())
{
// Create base project and use updateProject() to set its properties:
$project = new Project();
return $this->updateProject($project, $title, $type, $reference, $options);
}
/**
* Update the properties of a given project.
* @param Project $project
* @param string $title
* @param string $type
* @param string $reference
* @param array $options
* @return \PHPCI\Model\Project
*/
public function updateProject(Project $project, $title, $type, $reference, $options = array())
{
// Set basic properties:
$project->setTitle($title);
$project->setType($type);
$project->setReference($reference);
$project->setAllowPublicStatus(0);
// Handle extra project options:
if (array_key_exists('ssh_private_key', $options)) {
$project->setSshPrivateKey($options['ssh_private_key']);
}
if (array_key_exists('ssh_public_key', $options)) {
$project->setSshPublicKey($options['ssh_public_key']);
}
if (array_key_exists('build_config', $options)) {
$project->setBuildConfig($options['build_config']);
}
if (array_key_exists('allow_public_status', $options)) {
$project->setAllowPublicStatus((int)$options['allow_public_status']);
}
if (array_key_exists('branch', $options)) {
$project->setBranch($options['branch']);
}
// Allow certain project types to set access information:
$this->processAccessInformation($project);
// Save and return the project:
return $this->projectStore->save($project);
}
/**
* Delete a given project.
* @param Project $project
* @return bool
*/
public function deleteProject(Project $project)
{
return $this->projectStore->delete($project);
}
/**
* In circumstances where it is necessary, populate access information based on other project properties.
* @see ProjectService::createProject()
* @param Project $project
*/
protected function processAccessInformation(Project &$project)
{
$matches = array();
$reference = $project->getReference();
if ($project->getType() == 'gitlab') {
$info = array();
if (preg_match('`^(.*)@(.*):([0-9]+)?/?(.*)/(.*)\.git`', $reference, $matches)) {
$info['user'] = $matches[1];
$info['domain'] = $matches[2];
$info['port'] = $matches[3];
$project->setReference($matches[4] . '/' . $matches[5]);
}
$project->setAccessInformation($info);
}
}
}

View file

@ -0,0 +1,61 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link https://www.phptesting.org/
*/
namespace PHPCI\Service;
use PHPCI\Model\User;
use PHPCI\Store\UserStore;
class UserService
{
/**
* @var \PHPCI\Store\UserStore
*/
protected $store;
/**
* @param UserStore $store
*/
public function __construct(UserStore $store)
{
$this->store = $store;
}
public function createUser($name, $emailAddress, $password, $isAdmin = false)
{
$user = new User();
$user->setName($name);
$user->setEmail($emailAddress);
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
$user->setIsAdmin(($isAdmin ? 1 : 0));
return $this->store->save($user);
}
public function updateUser(User $user, $name, $emailAddress, $password = null, $isAdmin = null)
{
$user->setName($name);
$user->setEmail($emailAddress);
if (!empty($password)) {
$user->setHash(password_hash($password, PASSWORD_DEFAULT));
}
if (!is_null($isAdmin)) {
$user->setIsAdmin(($isAdmin ? 1 : 0));
}
return $this->store->save($user);
}
public function deleteUser(User $user)
{
return $this->store->delete($user);
}
}

View file

@ -165,21 +165,7 @@
<td><a href="<?php print $build->getBranchLink(); ?>"><?php print $build->getBranch(); ?></a></td>
<td>
<?php
$plugins = json_decode($build->getPlugins(), true);
if ( !is_array($plugins) ) {
$plugins = array();
}
if ( 0 === count($plugins) ) {
?> <span class='label label-<?php echo $subcls ?>'><?php echo $status ?></span> <?php
}
?>
<?php
foreach($plugins as $plugin => $pluginstatus):
$subcls = $pluginstatus?'label label-success':'label label-danger';
?> <span class='<?php echo $subcls ?>'><?php print $this->Build()->formatPluginName($plugin); ?></span> <?php endforeach; ?>
<br style='clear:both;' />
<span class='label label-<?php echo $subcls ?>'><?php echo $status ?></span>
</td>
</tr>
<?php endforeach; ?>

View file

@ -66,12 +66,26 @@
<script>
var refreshProjectData = function()
{
$('#latest-builds').load('<?php echo PHPCI_URL ?>home/latest', function () {
$('#latest-builds').trigger('latest-builds:reload');
$.ajax({
url: '<?php echo PHPCI_URL ?>home/latest',
success: function (data) {
$('#latest-builds').html(data);
$('#latest-builds').trigger('latest-builds:reload');
},
error: handleFailedAjax
});
$('#project-overview').load('<?php echo PHPCI_URL ?>home/summary', function () {
$('#project-overview').trigger('project-overview:reload');
$.ajax({
url: '<?php echo PHPCI_URL ?>home/summary',
success: function (data) {
$('#project-overview').html(data);
$('#project-overview').trigger('project-overview:reload');
},
error: handleFailedAjax
});
};

View file

@ -114,7 +114,16 @@
<script>
setInterval(function()
{
$('#latest-builds').load('<?php echo PHPCI_URL ?>project/builds/<?php print $project->getId(); ?>');
$.ajax({
url: '<?php echo PHPCI_URL ?>project/builds/<?php print $project->getId(); ?>',
success: function (data) {
$('#latest-builds').html(data);
$('#latest-builds').trigger('latest-builds:reload');
},
error: handleFailedAjax
});
}, 10000);
$(function() {

View file

@ -0,0 +1,71 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Helper\MailerFactory;
/**
* Unit tests for the ProjectService class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class MailerFactoryTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGetMailConfig()
{
$config = array(
'smtp_address' => 'mail.example.com',
'smtp_port' => 225,
'smtp_encryption' => true,
'smtp_username' => 'example.user',
'smtp_password' => 'examplepassword',
'default_mailto_address' => 'phpci@example.com',
);
$factory = new MailerFactory(array('email_settings' => $config));
$this->assertEquals($config['smtp_address'], $factory->getMailConfig('smtp_address'));
$this->assertEquals($config['smtp_port'], $factory->getMailConfig('smtp_port'));
$this->assertEquals($config['smtp_encryption'], $factory->getMailConfig('smtp_encryption'));
$this->assertEquals($config['smtp_username'], $factory->getMailConfig('smtp_username'));
$this->assertEquals($config['smtp_password'], $factory->getMailConfig('smtp_password'));
$this->assertEquals($config['default_mailto_address'], $factory->getMailConfig('default_mailto_address'));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestMailer()
{
$config = array(
'smtp_address' => 'mail.example.com',
'smtp_port' => 225,
'smtp_encryption' => true,
'smtp_username' => 'example.user',
'smtp_password' => 'examplepassword',
'default_mailto_address' => 'phpci@example.com',
);
$factory = new MailerFactory(array('email_settings' => $config));
$mailer = $factory->getSwiftMailerFromConfig();
$this->assertEquals($config['smtp_address'], $mailer->getTransport()->getHost());
$this->assertEquals($config['smtp_port'], $mailer->getTransport()->getPort());
$this->assertEquals('tls', $mailer->getTransport()->getEncryption());
$this->assertEquals($config['smtp_username'], $mailer->getTransport()->getUsername());
$this->assertEquals($config['smtp_password'], $mailer->getTransport()->getPassword());
}
}

View file

@ -0,0 +1,84 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Model\Tests;
use PHPCI\Model\Build;
use PHPCI\Model;
/**
* Unit tests for the Build model class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsAValidModel()
{
$build = new Build();
$this->assertTrue($build instanceof \b8\Model);
$this->assertTrue($build instanceof Model);
$this->assertTrue($build instanceof Model\Base\BuildBase);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBaseBuildDefaults()
{
$build = new Build();
$this->assertEquals('#', $build->getCommitLink());
$this->assertEquals('#', $build->getBranchLink());
$this->assertEquals(null, $build->getFileLinkTemplate());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsSuccessful()
{
$build = new Build();
$build->setStatus(Build::STATUS_NEW);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_RUNNING);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_FAILED);
$this->assertFalse($build->isSuccessful());
$build->setStatus(Build::STATUS_SUCCESS);
$this->assertTrue($build->isSuccessful());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBuildExtra()
{
$info = array(
'item1' => 'Item One',
'item2' => 2,
);
$build = new Build();
$build->setExtra(json_encode($info));
$this->assertEquals('Item One', $build->getExtra('item1'));
$this->assertEquals(2, $build->getExtra('item2'));
$this->assertNull($build->getExtra('item3'));
$this->assertEquals($info, $build->getExtra());
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Model\Tests;
use PHPCI\Model\Project;
use PHPCI\Model;
/**
* Unit tests for the Project model class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class ProjectTest extends \PHPUnit_Framework_TestCase
{
public function setUp()
{
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestIsAValidModel()
{
$project = new Project();
$this->assertTrue($project instanceof \b8\Model);
$this->assertTrue($project instanceof Model);
$this->assertTrue($project instanceof Model\Base\ProjectBase);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGitDefaultBranch()
{
$project = new Project();
$project->setType('git');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGithubDefaultBranch()
{
$project = new Project();
$project->setType('github');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestGitlabDefaultBranch()
{
$project = new Project();
$project->setType('gitlab');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestBitbucketDefaultBranch()
{
$project = new Project();
$project->setType('bitbucket');
$this->assertEquals('master', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestMercurialDefaultBranch()
{
$project = new Project();
$project->setType('hg');
$this->assertEquals('default', $project->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_TestProjectAccessInformation()
{
$info = array(
'item1' => 'Item One',
'item2' => 2,
);
$project = new Project();
$project->setAccessInformation($info);
$this->assertEquals('Item One', $project->getAccessInformation('item1'));
$this->assertEquals(2, $project->getAccessInformation('item2'));
$this->assertNull($project->getAccessInformation('item3'));
$this->assertEquals($info, $project->getAccessInformation());
}
}

View file

@ -0,0 +1,148 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\Build;
use PHPCI\Model\Project;
use PHPCI\Service\BuildService;
/**
* Unit tests for the ProjectService class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class BuildServiceTest extends \PHPUnit_Framework_TestCase
{
/**
* @var BuildService $testedService
*/
protected $testedService;
/**
* @var \ $mockBuildStore
*/
protected $mockBuildStore;
public function setUp()
{
$this->mockBuildStore = $this->getMock('PHPCI\Store\BuildStore');
$this->mockBuildStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new BuildService($this->mockBuildStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBasicBuild()
{
$project = new Project();
$project->setType('github');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project);
$this->assertEquals(101, $returnValue->getProjectId());
$this->assertEquals(Build::STATUS_NEW, $returnValue->getStatus());
$this->assertNull($returnValue->getStarted());
$this->assertNull($returnValue->getFinished());
$this->assertNull($returnValue->getLog());
$this->assertNull($returnValue->getCommitMessage());
$this->assertNull($returnValue->getCommitterEmail());
$this->assertNull($returnValue->getExtra());
$this->assertEquals('master', $returnValue->getBranch());
$this->assertInstanceOf('DateTime', $returnValue->getCreated());
$this->assertEquals('Manual', $returnValue->getCommitId());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBuildWithOptions()
{
$project = new Project();
$project->setType('hg');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project, '123', 'testbranch', 'test@example.com', 'test');
$this->assertEquals('testbranch', $returnValue->getBranch());
$this->assertEquals('123', $returnValue->getCommitId());
$this->assertEquals('test', $returnValue->getCommitMessage());
$this->assertEquals('test@example.com', $returnValue->getCommitterEmail());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBuildWithExtra()
{
$project = new Project();
$project->setType('bitbucket');
$project->setId(101);
$returnValue = $this->testedService->createBuild($project, null, null, null, null, array('item1' => 1001));
$this->assertEquals(1001, $returnValue->getExtra('item1'));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateDuplicateBuild()
{
$build = new Build();
$build->setId(1);
$build->setProjectId(101);
$build->setCommitId('abcde');
$build->setStatus(Build::STATUS_FAILED);
$build->setLog('Test');
$build->setBranch('example_branch');
$build->setStarted(new \DateTime());
$build->setFinished(new \DateTime());
$build->setCommitMessage('test');
$build->setCommitterEmail('test@example.com');
$build->setExtra(json_encode(array('item1' => 1001)));
$returnValue = $this->testedService->createDuplicateBuild($build);
$this->assertNotEquals($build->getId(), $returnValue->getId());
$this->assertEquals($build->getProjectId(), $returnValue->getProjectId());
$this->assertEquals($build->getCommitId(), $returnValue->getCommitId());
$this->assertNotEquals($build->getStatus(), $returnValue->getStatus());
$this->assertEquals(Build::STATUS_NEW, $returnValue->getStatus());
$this->assertNull($returnValue->getLog());
$this->assertEquals($build->getBranch(), $returnValue->getBranch());
$this->assertNotEquals($build->getCreated(), $returnValue->getCreated());
$this->assertNull($returnValue->getStarted());
$this->assertNull($returnValue->getFinished());
$this->assertEquals('test', $returnValue->getCommitMessage());
$this->assertEquals('test@example.com', $returnValue->getCommitterEmail());
$this->assertEquals($build->getExtra('item1'), $returnValue->getExtra('item1'));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DeleteBuild()
{
$store = $this->getMock('PHPCI\Store\BuildStore');
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new BuildService($store);
$build = new Build();
$this->assertEquals(true, $service->deleteBuild($build));
}
}

View file

@ -0,0 +1,142 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\Project;
use PHPCI\Service\ProjectService;
/**
* Unit tests for the ProjectService class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class ProjectServiceTest extends \PHPUnit_Framework_TestCase
{
/**
* @var ProjectService $testedService
*/
protected $testedService;
/**
* @var \ $mockProjectStore
*/
protected $mockProjectStore;
public function setUp()
{
$this->mockProjectStore = $this->getMock('PHPCI\Store\ProjectStore');
$this->mockProjectStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new ProjectService($this->mockProjectStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateBasicProject()
{
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci');
$this->assertEquals('Test Project', $returnValue->getTitle());
$this->assertEquals('github', $returnValue->getType());
$this->assertEquals('block8/phpci', $returnValue->getReference());
$this->assertEquals('master', $returnValue->getBranch());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateProjectWithOptions()
{
$options = array(
'ssh_private_key' => 'private',
'ssh_public_key' => 'public',
'allow_public_status' => 1,
'build_config' => 'config',
'branch' => 'testbranch',
);
$returnValue = $this->testedService->createProject('Test Project', 'github', 'block8/phpci', $options);
$this->assertEquals('private', $returnValue->getSshPrivateKey());
$this->assertEquals('public', $returnValue->getSshPublicKey());
$this->assertEquals('config', $returnValue->getBuildConfig());
$this->assertEquals('testbranch', $returnValue->getBranch());
$this->assertEquals(1, $returnValue->getAllowPublicStatus());
}
/**
* @link https://github.com/Block8/PHPCI/issues/484
* @covers PHPUnit::execute
*/
public function testExecute_CreateGitlabProjectWithoutPort()
{
$reference = 'git@gitlab.block8.net:block8/phpci.git';
$returnValue = $this->testedService->createProject('Gitlab', 'gitlab', $reference);
$this->assertEquals('git', $returnValue->getAccessInformation('user'));
$this->assertEquals('gitlab.block8.net', $returnValue->getAccessInformation('domain'));
$this->assertEquals('block8/phpci', $returnValue->getReference());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_UpdateExistingProject()
{
$project = new Project();
$project->setTitle('Before Title');
$project->setReference('Before Reference');
$project->setType('github');
$returnValue = $this->testedService->updateProject($project, 'After Title', 'bitbucket', 'After Reference');
$this->assertEquals('After Title', $returnValue->getTitle());
$this->assertEquals('After Reference', $returnValue->getReference());
$this->assertEquals('bitbucket', $returnValue->getType());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_EmptyPublicStatus()
{
$project = new Project();
$project->setAllowPublicStatus(1);
$options = array(
'ssh_private_key' => 'private',
'ssh_public_key' => 'public',
'build_config' => 'config',
);
$returnValue = $this->testedService->updateProject($project, 'Test Project', 'github', 'block8/phpci', $options);
$this->assertEquals(0, $returnValue->getAllowPublicStatus());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DeleteProject()
{
$store = $this->getMock('PHPCI\Store\ProjectStore');
$store->expects($this->once())
->method('delete')
->will($this->returnValue(true));
$service = new ProjectService($store);
$project = new Project();
$this->assertEquals(true, $service->deleteProject($project));
}
}

View file

@ -0,0 +1,116 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2014, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Service\Tests;
use PHPCI\Model\User;
use PHPCI\Service\UserService;
/**
* Unit tests for the ProjectService class.
* @author Dan Cryer <dan@block8.co.uk>
*/
class UserServiceTest extends \PHPUnit_Framework_TestCase
{
/**
* @var UserService $testedService
*/
protected $testedService;
/**
* @var \ $mockBuildStore
*/
protected $mockUserStore;
public function setUp()
{
$this->mockUserStore = $this->getMock('PHPCI\Store\UserStore');
$this->mockUserStore->expects($this->any())
->method('save')
->will($this->returnArgument(0));
$this->testedService = new UserService($this->mockUserStore);
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateNonAdminUser()
{
$user = $this->testedService->createUser('Test', 'test@example.com', 'testing', 0);
$this->assertEquals('Test', $user->getName());
$this->assertEquals('test@example.com', $user->getEmail());
$this->assertEquals(0, $user->getIsAdmin());
$this->assertTrue(password_verify('testing', $user->getHash()));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_CreateAdminUser()
{
$user = $this->testedService->createUser('Test', 'test@example.com', 'testing', 1);
$this->assertEquals(1, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_RevokeAdminStatus()
{
$user = new User();
$user->setEmail('test@example.com');
$user->setName('Test');
$user->setIsAdmin(1);
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'testing', 0);
$this->assertEquals(0, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_GrantAdminStatus()
{
$user = new User();
$user->setEmail('test@example.com');
$user->setName('Test');
$user->setIsAdmin(0);
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'testing', 1);
$this->assertEquals(1, $user->getIsAdmin());
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_ChangesPasswordIfNotEmpty()
{
$user = new User();
$user->setHash(password_hash('testing', PASSWORD_DEFAULT));
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', 'newpassword', 0);
$this->assertFalse(password_verify('testing', $user->getHash()));
$this->assertTrue(password_verify('newpassword', $user->getHash()));
}
/**
* @covers PHPUnit::execute
*/
public function testExecute_DoesNotChangePasswordIfEmpty()
{
$user = new User();
$user->setHash(password_hash('testing', PASSWORD_DEFAULT));
$user = $this->testedService->updateUser($user, 'Test', 'test@example.com', '', 0);
$this->assertTrue(password_verify('testing', $user->getHash()));
}
}

View file

@ -40,7 +40,11 @@
"require-dev": {
"phpunit/phpunit": "~4.0",
"phpspec/prophecy-phpunit": "~1.0"
"phpspec/prophecy-phpunit": "~1.0",
"phpmd/phpmd": "~2.0",
"squizlabs/php_codesniffer": "~1.5",
"block8/php-docblock-checker": "~1.0",
"phploc/phploc": "~2.0"
},
"suggest": {

View file

@ -6,6 +6,7 @@ build_settings:
- "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)
- "PHPCI/Migrations" # Ignore the migrations directory, as both PHPMD and PHPCS can't cope with them.
- "PHPCI/Model/Base" # These files are auto-generated, and sometimes hit PHPMD complexity thresholds.
setup:
composer:

View file

@ -20,5 +20,11 @@
<testsuite name="PHPCI Plugin Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Plugin</directory>
</testsuite>
<testsuite name="PHPCI Model Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Model</directory>
</testsuite>
<testsuite name="PHPCI Service Test Suite">
<directory suffix="Test.php">./Tests/PHPCI/Service</directory>
</testsuite>
</testsuites>
</phpunit>

View file

@ -20,7 +20,7 @@ function bindAppDeleteEvents () {
e.preventDefault();
confirmDelete(e.target.href, 'Build').onClose = function () {
refreshBuildsTable();
window.location.reload();
};
return false;

View file

@ -47,7 +47,7 @@ function confirmDelete(url, subject, reloadAfter) {
*/
$.ajax({
url: url,
'success': function (data) {
success: function (data) {
if (reloadAfter) {
dialog.onClose = function () {
window.location.reload();
@ -56,8 +56,12 @@ function confirmDelete(url, subject, reloadAfter) {
dialog.showStatusMessage('Successfully deleted!', 1000);
},
'error': function (data) {
error: function (data) {
dialog.showStatusMessage('Deletion failed! Server says "' + data.statusText + '"');
if (data.status == 401) {
handleFailedAjax(data);
}
}
});
}
@ -258,24 +262,28 @@ function setupProjectForm()
}
});
$('#element-type').change(function()
{
$('#element-type').change(function() {
if ($(this).val() == 'github') {
$('#loading').show();
$.getJSON(window.PHPCI_URL + 'project/github-repositories', function (data) {
$('#loading').hide();
$.ajax({
dataType: "json",
url: window.PHPCI_URL + 'project/github-repositories',
success: function (data) {
$('#loading').hide();
if (data.repos) {
$('#element-github').empty();
if (data.repos) {
$('#element-github').empty();
for (var i in data.repos) {
var name = data.repos[i];
$('#element-github').append($('<option></option>').text(name).val(name));
for (var i in data.repos) {
var name = data.repos[i];
$('#element-github').append($('<option></option>').text(name).val(name));
}
$('.github-container').slideDown();
}
$('.github-container').slideDown();
}
},
error: handleFailedAjax
});
} else {
$('.github-container').slideUp();
@ -342,8 +350,14 @@ var PHPCIObject = Class.extend({
}
var cb = function() {
$.getJSON(window.PHPCI_URL + uri, query, function(data) {
$(window).trigger({type: name, queryData: data});
$.ajax({
dataType: "json",
url: window.PHPCI_URL + uri,
data: query,
success: function(data) {
$(window).trigger({type: name, queryData: data});
},
error: handleFailedAjax
});
};
@ -454,3 +468,11 @@ var PHPCIObject = Class.extend({
}
})
});
function handleFailedAjax(xhr)
{
if (xhr.status == 401) {
window.location.href = window.PHPCI_URL + 'session/login';
}
}