Merge remote-tracking branch 'upstream/master'

Conflicts:
	composer.json
This commit is contained in:
a.cianfarani 2013-08-02 12:11:23 +02:00
commit 287a2b3632
49 changed files with 600 additions and 1032 deletions

View file

@ -10,7 +10,6 @@
namespace PHPCI;
use b8;
use b8\Registry;
use b8\Http\Response\RedirectResponse;
use b8\View;
@ -25,20 +24,14 @@ class Application extends b8\Application
*/
public function handleRequest()
{
// Registry legacy:
$registry = new b8\Registry($this->config, $this->request);
$this->initRequest();
// Validate the user's session unless it is a login/logout action or a web hook:
$sessionAction = ($this->controllerName == 'Session' && in_array($this->action, array('login', 'logout')));
$externalAction = in_array($this->controllerName, array('Bitbucket', 'Github', 'BuildStatus'));
$externalAction = in_array($this->controllerName, array('Bitbucket', 'Github', 'Gitlab', 'BuildStatus'));
$skipValidation = ($externalAction || $sessionAction);
if($skipValidation || $this->validateSession()) {
if ( !empty($_SESSION['user']) ) {
Registry::getInstance()->set('user', $_SESSION['user']);
}
parent::handleRequest();
}
@ -72,7 +65,7 @@ class Application extends b8\Application
$this->response->setContent('');
} else {
$this->response = new RedirectResponse($this->response);
$this->response->setHeader('Location', '/session/login');
$this->response->setHeader('Location', PHPCI_URL.'session/login');
}
return false;

View file

@ -11,7 +11,7 @@ namespace PHPCI;
use PHPCI\Model\Build;
use b8\Store;
use Symfony\Component\Yaml\Parser as YamlParser;
use b8\Config;
/**
* PHPCI Build Runner
@ -123,7 +123,7 @@ class Builder
*/
public function getSystemConfig($key)
{
return \b8\Registry::getInstance()->get($key);
return Config::getInstance()->get($key);
}
/**
@ -319,7 +319,7 @@ class Builder
{
$commitId = $this->build->getCommitId();
$buildId = 'project' . $this->build->getProject()->getId() . '-build' . $this->build->getId();
$this->ciDir = realpath(dirname(__FILE__) . '/../') . '/';
$this->ciDir = dirname(__FILE__) . '/../';
$this->buildPath = $this->ciDir . 'build/' . $buildId . '/';
$this->setInterpolationVars();

View file

@ -10,7 +10,6 @@
namespace PHPCI\Controller;
use b8;
use b8\Registry;
use PHPCI\Model\Build;
/**

View file

@ -41,6 +41,11 @@ class GithubController extends \PHPCI\Controller
$build->setLog('');
$build->setCreated(new \DateTime());
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
if (!empty($payload['pusher']['email'])) {
$build->setCommitterEmail($payload['pusher']['email']);
}
} catch (\Exception $ex) {
header('HTTP/1.1 400 Bad Request');
header('Ex: ' . $ex->getMessage());

View file

@ -0,0 +1,61 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Controller;
use b8;
use b8\Store;
use PHPCI\Model\Build;
/**
* Gitlab Controller - Processes webhook pings from Gitlab.
* @author Alex Russell <alex@clevercherry.com>, Dan Cryer <dan@block8.co.uk>
* @package PHPCI
* @subpackage Web
*/
class GitlabController extends \PHPCI\Controller
{
public function init()
{
$this->_buildStore = Store\Factory::getStore('Build');
}
/**
* Called by Gitlab Webhooks:
*/
public function webhook($project)
{
$payload = json_decode(file_get_contents("php://input"), true);
try {
$build = new Build();
$build->setProjectId($project);
$build->setCommitId($payload['after']);
$build->setStatus(0);
$build->setLog('');
$build->setCreated(new \DateTime());
$build->setBranch(str_replace('refs/heads/', '', $payload['ref']));
} catch (\Exception $ex) {
header('HTTP/1.1 400 Bad Request');
header('Ex: ' . $ex->getMessage());
die('FAIL');
}
try {
$build = $this->_buildStore->save($build);
$build->sendStatusPostback();
} catch (\Exception $ex) {
header('HTTP/1.1 500 Internal Server Error');
header('Ex: ' . $ex->getMessage());
die('FAIL');
}
die('OK');
}
}

View file

@ -15,7 +15,6 @@ use b8;
use b8\Controller;
use b8\Store;
use b8\Form;
use b8\Registry;
/**
* Project Controller - Allows users to create, edit and view projects.
@ -175,7 +174,7 @@ class ProjectController extends \PHPCI\Controller
*/
protected function handleGithubResponse()
{
$github = \b8\Registry::getInstance()->get('github_app');
$github = \b8\Config::getInstance()->get('phpci.github');
$code = $this->getParam('code', null);
if (!is_null($code)) {
@ -263,13 +262,15 @@ class ProjectController extends \PHPCI\Controller
$field->setPattern('^(github|bitbucket|remote|local)');
$field->setOptions($options);
$field->setLabel('Where is your project hosted?');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
if (isset($_SESSION['github_token'])) {
$field = new Form\Element\Select('github');
$field->setLabel('Choose a Github repository:');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$field->setOptions($this->getGithubRepositories());
$form->addField($field);
}
@ -303,24 +304,28 @@ class ProjectController extends \PHPCI\Controller
$field->setRequired(true);
$field->setValidator($referenceValidator);
$field->setLabel('Repository Name / URL (Remote) or Path (Local)');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\Text('title');
$field->setRequired(true);
$field->setLabel('Project Title');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\TextArea('key');
$field->setRequired(false);
$field->setLabel('Private key to use to access repository (leave blank for local and/or anonymous remotes)');
$field->setClass('span7');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$field->setRows(6);
$form->addField($field);
$field = new Form\Element\Submit();
$field->setValue('Save Project');
$field->setContainerClass('form-group');
$field->setClass('btn-success');
$form->addField($field);

View file

@ -21,7 +21,7 @@ class SessionController extends \PHPCI\Controller
{
public function init()
{
$this->response->disableLayout();
$this->response->disableLayout();
$this->_userStore = b8\Store\Factory::getStore('User');
}
@ -29,7 +29,7 @@ class SessionController extends \PHPCI\Controller
* Handles user login (form and processing)
*/
public function login()
{
{
if ($this->request->getMethod() == 'POST') {
$user = $this->_userStore->getByEmail($this->getParam('email'));
@ -42,22 +42,24 @@ class SessionController extends \PHPCI\Controller
$form = new b8\Form();
$form->setMethod('POST');
$form->setAction('/session/login');
$form->setAction(PHPCI_URL.'session/login');
$email = new b8\Form\Element\Email('email');
$email->setLabel('Email Address');
$email->setRequired(true);
$email->setClass('span3');
$email->setContainerClass('form-group');
$email->setClass('form-control');
$form->addField($email);
$pwd = new b8\Form\Element\Password('password');
$pwd->setLabel('Password');
$pwd->setRequired(true);
$pwd->setClass('span3');
$pwd->setContainerClass('form-group');
$pwd->setClass('form-control');
$form->addField($pwd);
$pwd = new b8\Form\Element\Submit();
$pwd->setValue('Login &raquo;');
$pwd->setValue('Log in &raquo;');
$pwd->setClass('btn-success');
$form->addField($pwd);

View file

@ -10,7 +10,6 @@
namespace PHPCI\Controller;
use b8;
use b8\Registry;
use PHPCI\Model\User;
use b8\Form;
@ -130,31 +129,35 @@ class UserController extends \PHPCI\Controller
{
$form = new Form();
$form->setMethod('POST');
$form->setAction('/user/' . $type);
$form->setAction(PHPCI_URL.'user/' . $type);
$form->addField(new Form\Element\Csrf('csrf'));
$field = new Form\Element\Email('email');
$field->setRequired(true);
$field->setLabel('Email Address');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\Text('name');
$field->setRequired(true);
$field->setLabel('Name');
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\Password('password');
$field->setRequired(true);
$field->setLabel('Password' . ($type == 'edit' ? ' (leave blank to keep current password)' : ''));
$field->setClass('span4');
$field->setClass('form-control');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\Checkbox('admin');
$field->setRequired(false);
$field->setCheckedValue(1);
$field->setLabel('Is this user an administrator?');
$field->setContainerClass('form-group');
$form->addField($field);
$field = new Form\Element\Submit();

24
PHPCI/Helper/Build.php Normal file
View file

@ -0,0 +1,24 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Helper;
/**
* User Helper - Provides access to logged in user information in views.
* @author Dan Cryer <dan@block8.co.uk>
* @package PHPCI
* @subpackage Web
*/
class Build
{
public function formatPluginName($name)
{
return str_replace('Php', 'PHP', ucwords(str_replace('_', ' ', $name)));
}
}

View file

@ -42,6 +42,7 @@ class BuildBase extends Model
'started' => null,
'finished' => null,
'plugins' => null,
'committer_email' => null,
);
/**
@ -58,6 +59,7 @@ class BuildBase extends Model
'started' => 'getStarted',
'finished' => 'getFinished',
'plugins' => 'getPlugins',
'committer_email' => 'getCommitterEmail',
'Project' => 'getProject',
);
@ -75,6 +77,7 @@ class BuildBase extends Model
'started' => 'setStarted',
'finished' => 'setFinished',
'plugins' => 'setPlugins',
'committer_email' => 'setCommitterEmail',
'Project' => 'setProject',
);
@ -129,6 +132,11 @@ class BuildBase extends Model
'length' => '',
'nullable' => true,
),
'committer_email' => array(
'type' => 'varchar',
'length' => '512',
'nullable' => true,
),
);
/**
@ -299,6 +307,19 @@ class BuildBase extends Model
return $rtn;
}
/**
* Get the value of CommitterEmail / committer_email.
*
* @return string
*/
public function getCommitterEmail()
{
$rtn = $this->data['committer_email'];
return $rtn;
}
/**
* Set the value of Id / id.
*
@ -309,7 +330,7 @@ class BuildBase extends Model
{
$this->_validateNotNull('Id', $value);
$this->_validateInt('Id', $value);
if ($this->data['id'] === $value) {
if ($this->data['id'] == $value) {
return;
}
@ -328,7 +349,7 @@ class BuildBase extends Model
{
$this->_validateNotNull('ProjectId', $value);
$this->_validateInt('ProjectId', $value);
if ($this->data['project_id'] === $value) {
if ($this->data['project_id'] == $value) {
return;
}
@ -347,7 +368,7 @@ class BuildBase extends Model
{
$this->_validateNotNull('CommitId', $value);
$this->_validateString('CommitId', $value);
if ($this->data['commit_id'] === $value) {
if ($this->data['commit_id'] == $value) {
return;
}
@ -366,7 +387,7 @@ class BuildBase extends Model
{
$this->_validateNotNull('Status', $value);
$this->_validateInt('Status', $value);
if ($this->data['status'] === $value) {
if ($this->data['status'] == $value) {
return;
}
@ -384,7 +405,7 @@ class BuildBase extends Model
{
$this->_validateString('Log', $value);
if ($this->data['log'] === $value) {
if ($this->data['log'] == $value) {
return;
}
@ -403,7 +424,7 @@ class BuildBase extends Model
{
$this->_validateNotNull('Branch', $value);
$this->_validateString('Branch', $value);
if ($this->data['branch'] === $value) {
if ($this->data['branch'] == $value) {
return;
}
@ -421,7 +442,7 @@ class BuildBase extends Model
{
$this->_validateDate('Created', $value);
if ($this->data['created'] === $value) {
if ($this->data['created'] == $value) {
return;
}
@ -439,7 +460,7 @@ class BuildBase extends Model
{
$this->_validateDate('Started', $value);
if ($this->data['started'] === $value) {
if ($this->data['started'] == $value) {
return;
}
@ -457,7 +478,7 @@ class BuildBase extends Model
{
$this->_validateDate('Finished', $value);
if ($this->data['finished'] === $value) {
if ($this->data['finished'] == $value) {
return;
}
@ -475,7 +496,7 @@ class BuildBase extends Model
{
$this->_validateString('Plugins', $value);
if ($this->data['plugins'] === $value) {
if ($this->data['plugins'] == $value) {
return;
}
@ -484,6 +505,24 @@ class BuildBase extends Model
$this->_setModified('plugins');
}
/**
* Set the value of CommitterEmail / committer_email.
*
* @param $value string
*/
public function setCommitterEmail($value)
{
$this->_validateString('CommitterEmail', $value);
if ($this->data['committer_email'] == $value) {
return;
}
$this->data['committer_email'] = $value;
$this->_setModified('committer_email');
}
/**
* Get the Project model for this Build by Id.
*

View file

@ -199,7 +199,7 @@ class ProjectBase extends Model
{
$this->_validateNotNull('Id', $value);
$this->_validateInt('Id', $value);
if ($this->data['id'] === $value) {
if ($this->data['id'] == $value) {
return;
}
@ -218,7 +218,7 @@ class ProjectBase extends Model
{
$this->_validateNotNull('Title', $value);
$this->_validateString('Title', $value);
if ($this->data['title'] === $value) {
if ($this->data['title'] == $value) {
return;
}
@ -237,7 +237,7 @@ class ProjectBase extends Model
{
$this->_validateNotNull('Reference', $value);
$this->_validateString('Reference', $value);
if ($this->data['reference'] === $value) {
if ($this->data['reference'] == $value) {
return;
}
@ -256,7 +256,7 @@ class ProjectBase extends Model
{
$this->_validateNotNull('GitKey', $value);
$this->_validateString('GitKey', $value);
if ($this->data['git_key'] === $value) {
if ($this->data['git_key'] == $value) {
return;
}
@ -275,7 +275,7 @@ class ProjectBase extends Model
{
$this->_validateNotNull('Type', $value);
$this->_validateString('Type', $value);
if ($this->data['type'] === $value) {
if ($this->data['type'] == $value) {
return;
}
@ -293,7 +293,7 @@ class ProjectBase extends Model
{
$this->_validateString('Token', $value);
if ($this->data['token'] === $value) {
if ($this->data['token'] == $value) {
return;
}

View file

@ -179,7 +179,7 @@ class UserBase extends Model
{
$this->_validateNotNull('Id', $value);
$this->_validateInt('Id', $value);
if ($this->data['id'] === $value) {
if ($this->data['id'] == $value) {
return;
}
@ -198,7 +198,7 @@ class UserBase extends Model
{
$this->_validateNotNull('Email', $value);
$this->_validateString('Email', $value);
if ($this->data['email'] === $value) {
if ($this->data['email'] == $value) {
return;
}
@ -217,7 +217,7 @@ class UserBase extends Model
{
$this->_validateNotNull('Hash', $value);
$this->_validateString('Hash', $value);
if ($this->data['hash'] === $value) {
if ($this->data['hash'] == $value) {
return;
}
@ -236,7 +236,7 @@ class UserBase extends Model
{
$this->_validateNotNull('IsAdmin', $value);
$this->_validateInt('IsAdmin', $value);
if ($this->data['is_admin'] === $value) {
if ($this->data['is_admin'] == $value) {
return;
}
@ -255,7 +255,7 @@ class UserBase extends Model
{
$this->_validateNotNull('Name', $value);
$this->_validateString('Name', $value);
if ($this->data['name'] === $value) {
if ($this->data['name'] == $value) {
return;
}

View file

@ -67,7 +67,7 @@ class GithubBuild extends RemoteGitBuild
break;
}
$url = \b8\Registry::getInstance()->get('install_url');
$url = \b8\Config::getInstance()->get('phpci.url');
$params = array( 'state' => $status,
'target_url' => $url . '/build/view/' . $this->getId());
$headers = array(

View file

@ -74,7 +74,14 @@ class RemoteGitBuild extends Build
protected function cloneBySsh(Builder $builder, $to)
{
// Copy the project's keyfile to disk:
$keyFile = realpath($to) . '.key';
$keyPath = realpath($to);
if ($keyPath === false) {
$keyPath = dirname($to);
}
$keyFile = $keyPath . '.key';
file_put_contents($keyFile, $this->getProject()->getGitKey());
chmod($keyFile, 0600);

56
PHPCI/Plugin/Grunt.php Normal file
View file

@ -0,0 +1,56 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Plugin;
/**
* Grunt Plugin - Provides access to grunt functionality.
* @author Tobias Tom <t.tom@succont.de>
* @package PHPCI
* @subpackage Plugins
*/
class Grunt implements \PHPCI\Plugin
{
protected $directory;
protected $task;
protected $preferDist;
protected $phpci;
protected $grunt;
protected $gruntfile;
public function __construct(\PHPCI\Builder $phpci, 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'] : 'grunt';
$this->gruntfile = isset($options['gruntfile']) ? $options['gruntfile'] : 'Gruntfile.js';
}
/**
* Executes grunt and runs a specified command (e.g. install / update)
*/
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 ) ) {
return false;
}
// build the grunt command
$cmd = 'cd %s && ' . $this->grunt;
$cmd .= ' --no-color';
$cmd .= ' --gruntfile %s';
$cmd .= ' %s'; // the task that will be executed
// and execute it
return $this->phpci->executeCommand($cmd, $this->directory, $this->gruntfile, $this->task);
}
}

104
PHPCI/Plugin/Pdepend.php Normal file
View file

@ -0,0 +1,104 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Plugin;
/**
* Pdepend Plugin - Allows Pdepend report
* @author Johan van der Heide <info@japaveh.nl>
* @package PHPCI
* @subpackage Plugins
*/
class Pdepend implements \PHPCI\Plugin
{
protected $args;
/**
* @var \PHPCI\Builder
*/
protected $phpci;
/**
* @var string Directory which needs to be scanned
*/
protected $directory;
/**
* @var string File where the summary.xml is stored
*/
protected $summary;
/**
* @var string File where the chart.svg is stored
*/
protected $chart;
/**
* @var string File where the pyramid.svg is stored
*/
protected $pyramid;
/**
* @var string Location on the server where the files are stored. Preferably in the webroot for inclusion
* in the readme.md of the repository
*/
protected $location;
public function __construct(\PHPCI\Builder $phpci, array $options = array())
{
$this->phpci = $phpci;
$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';
$this->location = $this->phpci->buildPath . '..' . DIRECTORY_SEPARATOR . 'pdepend';
}
/**
* Runs Pdepend with the given criteria as arguments
*/
public function execute()
{
if (!is_writable($this->location)) {
throw new \Exception(sprintf('The location %s is not writable.', $this->location));
}
$cmd = PHPCI_BIN_DIR . 'pdepend --summary-xml=%s --jdepend-chart=%s --overview-pyramid=%s "%s"';
//Remove the created files first
unlink($this->location . DIRECTORY_SEPARATOR . $this->summary);
unlink($this->location . DIRECTORY_SEPARATOR . $this->chart);
unlink($this->location . DIRECTORY_SEPARATOR . $this->pyramid);
$success = $this->phpci->executeCommand(
$cmd,
$this->location . DIRECTORY_SEPARATOR . $this->summary,
$this->location . DIRECTORY_SEPARATOR . $this->chart,
$this->location . DIRECTORY_SEPARATOR . $this->pyramid,
$this->directory
);
$config = $this->phpci->getSystemConfig('phpci');
if ($success) {
$this->phpci->logSuccess(
sprintf(
"Pdepend successful. You can use %s\n, ![Chart](%s \"Pdepend Chart\")\n
and ![Pyramid](%s \"Pdepend Pyramid\")\n
for inclusion in the readme.md file",
$config['url'] . '/build/pdepend/' . $this->summary,
$config['url'] . '/build/pdepend/' . $this->chart,
$config['url'] . '/build/pdepend/' . $this->pyramid
)
);
} else {
$this->phpci->logFailure(sprintf("The function '%s' failed"));
}
return $success;
}
}

View file

@ -26,6 +26,8 @@ class PhpCodeSniffer implements \PHPCI\Plugin
$this->phpci = $phpci;
$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'] : '';
}
/**
@ -39,7 +41,27 @@ class PhpCodeSniffer implements \PHPCI\Plugin
$ignore = ' --ignore=' . implode(',', $this->phpci->ignore);
}
$cmd = PHPCI_BIN_DIR . 'phpcs --standard=%s %s "%s"';
return $this->phpci->executeCommand($cmd, $this->standard, $ignore, $this->phpci->buildPath);
$standard = '';
if (strpos($this->standard, '/') !== false) {
$standard = ' --standard='.$this->directory.$this->standard;
} else {
$standard = ' --standard='.$this->standard;
}
$tab_width = '';
if (strlen($this->tab_width)) {
$tab_width = ' --tab-width='.$this->tab_width;
}
$encoding = '';
if (strlen($this->encoding)) {
$encoding = ' --encoding='.$this->encoding;
}
$cmd = PHPCI_BIN_DIR . 'phpcs %s %s %s %s "%s"';
return $this->phpci->executeCommand($cmd, $standard, $ignore, $tab_width, $encoding, $this->phpci->buildPath);
}
}

52
PHPCI/Plugin/PhpLoc.php Normal file
View file

@ -0,0 +1,52 @@
<?php
/**
* PHPCI - Continuous Integration for PHP
*
* @copyright Copyright 2013, Block 8 Limited.
* @license https://github.com/Block8/PHPCI/blob/master/LICENSE.md
* @link http://www.phptesting.org/
*/
namespace PHPCI\Plugin;
/**
* PHP Loc - Allows PHP Copy / Lines of Code testing.
* @author Johan van der Heide <info@japaveh.nl>
* @package PHPCI
* @subpackage Plugins
*/
class PhpLoc implements \PHPCI\Plugin
{
/**
* @var string
*/
protected $directory;
/**
* @var \PHPCI\Builder
*/
protected $phpci;
public function __construct(\PHPCI\Builder $phpci, array $options = array())
{
$this->phpci = $phpci;
$this->directory = isset($options['directory']) ? $options['directory'] : $phpci->buildPath;
}
/**
* Runs PHP Copy/Paste Detector in a specified directory.
*/
public function execute()
{
$ignore = '';
if (count($this->phpci->ignore)) {
$map = function ($item) {
return ' --exclude ' . (substr($item, -1) == '/' ? substr($item, 0, -1) : $item);
};
$ignore = array_map($map, $this->phpci->ignore);
$ignore = implode('', $ignore);
}
return $this->phpci->executeCommand(PHPCI_BIN_DIR . 'phploc %s "%s"', $ignore, $this->phpci->buildPath);
}
}

View file

@ -4,21 +4,20 @@
</div>
<div class="row">
<div class="span3">
<div class="well" style="padding: 8px 0">
<ul class="nav nav-list">
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $build->getProject()->getId(); ?>"><i class="icon-folder-open"></i> <?php print $build->getProject()->getTitle(); ?></a></li>
<li class="divider"></li>
<li class="nav-header">Options</li>
</ul>
<h5>Options</h5>
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>build/rebuild/<?php print $build->getId(); ?>"><i class="icon-cog"></i> Rebuild</a></li>
<?php if($this->User()->getIsAdmin()): ?>
<li><a href="#" id="delete-build"><i class="icon-trash"></i> Delete Build</a></li>
<?php endif; ?>
</ul>
</div>
<table class="table table-striped table-bordered">
<table class="table table-striped table-bordered" style="margin-top: 20px">
<thead>
<tr>
<th colspan="2">Plugin Status</th>
@ -28,7 +27,7 @@
</tbody>
</table>
</div>
<div class="span9">
<div class="col-lg-9">
<div id="status"></div>
<table class="table table-striped table-bordered">

View file

@ -10,7 +10,7 @@
switch($build->getStatus())
{
case 0:
$cls = 'info';
$cls = 'active';
$subcls = 'info';
$status = 'Pending';
@ -29,8 +29,8 @@ switch($build->getStatus())
break;
case 3:
$cls = 'error';
$subcls = 'important';
$cls = 'danger';
$subcls = 'danger';
$status = 'Failed';
break;
}
@ -48,28 +48,20 @@ switch($build->getStatus())
$plugins = array();
}
if ( 0 === count($plugins) ) {
?>
<span class='label label-<?= $subcls ?>'>
<?= $status ?>
</span>
<?php
?> <span class='label label-<?= $subcls ?>'><?= $status ?></span> <?php
}
?>
<?php
foreach($plugins as $plugin => $pluginstatus):
$subcls = $pluginstatus?'label label-success':'label label-important';
?>
<span class='<?= $subcls ?>'>
<?= ucwords(str_replace('_', ' ', $plugin)) ?>
</span>
<?php endforeach; ?>
$subcls = $pluginstatus?'label label-success':'label label-danger';
?> <span class='<?= $subcls ?>'><?php print $this->Build()->formatPluginName($plugin); ?></span> <?php endforeach; ?>
<br style='clear:both;' />
</td>
<td>
<div class="btn-group">
<a class="btn" href="<?= PHPCI_URL ?>build/view/<?php print $build->getId(); ?>">View</a>
<a class="btn btn-default btn-small" href="<?= PHPCI_URL ?>build/view/<?php print $build->getId(); ?>">View</a>
<?php if($this->User()->getIsAdmin()): ?>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<button class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
@ -79,4 +71,4 @@ switch($build->getStatus())
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>

View file

@ -2,14 +2,15 @@
<h1 style="display: inline-block">Dashboard</h1>
</div>
<div class="row">
<div class="span3">
<div class="well" style="padding: 8px 0">
<ul class="nav nav-list">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li class="active"><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>user"><i class="icon-user"></i> Users</a></li>
<li class="divider"></li>
<li class="nav-header">Projects</li>
</ul>
<?php if (count($projects)): ?>
<h5>Projects</h5>
<ul class="nav nav-pills nav-stacked">
<?php
foreach($projects as $project):
$status = 'icon-build-ok';
@ -37,9 +38,9 @@
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><i class="<?= $status; ?>"></i> <?php print $project->getTitle(); ?></a></li>
<?php endforeach; ?>
</ul>
</div>
</div>
<div class="span9">
<?php endif; ?>
</div>
<div class="col-lg-9">
<h3>Project Overview</h3>
<table class="table table-striped table-bordered">
<thead>
@ -49,7 +50,7 @@
<th>Last Success</th>
<th>Last Failure</th>
<th>Success/Failures</th>
<th style="width: 1%"></th>
<th style="width: 100px"></th>
</tr>
</thead>
<tbody>
@ -66,7 +67,7 @@
<th>Commit</th>
<th>Branch</th>
<th>Status</th>
<th style="width: 1%"></th>
<th style="width: 100px"></th>
</tr>
</thead>
<tbody id="latest-builds">

View file

@ -3,13 +3,13 @@
</div>
<div class="row">
<div class="span3">
<div class="well" style="padding: 8px 0">
<ul class="nav nav-list">
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>project/view/<?php print $project->getId(); ?>"><i class="icon-folder-open"></i> <?php print $project->getTitle(); ?></a></li>
<li class="divider"></li>
<li class="nav-header">Options</li>
</ul>
<h5>Options</h5>
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>project/build/<?php print $project->getId(); ?>"><i class="icon-cog"></i> Build Now</a></li>
<?php if($this->User()->getIsAdmin()): ?>
@ -17,7 +17,6 @@
<li><a href="#" id="delete-project"><i class="icon-trash"></i> Delete Project</a></li>
<?php endif; ?>
</ul>
</div>
<?php if (in_array($project->getType(), array('github', 'bitbucket'))): ?>
<br>
@ -40,7 +39,7 @@
?>
</p>
</div>
<div class="span9">
<div class="col-lg-9">
<table class="table table-striped table-bordered">
<thead>
<tr>
@ -49,7 +48,7 @@
<th>Commit</th>
<th>Branch</th>
<th>Status</th>
<th style="width: 1%"></th>
<th style="width: 100px"></th>
</tr>
</thead>
<tbody id="latest-builds">
@ -59,7 +58,7 @@
<?php
print '<div class="pagination"><ul>';
print '<div><ul class="pagination">';
$pages = ceil($total / 10);
$pages = $pages == 0 ? 1 : $pages;

View file

@ -3,7 +3,7 @@
</div>
<div class="row">
<div class="span4">
<div class="col-lg-4">
<div class="well" style="">
<?php if(!is_null($key)): ?>
<p>To make it easier to get started, we've generated a public / private key pair for you to use for this project. To use it, just add the following public key to the "deploy keys" section of your repository settings on Github / Bitbucket.</p>
@ -16,7 +16,7 @@
<?php endif; ?>
</div>
</div>
<div class="span8">
<div class="col-lg-8">
<?php print $form; ?>
</div>
</div>
@ -25,7 +25,7 @@
window.return_url = <?php print json_encode((empty($_SERVER['HTTPS']) ? 'http' : 'https') . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); ?>;
<?php
$gh = \b8\Registry::getInstance()->get('github_app', null);
$gh = \b8\Config::getInstance()->get('phpci.github', null);
if($gh) {
print 'window.github_app_id = ' . json_encode($gh['id']) . ';' . PHP_EOL;

View file

@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Log in</title>
<title>Log in to PHPCI</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -11,39 +11,77 @@
<style type="text/css">
html {
min-height: 100%;
}
body
{
background: #246;
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 */
min-height: 100%;
font-family: Roboto, Arial, Sans-Serif;
font-style: normal;
font-weight: 300;
padding-top: 70px;
padding-top: 0px;
}
#login-box
{
background: #fff;
border: 10px solid #369;
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 */
border-radius: 5px;
box-shadow: 0 0 30px rgba(0,0,0, 0.3);
margin: 0 auto;
padding: 10px;
padding: 15px 30px;
text-align: left;
width: 270px;
width: 350px;
}
#logo {
display: block;
background: transparent url('http://www.block8.co.uk/badge-dark-muted.png') no-repeat top left;
display: inline-block;
height: 26px;
margin: 40px auto;
width: 90px;
}
#logo:hover {
background-image: url('http://www.block8.co.uk/badge-dark.png');
}
#phpci-logo img {
margin-bottom: 30px;
}
</style>
</head>
<body>
<div class="container">
<div class="row" style="margin-top: 10%; text-align: center">
<a id="phpci-logo" href="http://www.phptesting.org">
<img src="<?php print PHPCI_URL; ?>/assets/img/logo-large.png">
</a>
<div class="" id="login-box">
<?php print $form; ?>
</div>
<a id="logo" href="http://www.block8.co.uk/"><img src="http://cms.block8.co.uk/assets/img/small-logo-trans-white.png"></a>
<a id="logo" href="http://www.block8.co.uk/"></a>
</div>
</div>
</body>

View file

@ -60,12 +60,12 @@ foreach($projects as $projectId => $project):
switch($project['lastbuildstatus'])
{
case 0:
$cls = 'info';
$cls = 'active';
$status = 'Pending';
break;
case 1:
$cls = 'warning';
$cls = 'danger';
$status = 'Running';
break;
@ -80,8 +80,8 @@ foreach($projects as $projectId => $project):
break;
}
$health = ($project['health'] < 0 ? 'Stormy': ($project['health'] < 5? 'Overcast': 'Sunny'));
$subcls = ($project['health'] < 0 ? 'important': ($project['health'] < 5? 'warning': 'success'));
$health = ($project['health'] <= 0 ? 'Stormy': ($project['successes'] < $project['count']? 'Overcast': 'Sunny'));
$subcls = ($project['health'] <= 0 ? 'danger': ($project['successes'] < $project['count']? 'warning': 'success'));
?>
<tr class="<?php print $cls; ?>">
<td>
@ -109,6 +109,6 @@ foreach($projects as $projectId => $project):
<?php } ?>
</td>
<td><?= $project['successes'] ?>/<?= $project['failures'] ?></td>
<td><a class="btn" href='<?= PHPCI_URL ?>project/build/<?= $projectId ?>'>build</a></td>
<td><a class="btn btn-default btn-small" href='<?= PHPCI_URL ?>project/build/<?= $projectId ?>'>build now &raquo;</a></td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>

View file

@ -3,25 +3,23 @@
</div>
<div class="row">
<div class="span3">
<div class="well" style="padding: 8px 0">
<ul class="nav nav-list">
<div class="col-lg-3">
<ul class="nav nav-pills nav-stacked">
<li><a href="<?= PHPCI_URL ?>"><i class="icon-home"></i> Dashboard</a></li>
<li><a href="<?= PHPCI_URL ?>user"><i class="icon-user"></i> Users</a></li>
<li class="active"><a href="<?= PHPCI_URL ?>user"><i class="icon-user"></i> Users</a></li>
<?php if($this->User()->getIsAdmin()): ?>
<li><a href="<?= PHPCI_URL ?>user/add"><i class="icon-plus-sign"></i> Add User</a></li>
<?php endif; ?>
</ul>
</div>
</div>
<div class="span9">
<div class="col-lg-9">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Email Address</th>
<th>Name</th>
<th>Administrator</th>
<th style="width: 1%"></th>
<th style="width: 100px"></th>
</tr>
</thead>
<tbody>
@ -47,8 +45,8 @@
<td>
<?php if($this->User()->getIsAdmin()): ?>
<div class="btn-group">
<a class="btn" href="<?= PHPCI_URL ?>user/edit/<?php print $user->getId(); ?>">Edit</a>
<button class="btn dropdown-toggle" data-toggle="dropdown">
<a class="btn btn-default btn-small" href="<?= PHPCI_URL ?>user/edit/<?php print $user->getId(); ?>">Edit</a>
<button class="btn btn-default btn-small dropdown-toggle" data-toggle="dropdown">
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
@ -62,4 +60,4 @@
</tbody>
</table>
</div>
</div>
</div>

View file

@ -3,7 +3,7 @@
</div>
<div class="row">
<div class="span4">
<div class="col-lg-4">
<div class="well" style="">
<?php if($type == 'add'): ?>
<p>Fill in the form to the right to add a new user.</p>
@ -12,7 +12,7 @@
<?php endif; ?>
</div>
</div>
<div class="span8">
<div class="col-lg-8">
<?php print $form; ?>
</div>
</div>

View file

@ -15,19 +15,27 @@
</head>
<body>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="brand" href="<?= PHPCI_URL ?>">PHPCI <span class="badge badge-important" style="position: relative; top: -3px; margin-left: 10px">1.0.0 Beta</span></a>
<div class="container">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="<?= PHPCI_URL ?>"><img src="<?= PHPCI_URL ?>/assets/img/logo.png"></a>
<div class="nav-collapse collapse navbar-responsive-collapse">
<ul class="nav navbar-nav pull-right">
<li><a href="<?= PHPCI_URL ?>session/logout">Log out</a></li>
</ul>
<?php if($this->User()->getIsAdmin()): ?>
<a class="btn btn-success navbar-btn pull-right" href="<?= PHPCI_URL ?>project/add">Add Project</a>
<?php endif; ?>
</div>
<ul class="nav pull-right">
<li><a href="<?= PHPCI_URL ?>session/logout">Log out</a></li>
</ul>
<?php if($this->User()->getIsAdmin()): ?>
<a class="pull-right btn" href="<?= PHPCI_URL ?>project/add">Add Project</a>
<?php endif; ?>
</div>
</div>
</div>

View file

@ -41,7 +41,8 @@ _**Please be aware that PHPCI is a beta-release project, so whilst it is very st
####Installing from Github:
* Step 1: `git clone https://github.com/Block8/PHPCI.git`
* Step 2: `cd PHPCI`
* Step 3: `chmod +x ./console && ./console phpci:install`
* Step 3: `composer install`
* Step 4: `chmod +x ./console && ./console phpci:install`
* When prompted, enter your database host, username, password and the database name that PHPCI should use.
* The script will attempt to create the database if it does not exist already.
* If you intend to use the MySQL plugin to create / destroy databases, the user you entered above will need CREATE / DELETE permissions on the server.
@ -51,7 +52,7 @@ _**Please be aware that PHPCI is a beta-release project, so whilst it is very st
**Apache Example**:
RewriteEngine On
RewriteBase /path-to-phpci
RewriteBase /path-to-phpci/public
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)? index.php [L,E=PATH_INFO:/$1]
@ -103,6 +104,8 @@ Similar to Travis CI, to support PHPCI in your project, you simply need to add a
standard: "PSR2"
php_cpd:
allow_failures: true
grunt:
task: "build"
complete:
mysql:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -42,31 +42,6 @@ $conf['b8']['app']['default_controller'] = 'Index';
$conf['b8']['view']['path'] = dirname(__FILE__) . '/PHPCI/View/';
$config = new b8\Config($conf);
$request = new b8\Http\Request();
$registry = new b8\Registry($config, $request);
if (file_exists(APPLICATION_PATH . 'config.php')) {
require(APPLICATION_PATH . 'config.php');
$conf = $config->get(null);
unset($conf['b8']['app']);
unset($conf['b8']['view']);
$conf['phpci']['url'] = $conf['install_url'];
if (isset($conf['github_app'])) {
$conf['phpci']['github'] = $conf['github_app'];
}
unset($conf['install_url']);
unset($conf['github_app']);
$dumper = new Symfony\Component\Yaml\Dumper();
$yaml = $dumper->dump($conf);
file_put_contents(APPLICATION_PATH . 'PHPCI/config.yml', $yaml);
unlink(APPLICATION_PATH . 'config.php');
}
if (file_exists(APPLICATION_PATH . 'PHPCI/config.yml')) {
$config->loadYaml(APPLICATION_PATH . 'PHPCI/config.yml');

View file

@ -34,6 +34,7 @@
"symfony/console" : "2.2.*",
"fabpot/php-cs-fixer" : "0.3.*@dev",
"swiftmailer/swiftmailer" : "v5.0.0",
"atoum/atoum":"*"
"phploc/phploc": "*",
"atoum/atoum":"*"
}
}

11
console
View file

@ -14,14 +14,9 @@ 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_exists(PHPCI_DIR . 'composer.phar')) {
print 'INSTALLING: Composer' . PHP_EOL;
file_put_contents(PHPCI_DIR . 'composerinstaller.php', file_get_contents('https://getcomposer.org/installer'));
shell_exec('php ' . escapeshellarg(PHPCI_DIR . 'composerinstaller.php'));
unlink(PHPCI_DIR . 'composerinstaller.php');
print 'RUNNING: Composer' . PHP_EOL;
shell_exec('php '.escapeshellarg(PHPCI_DIR.'composer.phar').' install');
if (!file_exists(PHPCI_DIR . 'vendor/autoload.php')) {
file_put_contents('php://stderr', 'Please install PHPCI with "composer install" before using console');
exit( 1 );
}
require('bootstrap.php');

9
public/assets/css/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -57,22 +57,22 @@ td .label { margin-right: 5px; }
.icon-build-ok
{
background: url('/assets/img/icon-build-ok.png') no-repeat top left;
background: url('../img/icon-build-ok.png') no-repeat top left;
}
.icon-build-failed
{
background: url('/assets/img/icon-build-failed.png') no-repeat top left;
background: url('../img/icon-build-failed.png') no-repeat top left;
}
.icon-build-pending
{
background: url('/assets/img/icon-build-pending.png') no-repeat top left;
background: url('../img/icon-build-pending.png') no-repeat top left;
}
.icon-build-running
{
background: url('/assets/img/icon-build-running.png') no-repeat top left;
background: url('../img/icon-build-running.png') no-repeat top left;
}
h3
@ -80,4 +80,8 @@ h3
border-bottom: 1px solid #f0f0f0;
margin-top: 0;
padding-top: 0;
}
.navbar-brand {
padding: 10px 15px;
}

View file

Before

Width:  |  Height:  |  Size: 2 KiB

After

Width:  |  Height:  |  Size: 2 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 282 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 290 B

After

Width:  |  Height:  |  Size: 290 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 292 B

After

Width:  |  Height:  |  Size: 292 B

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 284 B

After

Width:  |  Height:  |  Size: 284 B

Before After
Before After

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

BIN
public/assets/img/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

6
public/assets/js/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -82,7 +82,7 @@ function updateBuildView(data)
for(var plugin in data.plugins)
{
var row = $('<tr>').addClass(data.plugins[plugin] ? 'success' : 'error');
var name = $('<td>').html('<strong>' + plugin + '</strong>');
var name = $('<td>').html('<strong>' + formatPluginName(plugin) + '</strong>');
var status = $('<td>').text(data.plugins[plugin] ? 'OK' : 'Failed');
row.append(name);
@ -168,4 +168,19 @@ function setupProjectForm()
$('#element-token').val('');
}
});
}
function formatPluginName (name) {
name = name.replace(new RegExp('_', 'g'), ' ');
name = ucwords(name);
name = name.replace(new RegExp('Php', 'g'), 'PHP');
return name;
}
function ucwords (str) {
return (str + '').replace(/^([a-z\u00E0-\u00FC])|\s+([a-z\u00E0-\u00FC])/g, function ($1) {
return $1.toUpperCase();
});
}

View file

@ -12,7 +12,8 @@ session_start();
error_reporting(E_ALL);
ini_set('display_errors', 'on');
require_once('bootstrap.php');
require_once('../bootstrap.php');
$fc = new PHPCI\Application($config, $request);
$fc = new PHPCI\Application($config, new b8\Http\Request());
print $fc->handleRequest();