From 623bb18dd42fb3b1e8c1f2bda892f6d8b0dbb491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kinn=20Coelho=20Juli=C3=A3o?= Date: Fri, 17 May 2013 10:10:48 -0400 Subject: [PATCH 01/14] Added a Shell Plugin --- PHPCI/Plugin/Shell.php | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 PHPCI/Plugin/Shell.php diff --git a/PHPCI/Plugin/Shell.php b/PHPCI/Plugin/Shell.php new file mode 100644 index 00000000..602824ec --- /dev/null +++ b/PHPCI/Plugin/Shell.php @@ -0,0 +1,48 @@ + +* @package PHPCI +* @subpackage Plugins +*/ +class Shell implements \PHPCI\Plugin +{ + protected $args; + protected $phpci; + + /** + * @var string $command The command to be executed + */ + protected $command; + + public function __construct(\PHPCI\Builder $phpci, array $options = array()) + { + $this->phpci = $phpci; + + if (isset($options['command'])) { + $command = $options['command']; + $command = str_replace("%buildpath%", $this->phpci->buildPath, $command); + $this->command = $command; + } + } + + /** + * Runs the shell command. + */ + public function execute() + { + $success = $this->phpci->executeCommand($this->command); + + return $success; + } +} From 67386df9efe47f481dfde4ddac81ca998dc5d2e8 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 16:36:55 +0100 Subject: [PATCH 02/14] Refactoring to support updated b8framework. --- PHPCI/Application.php | 55 ++++++++++--------- PHPCI/Controller.php | 54 ++++++++++++++++++ PHPCI/Controller/BitbucketController.php | 2 +- PHPCI/Controller/BuildController.php | 9 +-- PHPCI/Controller/BuildStatusController.php | 2 +- PHPCI/Controller/GithubController.php | 2 +- PHPCI/Controller/IndexController.php | 9 ++- PHPCI/Controller/ProjectController.php | 31 ++++++----- PHPCI/Controller/SessionController.php | 15 ++--- PHPCI/Controller/UserController.php | 17 +++--- PHPCI/Helper/User.php | 2 +- PHPCI/Model/Base/BuildBase.php | 6 +- PHPCI/View/{Build.phtml => Build/view.phtml} | 0 PHPCI/View/{Index.phtml => Index/index.phtml} | 0 .../{Project.phtml => Project/view.phtml} | 0 .../View/{Login.phtml => Session/login.phtml} | 0 PHPCI/View/{User.phtml => User/index.phtml} | 0 PHPCI/View/{Layout.phtml => layout.phtml} | 0 bootstrap.php | 10 ++-- index.php | 5 +- 20 files changed, 140 insertions(+), 79 deletions(-) create mode 100644 PHPCI/Controller.php rename PHPCI/View/{Build.phtml => Build/view.phtml} (100%) rename PHPCI/View/{Index.phtml => Index/index.phtml} (100%) rename PHPCI/View/{Project.phtml => Project/view.phtml} (100%) rename PHPCI/View/{Login.phtml => Session/login.phtml} (100%) rename PHPCI/View/{User.phtml => User/index.phtml} (100%) rename PHPCI/View/{Layout.phtml => layout.phtml} (100%) diff --git a/PHPCI/Application.php b/PHPCI/Application.php index a2d2f940..5e873571 100644 --- a/PHPCI/Application.php +++ b/PHPCI/Application.php @@ -10,7 +10,8 @@ namespace PHPCI; use b8; -use b8\Registry; +use b8\Http\Response\RedirectResponse; +use b8\View; /** * PHPCI Front Controller @@ -18,35 +19,32 @@ use b8\Registry; */ class Application extends b8\Application { - public function __construct() - { - if (isset($_SERVER['REDIRECT_PATH_INFO'])) { - $_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_PATH_INFO']; - } - - return parent::__construct(); - } - /** * Handle an incoming web request. */ public function handleRequest() { - $controllerName = \b8\Registry::getInstance()->get('ControllerName'); + // 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 = ($controllerName == 'Session' && in_array($this->action, array('login', 'logout'))); - $externalAction = in_array($controllerName, array('Bitbucket', 'Github', 'BuildStatus')); - - if (!$externalAction && !$sessionAction) { - $this->validateSession(); + $sessionAction = ($this->controllerName == 'Session' && in_array($this->action, array('login', 'logout'))); + $externalAction = in_array($this->controllerName, array('Bitbucket', 'Github', 'BuildStatus')); + $skipValidation = ($externalAction || $sessionAction); + + if($skipValidation || $this->validateSession()) { + parent::handleRequest(); } - // Render content into layout and return: - $view = new b8\View('Layout'); - $view->content = parent::handleRequest(); - - return $view->render(); + if (View::exists('layout') && $this->response->hasLayout()) { + $view = new View('layout'); + $view->content = $this->response->getContent(); + $this->response->setContent($view->render()); + } + + return $this->response; } /** @@ -58,14 +56,21 @@ class Application extends b8\Application $user = b8\Store\Factory::getStore('User')->getByPrimaryKey($_SESSION['user_id']); if ($user) { - Registry::getInstance()->set('user', $user); - return; + $_SESSION['user'] = $user; + return true; } unset($_SESSION['user_id']); } - header('Location: /session/login'); - die; + if ($this->request->isAjax()) { + $this->response->setResponseCode(401); + $this->response->setBody(''); + } else { + $this->response = new RedirectResponse($this->response); + $this->response->setHeader('Location', '/session/login'); + } + + return false; } } diff --git a/PHPCI/Controller.php b/PHPCI/Controller.php new file mode 100644 index 00000000..b90e1c4e --- /dev/null +++ b/PHPCI/Controller.php @@ -0,0 +1,54 @@ +className = substr(array_pop($class), 0, -10); + $this->setControllerView(); + } + + protected function setControllerView() + { + if (View::exists($this->className)) { + $this->controllerView = new View($this->className); + } else { + $this->controllerView = new View\UserView('{@content}'); + } + } + + protected function setView($action) + { + if (View::exists($this->className . '/' . $action)) { + $this->view = new View($this->className . '/' . $action); + } + } + + public function handleAction($action, $actionParams) + { + $this->setView($action); + $response = parent::handleAction($action, $actionParams); + + if (is_string($response)) { + $this->controllerView->content = $response; + } elseif (isset($this->view)) { + $this->controllerView->content = $this->view->render(); + } + + $this->response->setContent($this->controllerView->render()); + + return $this->response; + } +} \ No newline at end of file diff --git a/PHPCI/Controller/BitbucketController.php b/PHPCI/Controller/BitbucketController.php index b0011336..dff0e8e6 100644 --- a/PHPCI/Controller/BitbucketController.php +++ b/PHPCI/Controller/BitbucketController.php @@ -19,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Web */ -class BitbucketController extends b8\Controller +class BitbucketController extends \PHPCI\Controller { public function init() { diff --git a/PHPCI/Controller/BuildController.php b/PHPCI/Controller/BuildController.php index 77c4762a..21de59c9 100644 --- a/PHPCI/Controller/BuildController.php +++ b/PHPCI/Controller/BuildController.php @@ -19,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Web */ -class BuildController extends b8\Controller +class BuildController extends \PHPCI\Controller { public function init() { @@ -32,11 +32,8 @@ class BuildController extends b8\Controller public function view($buildId) { $build = $this->_buildStore->getById($buildId); - $view = new b8\View('Build'); - $view->build = $build; - $view->data = $this->getBuildData($buildId); - - return $view->render(); + $this->view->build = $build; + $this->view->data = $this->getBuildData($buildId); } /** diff --git a/PHPCI/Controller/BuildStatusController.php b/PHPCI/Controller/BuildStatusController.php index e898405a..2a0f5c36 100644 --- a/PHPCI/Controller/BuildStatusController.php +++ b/PHPCI/Controller/BuildStatusController.php @@ -20,7 +20,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Web */ -class BuildStatusController extends b8\Controller +class BuildStatusController extends \PHPCI\Controller { public function init() { diff --git a/PHPCI/Controller/GithubController.php b/PHPCI/Controller/GithubController.php index a2a92e68..90bc37fe 100644 --- a/PHPCI/Controller/GithubController.php +++ b/PHPCI/Controller/GithubController.php @@ -19,7 +19,7 @@ use PHPCI\Model\Build; * @package PHPCI * @subpackage Web */ -class GithubController extends b8\Controller +class GithubController extends \PHPCI\Controller { public function init() { diff --git a/PHPCI/Controller/IndexController.php b/PHPCI/Controller/IndexController.php index 2633ab87..6f9d9c52 100644 --- a/PHPCI/Controller/IndexController.php +++ b/PHPCI/Controller/IndexController.php @@ -17,7 +17,7 @@ use b8; * @package PHPCI * @subpackage Web */ -class IndexController extends b8\Controller +class IndexController extends \PHPCI\Controller { public function init() { @@ -31,11 +31,10 @@ class IndexController extends b8\Controller public function index() { $projects = $this->_projectStore->getWhere(array(), 50, 0, array(), array('title' => 'ASC')); - $view = new b8\View('Index'); - $view->builds = $this->getLatestBuildsHtml(); - $view->projects = $projects['items']; + $this->view->builds = $this->getLatestBuildsHtml(); + $this->view->projects = $projects['items']; - return $view->render(); + return $this->view->render(); } /** diff --git a/PHPCI/Controller/ProjectController.php b/PHPCI/Controller/ProjectController.php index 89a4f819..70f95ab1 100644 --- a/PHPCI/Controller/ProjectController.php +++ b/PHPCI/Controller/ProjectController.php @@ -9,9 +9,11 @@ namespace PHPCI\Controller; -use b8; use PHPCI\Model\Build; use PHPCI\Model\Project; +use b8; +use b8\Controller; +use b8\Store; use b8\Form; use b8\Registry; @@ -21,12 +23,12 @@ use b8\Registry; * @package PHPCI * @subpackage Web */ -class ProjectController extends b8\Controller +class ProjectController extends \PHPCI\Controller { public function init() { - $this->_buildStore = b8\Store\Factory::getStore('Build'); - $this->_projectStore = b8\Store\Factory::getStore('Project'); + $this->_buildStore = Store\Factory::getStore('Build'); + $this->_projectStore = Store\Factory::getStore('Project'); } /** @@ -38,13 +40,12 @@ class ProjectController extends b8\Controller $page = $this->getParam('p', 1); $builds = $this->getLatestBuildsHtml($projectId, (($page - 1) * 10)); - $view = new b8\View('Project'); - $view->builds = $builds[0]; - $view->total = $builds[1]; - $view->project = $project; - $view->page = $page; + $this->view->builds = $builds[0]; + $this->view->total = $builds[1]; + $this->view->project = $project; + $this->view->page = $page; - return $view->render(); + return $this->view->render(); } /** @@ -69,7 +70,7 @@ class ProjectController extends b8\Controller */ public function delete($projectId) { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } @@ -107,11 +108,11 @@ class ProjectController extends b8\Controller */ public function add() { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } - $method = Registry::getInstance()->get('requestMethod'); + $method = $this->request->getMethod(); $this->handleGithubResponse(); if ($method == 'POST') { @@ -199,11 +200,11 @@ class ProjectController extends b8\Controller */ public function edit($projectId) { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } - $method = Registry::getInstance()->get('requestMethod'); + $method = $this->request->getMethod(); $project = $this->_projectStore->getById($projectId); if ($method == 'POST') { diff --git a/PHPCI/Controller/SessionController.php b/PHPCI/Controller/SessionController.php index a05c708d..214f9921 100644 --- a/PHPCI/Controller/SessionController.php +++ b/PHPCI/Controller/SessionController.php @@ -17,10 +17,11 @@ use b8; * @package PHPCI * @subpackage Web */ -class SessionController extends b8\Controller +class SessionController extends \PHPCI\Controller { public function init() { + $this->response->disableLayout(); $this->_userStore = b8\Store\Factory::getStore('User'); } @@ -28,10 +29,10 @@ class SessionController extends b8\Controller * Handles user login (form and processing) */ public function login() - { - if (b8\Registry::getInstance()->get('requestMethod') == 'POST') { + { + if ($this->request->getMethod() == 'POST') { $user = $this->_userStore->getByEmail($this->getParam('email')); - + if ($user && password_verify($this->getParam('password', ''), $user->getHash())) { $_SESSION['user_id'] = $user->getId(); header('Location: ' . PHPCI_URL); @@ -60,9 +61,9 @@ class SessionController extends b8\Controller $pwd->setClass('btn-success'); $form->addField($pwd); - $view = new b8\View('Login'); - $view->form = $form->render(); - die($view->render()); + $this->view->form = $form->render(); + + return $this->view->render(); } /** diff --git a/PHPCI/Controller/UserController.php b/PHPCI/Controller/UserController.php index 2160bd9b..402c8792 100644 --- a/PHPCI/Controller/UserController.php +++ b/PHPCI/Controller/UserController.php @@ -20,7 +20,7 @@ use b8\Form; * @package PHPCI * @subpackage Web */ -class UserController extends b8\Controller +class UserController extends \PHPCI\Controller { public function init() { @@ -33,10 +33,9 @@ class UserController extends b8\Controller public function index() { $users = $this->_userStore->getWhere(array(), 1000, 0, array(), array('email' => 'ASC')); - $view = new b8\View('User'); - $view->users = $users; + $this->view->users = $users; - return $view->render(); + return $this->view->render(); } /** @@ -44,11 +43,11 @@ class UserController extends b8\Controller */ public function add() { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } - $method = Registry::getInstance()->get('requestMethod'); + $method = $this->request->getMethod(); if ($method == 'POST') { $values = $this->getParams(); @@ -85,11 +84,11 @@ class UserController extends b8\Controller */ public function edit($userId) { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } - $method = Registry::getInstance()->get('requestMethod'); + $method = $this->request->getMethod(); $user = $this->_userStore->getById($userId); if ($method == 'POST') { @@ -172,7 +171,7 @@ class UserController extends b8\Controller */ public function delete($userId) { - if (!Registry::getInstance()->get('user')->getIsAdmin()) { + if (!$_SESSION['user']->getIsAdmin()) { throw new \Exception('You do not have permission to do that.'); } diff --git a/PHPCI/Helper/User.php b/PHPCI/Helper/User.php index e421520c..64872992 100644 --- a/PHPCI/Helper/User.php +++ b/PHPCI/Helper/User.php @@ -19,7 +19,7 @@ class User { public function __call($method, $params = array()) { - $user = \b8\Registry::getInstance()->get('user'); + $user = $_SESSION['user']; return call_user_func_array(array($user, $method), $params); } } diff --git a/PHPCI/Model/Base/BuildBase.php b/PHPCI/Model/Base/BuildBase.php index a2b0c092..e051aac4 100644 --- a/PHPCI/Model/Base/BuildBase.php +++ b/PHPCI/Model/Base/BuildBase.php @@ -101,7 +101,7 @@ class BuildBase extends Model 'length' => '4', ), 'log' => array( - 'type' => 'text', + 'type' => 'longtext', 'length' => '', 'nullable' => true, ), @@ -500,11 +500,11 @@ class BuildBase extends Model } $cacheKey = 'Cache.Project.' . $key; - $rtn = $this->registry->get($cacheKey, null); + $rtn = $this->cache->get($cacheKey, null); if (empty($rtn)) { $rtn = \b8\Store\Factory::getStore('Project')->getById($key); - $this->registry->set($cacheKey, $rtn); + $this->cache->set($cacheKey, $rtn); } return $rtn; diff --git a/PHPCI/View/Build.phtml b/PHPCI/View/Build/view.phtml similarity index 100% rename from PHPCI/View/Build.phtml rename to PHPCI/View/Build/view.phtml diff --git a/PHPCI/View/Index.phtml b/PHPCI/View/Index/index.phtml similarity index 100% rename from PHPCI/View/Index.phtml rename to PHPCI/View/Index/index.phtml diff --git a/PHPCI/View/Project.phtml b/PHPCI/View/Project/view.phtml similarity index 100% rename from PHPCI/View/Project.phtml rename to PHPCI/View/Project/view.phtml diff --git a/PHPCI/View/Login.phtml b/PHPCI/View/Session/login.phtml similarity index 100% rename from PHPCI/View/Login.phtml rename to PHPCI/View/Session/login.phtml diff --git a/PHPCI/View/User.phtml b/PHPCI/View/User/index.phtml similarity index 100% rename from PHPCI/View/User.phtml rename to PHPCI/View/User/index.phtml diff --git a/PHPCI/View/Layout.phtml b/PHPCI/View/layout.phtml similarity index 100% rename from PHPCI/View/Layout.phtml rename to PHPCI/View/layout.phtml diff --git a/bootstrap.php b/bootstrap.php index 3ece003e..4704260f 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -36,16 +36,18 @@ if (!defined('APPLICATION_PATH')) { require_once(APPLICATION_PATH . 'vendor/autoload.php'); // Load configuration if present: +$config = new b8\Config(); + if (file_exists(APPLICATION_PATH . 'config.php')) { require(APPLICATION_PATH . 'config.php'); // Define our PHPCI_URL, if not already defined: if (!defined('PHPCI_URL')) { - define('PHPCI_URL', $registry->get('install_url', '') . '/'); + define('PHPCI_URL', $config->get('install_url', '') . '/'); } } // Set up the registry: -b8\Registry::getInstance()->set('app_namespace', 'PHPCI'); -b8\Registry::getInstance()->set('DefaultController', 'Index'); -b8\Registry::getInstance()->set('ViewPath', dirname(__FILE__) . '/PHPCI/View/'); +$config->set('app_namespace', 'PHPCI'); +$config->set('default_controller', 'Index'); +$config->set('view_path', dirname(__FILE__) . '/PHPCI/View/'); \ No newline at end of file diff --git a/index.php b/index.php index 622e04c2..4f42e24f 100644 --- a/index.php +++ b/index.php @@ -9,7 +9,10 @@ session_start(); +error_reporting(E_ALL); +ini_set('display_errors', 'on'); + require_once('bootstrap.php'); -$fc = new PHPCI\Application(); +$fc = new PHPCI\Application(b8\Config::getInstance()); print $fc->handleRequest(); From 75816c50e7d98d3f241b997852c37abeab5aaa75 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 16:46:59 +0100 Subject: [PATCH 03/14] Fix for login screen appearing within layout, closes #51. --- PHPCI/Application.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Application.php b/PHPCI/Application.php index 5e873571..c0048adf 100644 --- a/PHPCI/Application.php +++ b/PHPCI/Application.php @@ -65,7 +65,7 @@ class Application extends b8\Application if ($this->request->isAjax()) { $this->response->setResponseCode(401); - $this->response->setBody(''); + $this->response->setContent(''); } else { $this->response = new RedirectResponse($this->response); $this->response->setHeader('Location', '/session/login'); From acb58ff5e042bb54f8cb55271db43056721756ed Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 17:15:02 +0100 Subject: [PATCH 04/14] Adding project overview to dashboard, closes #55 --- PHPCI/Controller/IndexController.php | 8 +++++++- PHPCI/Store/BuildStore.php | 29 +++++++++++++++++++++++++++- PHPCI/View/Index/index.phtml | 18 +++++++++++++++++ assets/css/phpci.css | 7 +++++++ 4 files changed, 60 insertions(+), 2 deletions(-) diff --git a/PHPCI/Controller/IndexController.php b/PHPCI/Controller/IndexController.php index 6f9d9c52..c185d2f3 100644 --- a/PHPCI/Controller/IndexController.php +++ b/PHPCI/Controller/IndexController.php @@ -31,8 +31,14 @@ class IndexController extends \PHPCI\Controller public function index() { $projects = $this->_projectStore->getWhere(array(), 50, 0, array(), array('title' => 'ASC')); + $summary = $this->_buildStore->getBuildSummary(); + + $summaryView = new b8\View('BuildsTable'); + $summaryView->builds = $summary['items']; + $this->view->builds = $this->getLatestBuildsHtml(); $this->view->projects = $projects['items']; + $this->view->summary = $summaryView->render(); return $this->view->render(); } @@ -50,7 +56,7 @@ class IndexController extends \PHPCI\Controller */ protected function getLatestBuildsHtml() { - $builds = $this->_buildStore->getWhere(array(), 10, 0, array(), array('id' => 'DESC')); + $builds = $this->_buildStore->getWhere(array(), 5, 0, array(), array('id' => 'DESC')); $view = new b8\View('BuildsTable'); $view->builds = $builds['items']; diff --git a/PHPCI/Store/BuildStore.php b/PHPCI/Store/BuildStore.php index 5355fac2..03b1ad28 100644 --- a/PHPCI/Store/BuildStore.php +++ b/PHPCI/Store/BuildStore.php @@ -19,5 +19,32 @@ use PHPCI\Store\Base\BuildStoreBase; */ class BuildStore extends BuildStoreBase { - // This class has been left blank so that you can modify it - changes in this file will not be overwritten. + public function getBuildSummary() + { + $query = 'SELECT COUNT(*) AS cnt FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC'; + $stmt = \b8\Database::getConnection('read')->prepare($query); + + if ($stmt->execute()) { + $res = $stmt->fetch(\PDO::FETCH_ASSOC); + $count = (int)$res['cnt']; + } else { + $count = 0; + } + + $query = 'SELECT * FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC'; + $stmt = \b8\Database::getConnection('read')->prepare($query); + + if ($stmt->execute()) { + $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); + + $map = function ($item) { + return new \PHPCI\Model\Build($item); + }; + $rtn = array_map($map, $res); + + return array('items' => $rtn, 'count' => $count); + } else { + return array('items' => array(), 'count' => 0); + } + } } diff --git a/PHPCI/View/Index/index.phtml b/PHPCI/View/Index/index.phtml index 4a53ec33..887b46d3 100644 --- a/PHPCI/View/Index/index.phtml +++ b/PHPCI/View/Index/index.phtml @@ -40,6 +40,24 @@
+

Project Overview

+ + + + + + + + + + + + + + +
IDProjectCommitBranchStatus
+ +

Last 5 Builds

diff --git a/assets/css/phpci.css b/assets/css/phpci.css index bb0340c3..931c4b0a 100644 --- a/assets/css/phpci.css +++ b/assets/css/phpci.css @@ -59,4 +59,11 @@ body .icon-build-running { background: url('/assets/img/icon-build-running.png') no-repeat top left; +} + +h3 +{ + border-bottom: 1px solid #f0f0f0; + margin-top: 0; + padding-top: 0; } \ No newline at end of file From c5b20b48911e9813610a99bcefcb878c36748522 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 17:23:35 +0100 Subject: [PATCH 05/14] Adding Shell plugin, but with the requirement that ENABLE_SHELL_PLUGIN must be defined and true, to give sysadmins some control. Closes #45. --- PHPCI/Plugin/Shell.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/PHPCI/Plugin/Shell.php b/PHPCI/Plugin/Shell.php index 602824ec..83595ad8 100644 --- a/PHPCI/Plugin/Shell.php +++ b/PHPCI/Plugin/Shell.php @@ -41,6 +41,10 @@ class Shell implements \PHPCI\Plugin */ public function execute() { + if (!defined('ENABLE_SHELL_PLUGIN') || !ENABLE_SHELL_PLUGIN) { + throw new \Exception('The shell plugin is not enabled.'); + } + $success = $this->phpci->executeCommand($this->command); return $success; From 40afb58ff70d006005245a621e2663133fb87d67 Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Wed, 22 May 2013 14:17:33 -0400 Subject: [PATCH 06/14] Added support for interpolation --- PHPCI/Builder.php | 61 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 5a26be8d..2043531f 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -73,6 +73,15 @@ class Builder * @var array */ protected $config; + + /** + * An array of key => value pairs that will be used for + * interpolation and environment variables + * @var array + * @see setInterpolationVars() + * @see getInterpolationVars() + */ + protected $interpolation_vars = array(); /** * Set up the builder. @@ -236,7 +245,46 @@ class Builder { $this->log("\033[0;31m" . $message . "\033[0m"); } + + /** + * Get an array key => value pairs that are used for interpolation + * @return array + */ + public function getInterpolationVars() + { + return $this->interpolation_vars; + } + + /** + * Replace every occurance of the interpolation vars in the given string + * Example: "This is build %PHPCI_BUILD%" => "This is build 182" + * @param string $input + * @return string + */ + public function interpolate($input) + { + $translations = array_walk($this->getInterpolationVars(), function($value, &$key) { + $key = '%'.$key.'%'; + }); + return strtr($input, $translations); + } + /** + * Sets the variables that will be used for interpolation. This must be run + * from setupBuild() because prior to that, we don't know the buildPath + */ + protected function setInterpolationVars() + { + $this->interpolation_vars = array( + 'PHPCI' => 1, + 'PHPCI_COMMIT' => $this->build->getCommitId(), + 'PHPCI_PROJECT' => $this->build->getProject()->getId(), + 'PHPCI_BUILD' => $this->build->getId(), + 'PHPCI_PROJECT_TITLE' => $this->build->getProject()->getTitle(), + 'PHPCI_BUILD_PATH' => $this->buildPath, + ); + } + /** * Set up a working copy of the project for building. */ @@ -247,14 +295,13 @@ class Builder $this->ciDir = realpath(dirname(__FILE__) . '/../') . '/'; $this->buildPath = $this->ciDir . 'build/' . $buildId . '/'; + $this->setInterpolationVars(); + // Setup environment vars that will be accessible during exec() - putenv("PHPCI=1"); - putenv("PHPCI_COMMIT=".$commitId); - putenv("PHPCI_PROJECT=".$this->build->getProject()->getId()); - putenv("PHPCI_BUILD=".$this->build->getId()); - putenv("PHPCI_PROJECT_TITLE=".$this->build->getProject()->getTitle()); - putenv("PHPCI_BUILD_PATH=".$this->buildPath); - + foreach ($this->getInterpolationVars() as $key => $value) { + putenv($key.'='.$value); + } + // Create a working copy of the project: if (!$this->build->createWorkingCopy($this, $this->buildPath)) { return false; From 095b7d7f14ecadf6a09e9112e44df117e3a97b9b Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Wed, 22 May 2013 14:21:17 -0400 Subject: [PATCH 07/14] Added support for interpolation in MySQL host, user, database, queries and file imports --- PHPCI/Plugin/Mysql.php | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/PHPCI/Plugin/Mysql.php b/PHPCI/Plugin/Mysql.php index e67c31a4..5138116e 100644 --- a/PHPCI/Plugin/Mysql.php +++ b/PHPCI/Plugin/Mysql.php @@ -51,8 +51,8 @@ class Mysql implements \PHPCI\Plugin if (isset($buildSettings['mysql'])) { $sql = $buildSettings['mysql']; - $this->host = !empty($sql['host']) ? $sql['host'] : $this->host; - $this->user = !empty($sql['user']) ? $sql['user'] : $this->user; + $this->host = !empty($sql['host']) ? $sql['host'] : $this->phpci->interpolate($this->host); + $this->user = !empty($sql['user']) ? $sql['user'] : $this->phpci->interpolate($this->user); $this->pass = array_key_exists('pass', $sql) ? $sql['pass'] : $this->pass; } } @@ -71,10 +71,12 @@ class Mysql implements \PHPCI\Plugin foreach ($this->queries as $query) { if (!is_array($query)) { // Simple query - $this->pdo->query($query); + $this->pdo->query($this->phpci->interpolate($query)); } else if (isset($query['import'])) { // SQL file execution $this->executeFile($query['import']); + } else { + throw new \Exception("Invalid command"); } } } catch (\Exception $ex) { @@ -88,15 +90,15 @@ class Mysql implements \PHPCI\Plugin protected function executeFile($query) { if (!isset($query['file'])) { - throw new \Exception("Import statement must contiain an 'file' key"); + throw new \Exception("Import statement must contain a 'file' key"); } - $import_file = $this->phpci->buildPath . $query['file']; + $import_file = $this->phpci->buildPath . $this->phpci->interpolate($query['file']); if (!is_readable($import_file)) { throw new \Exception("Cannot open SQL import file: $import_file"); } - $database = isset($query['database'])? $query['database']: null; + $database = isset($query['database'])? $this->phpci->interpolate($query['database']): null; $import_command = $this->getImportCommand($import_file, $database); if (!$this->phpci->executeCommand($import_command)) { From 0a755cedaee148fdd81686b5e125d0db1843017c Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Wed, 22 May 2013 15:17:54 -0400 Subject: [PATCH 08/14] array_walk doesn't alter keys, fixed --- PHPCI/Builder.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/PHPCI/Builder.php b/PHPCI/Builder.php index 2043531f..a7b60bc1 100644 --- a/PHPCI/Builder.php +++ b/PHPCI/Builder.php @@ -263,10 +263,11 @@ class Builder */ public function interpolate($input) { - $translations = array_walk($this->getInterpolationVars(), function($value, &$key) { - $key = '%'.$key.'%'; - }); - return strtr($input, $translations); + $trans_table = array(); + foreach ($this->getInterpolationVars() as $key => $value) { + $trans_table['%'.$key.'%'] = $value; + } + return strtr($input, $trans_table); } /** From d7c62f36092e62cad1e6ffb53ef6dc4e88fab6ff Mon Sep 17 00:00:00 2001 From: Steve Kamerman Date: Wed, 22 May 2013 15:54:18 -0400 Subject: [PATCH 09/14] Added interpolation support to Env plugin --- PHPCI/Plugin/Env.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Plugin/Env.php b/PHPCI/Plugin/Env.php index 1de016fb..e09d3dbf 100644 --- a/PHPCI/Plugin/Env.php +++ b/PHPCI/Plugin/Env.php @@ -41,7 +41,7 @@ class Env implements \PHPCI\Plugin $env_var = "$key=$value"; } - if (!putenv($env_var)) { + if (!putenv($this->phpci->interpolate($env_var))) { $success = false; $this->phpci->logFailure("Unable to set environment variable"); } From 81b2f89435dd54f5c2dee982223243cfc9576455 Mon Sep 17 00:00:00 2001 From: Gabriel Baker Date: Wed, 22 May 2013 21:43:19 +0100 Subject: [PATCH 10/14] PHP CS Fixer and indentation fix --- PHPCI/Plugin/PhpCsFixer.php | 89 +++++++++++++++++++++++++++++++++++++ composer.json | 35 ++++++++------- 2 files changed, 107 insertions(+), 17 deletions(-) create mode 100644 PHPCI/Plugin/PhpCsFixer.php diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php new file mode 100644 index 00000000..571a7e8d --- /dev/null +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -0,0 +1,89 @@ + +* @package PHPCI +* @subpackage Plugins +*/ +class PhpCsFixer implements \PHPCI\Plugin +{ + protected $phpci; + + protected $args = ''; + + protected $workingDir = ''; + protected $level = 'all'; + protected $dryRun = true; + protected $verbose = false; + protected $diff = false; + protected $levels = array('psr0', 'psr1', 'psr2', 'all'); + + public function __construct(\PHPCI\Builder $phpci, array $options = array()) + { + $this->phpci = $phpci; + $this->workingdir = $this->phpci->buildPath; + $this->buildArgs($options); + } + + public function execute() + { + $success = false; + + $curdir = getcwd(); + chdir($this->workingdir); + + $cmd = PHPCI_BIN_DIR . 'php-cs-fixer fix . %s'; + $success = $this->phpci->executeCommand($cmd, $this->args); + + chdir($curdir); + + return $success; + } + + public function buildArgs($options) + { + $argstring = ""; + + if ( array_key_exists('verbose', $options) && $options['verbose'] ) + { + $this->verbose = true; + $this->args .= ' --verbose'; + } + + if ( array_key_exists('diff', $options) && $options['diff'] ) + { + $this->diff = true; + $this->args .= ' --diff'; + } + + if ( array_key_exists('level', $options) && array_key_exists($options['level'], $this->levels) ) + { + $this->level = $options['level']; + $this->args .= ' --level='.$options['level']; + } + + if ( array_key_exists('dryrun', $options) && $options['dryrun'] ) + { + $this->dryRun = true; + $this->args .= ' --dry-run'; + } + + if ( array_key_exists('workingdir', $options) + && $options['workingdir'] + && is_dir($this->phpci->buildPath.$options['workingdir']) ) + { + $this->workingdir = $this->phpci->buildPath.$options['workingdir']; + } + + } +} \ No newline at end of file diff --git a/composer.json b/composer.json index 03e9ec38..7b8c37b3 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,37 @@ { - "name": "block8/phpci", - "description": "Simple continuous integration for PHP projects.", + "name" : "block8/phpci", + "description" : "Simple continuous integration for PHP projects.", "minimum-stability": "dev", - "type": "library", - "keywords": ["php", "phpci", "ci", "continuous", "integration", "testing", "phpunit", "continuous integration", "jenkins", "travis"], - "homepage": "http://www.phptesting.org/", - "license": "BSD-2-Clause", + "type" : "library", + "keywords" : ["php", "phpci", "ci", "continuous", "integration", "testing", "phpunit", "continuous integration", "jenkins", "travis"], + "homepage" : "http://www.phptesting.org/", + "license" : "BSD-2-Clause", "authors": [ { - "name": "Dan Cryer", - "email": "dan.cryer@block8.co.uk", + "name" : "Dan Cryer", + "email" : "dan.cryer@block8.co.uk", "homepage": "http://www.block8.co.uk", - "role": "Developer" + "role" : "Developer" } ], "support": { - "email": "hello+phpci@block8.co.uk", + "email" : "hello+phpci@block8.co.uk", "issues": "https://github.com/Block8/PHPCI/issues", "source": "https://github.com/Block8/PHPCI" }, "require": { - "block8/b8framework": "dev-master", - "phpunit/phpunit": "3.*", - "phpmd/phpmd" : "1.*", - "sebastian/phpcpd": "1.*", + "block8/b8framework" : "dev-master", + "phpunit/phpunit" : "3.*", + "phpmd/phpmd" : "1.*", + "sebastian/phpcpd" : "1.*", "squizlabs/php_codesniffer": "1.*", "ircmaxell/password-compat": "1.x", - "phpspec/phpspec": "2.*", - "symfony/yaml": "2.2.x-dev", - "symfony/console": "2.2.*" + "phpspec/phpspec" : "2.*", + "symfony/yaml" : "2.2.x-dev", + "symfony/console" : "2.2.*", + "fabpot/php-cs-fixer" : "0.3.*@dev" } } From be13ec90eeb5c1f5690081f79d74f4a856cab7d2 Mon Sep 17 00:00:00 2001 From: Gabriel Baker Date: Wed, 22 May 2013 21:53:56 +0100 Subject: [PATCH 11/14] indentation --- PHPCI/Plugin/PhpCsFixer.php | 70 ++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php index 571a7e8d..b4d298e9 100644 --- a/PHPCI/Plugin/PhpCsFixer.php +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -21,14 +21,14 @@ class PhpCsFixer implements \PHPCI\Plugin protected $args = ''; - protected $workingDir = ''; - protected $level = 'all'; - protected $dryRun = true; - protected $verbose = false; - protected $diff = false; - protected $levels = array('psr0', 'psr1', 'psr2', 'all'); + protected $workingDir = ''; + protected $level = 'all'; + protected $dryRun = true; + protected $verbose = false; + protected $diff = false; + protected $levels = array('psr0', 'psr1', 'psr2', 'all'); - public function __construct(\PHPCI\Builder $phpci, array $options = array()) + public function __construct(\PHPCI\Builder $phpci, array $options = array()) { $this->phpci = $phpci; $this->workingdir = $this->phpci->buildPath; @@ -39,7 +39,7 @@ class PhpCsFixer implements \PHPCI\Plugin { $success = false; - $curdir = getcwd(); + $curdir = getcwd(); chdir($this->workingdir); $cmd = PHPCI_BIN_DIR . 'php-cs-fixer fix . %s'; @@ -52,38 +52,38 @@ class PhpCsFixer implements \PHPCI\Plugin public function buildArgs($options) { - $argstring = ""; + $argstring = ""; - if ( array_key_exists('verbose', $options) && $options['verbose'] ) - { - $this->verbose = true; - $this->args .= ' --verbose'; - } + if ( array_key_exists('verbose', $options) && $options['verbose'] ) + { + $this->verbose = true; + $this->args .= ' --verbose'; + } - if ( array_key_exists('diff', $options) && $options['diff'] ) - { - $this->diff = true; - $this->args .= ' --diff'; - } + if ( array_key_exists('diff', $options) && $options['diff'] ) + { + $this->diff = true; + $this->args .= ' --diff'; + } - if ( array_key_exists('level', $options) && array_key_exists($options['level'], $this->levels) ) - { - $this->level = $options['level']; - $this->args .= ' --level='.$options['level']; - } + if ( array_key_exists('level', $options) && array_key_exists($options['level'], $this->levels) ) + { + $this->level = $options['level']; + $this->args .= ' --level='.$options['level']; + } - if ( array_key_exists('dryrun', $options) && $options['dryrun'] ) - { - $this->dryRun = true; - $this->args .= ' --dry-run'; - } + if ( array_key_exists('dryrun', $options) && $options['dryrun'] ) + { + $this->dryRun = true; + $this->args .= ' --dry-run'; + } - if ( array_key_exists('workingdir', $options) - && $options['workingdir'] - && is_dir($this->phpci->buildPath.$options['workingdir']) ) - { - $this->workingdir = $this->phpci->buildPath.$options['workingdir']; - } + if ( array_key_exists('workingdir', $options) + && $options['workingdir'] + && is_dir($this->phpci->buildPath.$options['workingdir']) ) + { + $this->workingdir = $this->phpci->buildPath.$options['workingdir']; + } } } \ No newline at end of file From efcf209478db6c29456f989e108cece6c4a841b8 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 22:11:36 +0100 Subject: [PATCH 12/14] Fixing project overview --- PHPCI/Store/BuildStore.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PHPCI/Store/BuildStore.php b/PHPCI/Store/BuildStore.php index 03b1ad28..6b26c3c7 100644 --- a/PHPCI/Store/BuildStore.php +++ b/PHPCI/Store/BuildStore.php @@ -21,7 +21,7 @@ class BuildStore extends BuildStoreBase { public function getBuildSummary() { - $query = 'SELECT COUNT(*) AS cnt FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC'; + $query = 'SELECT COUNT(*) AS cnt FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC, b.id DESC'; $stmt = \b8\Database::getConnection('read')->prepare($query); if ($stmt->execute()) { @@ -31,7 +31,7 @@ class BuildStore extends BuildStoreBase $count = 0; } - $query = 'SELECT * FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC'; + $query = 'SELECT b.* FROM build b LEFT JOIN project p on p.id = b.project_id GROUP BY b.project_id ORDER BY p.title ASC, b.id DESC'; $stmt = \b8\Database::getConnection('read')->prepare($query); if ($stmt->execute()) { From 6e3df00f62664a62538ab0c75401353b439bfb95 Mon Sep 17 00:00:00 2001 From: Dan Cryer Date: Wed, 22 May 2013 22:21:29 +0100 Subject: [PATCH 13/14] Removing broken Registry stuff (as registry is now deprecated in b8framework) - Fixes #58 --- PHPCI/Command/InstallCommand.php | 4 ++-- bootstrap.php | 2 ++ index.php | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/PHPCI/Command/InstallCommand.php b/PHPCI/Command/InstallCommand.php index 2549e5cc..18e600b4 100644 --- a/PHPCI/Command/InstallCommand.php +++ b/PHPCI/Command/InstallCommand.php @@ -62,8 +62,8 @@ b8\Database::setDetails('{$dbName}', '{$dbUser}', '{$dbPass}'); b8\Database::setWriteServers(array('{$dbHost}')); b8\Database::setReadServers(array('{$dbHost}')); -\$registry = b8\Registry::getInstance(); -\$registry->set('install_url', '{$ciUrl}'); +\$config = b8\Config::getInstance(); +\$config->set('install_url', '{$ciUrl}'); "; // Has the user entered Github app details? If so add those to config: diff --git a/bootstrap.php b/bootstrap.php index 4704260f..08fe30d7 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -37,6 +37,8 @@ require_once(APPLICATION_PATH . 'vendor/autoload.php'); // Load configuration if present: $config = new b8\Config(); +$request = new b8\Http\Request(); +$registry = new b8\Registry($config, $request); if (file_exists(APPLICATION_PATH . 'config.php')) { require(APPLICATION_PATH . 'config.php'); diff --git a/index.php b/index.php index 4f42e24f..cab4239d 100644 --- a/index.php +++ b/index.php @@ -14,5 +14,5 @@ ini_set('display_errors', 'on'); require_once('bootstrap.php'); -$fc = new PHPCI\Application(b8\Config::getInstance()); +$fc = new PHPCI\Application($config, $request); print $fc->handleRequest(); From e342483f03307687047f8410e9f97a7b3c52b78e Mon Sep 17 00:00:00 2001 From: Gabriel Baker Date: Thu, 23 May 2013 06:36:40 +0100 Subject: [PATCH 14/14] This should be checking the value not the key --- PHPCI/Plugin/PhpCsFixer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PHPCI/Plugin/PhpCsFixer.php b/PHPCI/Plugin/PhpCsFixer.php index b4d298e9..9aaa7536 100644 --- a/PHPCI/Plugin/PhpCsFixer.php +++ b/PHPCI/Plugin/PhpCsFixer.php @@ -66,7 +66,7 @@ class PhpCsFixer implements \PHPCI\Plugin $this->args .= ' --diff'; } - if ( array_key_exists('level', $options) && array_key_exists($options['level'], $this->levels) ) + if ( array_key_exists('level', $options) && in_array($options['level'], $this->levels) ) { $this->level = $options['level']; $this->args .= ' --level='.$options['level'];