Refactored Controllers.

This commit is contained in:
Dmitry Khomutov 2018-03-13 20:09:54 +07:00
parent 7abd3febc1
commit ba0d9f14fa
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
20 changed files with 512 additions and 512 deletions

View file

@ -21,7 +21,7 @@ class Application
protected $route; protected $route;
/** /**
* @var Controller * @var Controller|WebController
*/ */
protected $controller; protected $controller;
@ -30,11 +30,6 @@ class Application
*/ */
protected $request; protected $request;
/**
* @var Response
*/
protected $response;
/** /**
* @var Config * @var Config
*/ */
@ -53,7 +48,6 @@ class Application
public function __construct(Config $config, Request $request = null) public function __construct(Config $config, Request $request = null)
{ {
$this->config = $config; $this->config = $config;
$this->response = new Response();
if (!is_null($request)) { if (!is_null($request)) {
$this->request = $request; $this->request = $request;
@ -128,8 +122,9 @@ class Application
if (!empty($this->route['callback'])) { if (!empty($this->route['callback'])) {
$callback = $this->route['callback']; $callback = $this->route['callback'];
if (!$callback($this->route, $this->response)) { $response = new Response();
return $this->response; if (!$callback($this->route, $response)) {
return $response;
} }
} }
@ -153,33 +148,30 @@ class Application
public function handleRequest() public function handleRequest()
{ {
try { try {
$this->response = $this->handleRequestInner(); $response = $this->handleRequestInner();
} catch (HttpException $ex) { } catch (HttpException $ex) {
$this->config->set('page_title', 'Error'); $this->config->set('page_title', 'Error');
$view = new View('exception'); $view = new View('exception');
$view->exception = $ex; $view->exception = $ex;
$this->response->setResponseCode($ex->getErrorCode()); $response = new Response();
$this->response->setContent($view->render());
$response->setResponseCode($ex->getErrorCode());
$response->setContent($view->render());
} catch (\Exception $ex) { } catch (\Exception $ex) {
$this->config->set('page_title', 'Error'); $this->config->set('page_title', 'Error');
$view = new View('exception'); $view = new View('exception');
$view->exception = $ex; $view->exception = $ex;
$this->response->setResponseCode(500); $response = new Response();
$this->response->setContent($view->render());
$response->setResponseCode(500);
$response->setContent($view->render());
} }
if ($this->response->hasLayout() && $this->controller && $this->controller->layout) { return $response;
$this->setLayoutVariables($this->controller->layout);
$this->controller->layout->content = $this->response->getContent();
$this->response->setContent($this->controller->layout->render());
}
return $this->response;
} }
/** /**
@ -192,40 +184,13 @@ class Application
protected function loadController($class) protected function loadController($class)
{ {
/** @var Controller $controller */ /** @var Controller $controller */
$controller = new $class($this->config, $this->request, $this->response); $controller = new $class($this->config, $this->request);
$controller->init(); $controller->init();
$controller->layout = new View('layout');
$controller->layout->title = 'PHP Censor';
$controller->layout->breadcrumb = [];
$controller->layout->version = trim(file_get_contents(ROOT_DIR . 'VERSION.md'));
return $controller; return $controller;
} }
/**
* Injects variables into the layout before rendering it.
*
* @param View $layout
*/
protected function setLayoutVariables(View &$layout)
{
$groups = [];
$groupStore = Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) {
$thisGroup = ['title' => $group->getTitle()];
$projects = Factory::getStore('Project')->getByGroupId($group->getId(), false);
$thisGroup['projects'] = $projects['items'];
$groups[] = $thisGroup;
}
$archivedProjects = Factory::getStore('Project')->getAll(true);
$layout->archived_projects = $archivedProjects['items'];
$layout->groups = $groups;
}
/** /**
* Check whether we should skip auth (because it is disabled) * Check whether we should skip auth (because it is disabled)
* *

View file

@ -2,171 +2,35 @@
namespace PHPCensor; namespace PHPCensor;
use PHPCensor\Exception\HttpException\ForbiddenException;
use PHPCensor\Http\Request; use PHPCensor\Http\Request;
use PHPCensor\Http\Response; use PHPCensor\Http\Response;
use PHPCensor\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Store\UserStore;
class Controller abstract class Controller
{ {
/** /**
* @var Request * @var Request
*/ */
protected $request; protected $request;
/**
* @var Response
*/
protected $response;
/** /**
* @var Config * @var Config
*/ */
protected $config; protected $config;
/** /**
* @var View * @param Config $config
* @param Request $request
*/ */
protected $controllerView; public function __construct(Config $config, Request $request)
{
/** $this->config = $config;
* @var View $this->request = $request;
*/ }
protected $view;
/**
* @var string
*/
protected $className;
/**
* @var View
*/
public $layout;
/** /**
* Initialise the controller. * Initialise the controller.
*/ */
public function init() abstract public function init();
{
// Extended by actual controllers.
}
/**
* @param Config $config
* @param Request $request
* @param Response $response
*/
public function __construct(Config $config, Request $request, Response $response)
{
$this->config = $config;
$this->request = $request;
$this->response = $response;
$class = explode('\\', get_class($this));
$this->className = substr(array_pop($class), 0, -10);
$this->setControllerView();
if (!empty($_SESSION['php-censor-user'])) {
unset($_SESSION['php-censor-user']);
}
}
/**
* Set the view that this controller should use.
*/
protected function setControllerView()
{
if (View::exists($this->className)) {
$this->controllerView = new View($this->className);
} else {
$this->controllerView = new View('{@content}');
}
}
/**
* Set the view that this controller action should use.
*
* @param string $action
*/
protected function setView($action)
{
if (View::exists($this->className . '/' . $action)) {
$this->view = new View($this->className . '/' . $action);
}
}
/**
* Handle the incoming request.
*
* @param string $action
* @param array $actionParams
*
* @return Response
*/
public function handleAction($action, $actionParams)
{
$this->setView($action);
$response = call_user_func_array([$this, $action], $actionParams);
if ($response instanceof Response) {
return $response;
}
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;
}
/**
* Require that the currently logged in user is an administrator.
*
* @throws ForbiddenException
*/
protected function requireAdmin()
{
if (!$this->currentUserIsAdmin()) {
throw new ForbiddenException('You do not have permission to do that.');
}
}
/**
* Check if the currently logged in user is an administrator.
*
* @return boolean
*/
protected function currentUserIsAdmin()
{
$user = $this->getUser();
if (!$user) {
return false;
}
return $this->getUser()->getIsAdmin();
}
/**
* @return User|null
*/
protected function getUser()
{
if (empty($_SESSION['php-censor-user-id'])) {
return null;
}
/** @var UserStore $userStore */
$userStore = Factory::getStore('User');
return $userStore->getById($_SESSION['php-censor-user-id']);
}
/** /**
* @param string $name * @param string $name
@ -186,6 +50,19 @@ class Controller
return false; return false;
} }
/**
* Handles an action on this controller and returns a Response object.
*
* @param string $action
* @param array $actionParams
*
* @return Response
*/
public function handleAction($action, $actionParams)
{
return call_user_func_array([$this, $action], $actionParams);
}
/** /**
* Get a hash of incoming request parameters ($_GET, $_POST) * Get a hash of incoming request parameters ($_GET, $_POST)
* *

View file

@ -12,7 +12,7 @@ use PHPCensor\Http\Response\RedirectResponse;
use PHPCensor\Model\Build; use PHPCensor\Model\Build;
use PHPCensor\Model\User; use PHPCensor\Model\User;
use PHPCensor\Service\BuildService; use PHPCensor\Service\BuildService;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\View; use PHPCensor\View;
use PHPCensor\Store\Factory; use PHPCensor\Store\Factory;
@ -21,8 +21,13 @@ use PHPCensor\Store\Factory;
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class BuildController extends Controller class BuildController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layout';
/** /**
* @var \PHPCensor\Store\BuildStore * @var \PHPCensor\Store\BuildStore
*/ */
@ -33,11 +38,10 @@ class BuildController extends Controller
*/ */
protected $buildService; protected $buildService;
/**
* Initialise the controller, set up stores and services.
*/
public function init() public function init()
{ {
parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
$this->buildService = new BuildService($this->buildStore); $this->buildService = new BuildService($this->buildStore);
} }

View file

@ -10,27 +10,33 @@ use PHPCensor\BuildFactory;
use PHPCensor\Model\Project; use PHPCensor\Model\Project;
use PHPCensor\Model\Build; use PHPCensor\Model\Build;
use PHPCensor\Service\BuildStatusService; use PHPCensor\Service\BuildStatusService;
use PHPCensor\Controller; use PHPCensor\WebController;
/** /**
* Build Status Controller - Allows external access to build status information / images. * Build Status Controller - Allows external access to build status information / images.
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class BuildStatusController extends Controller class BuildStatusController extends WebController
{ {
/* @var \PHPCensor\Store\ProjectStore */ /**
protected $projectStore; * @var string
*/
/* @var \PHPCensor\Store\BuildStore */ public $layoutName = 'layoutPublic';
protected $buildStore;
/** /**
* Initialise the controller, set up stores and services. * @var \PHPCensor\Store\ProjectStore
*/ */
protected $projectStore;
/**
* @var \PHPCensor\Store\BuildStore
*/
protected $buildStore;
public function init() public function init()
{ {
$this->response->disableLayout(); parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project'); $this->projectStore = Factory::getStore('Project');
@ -74,7 +80,7 @@ class BuildStatusController extends Controller
* *
* @param $projectId * @param $projectId
* *
* @return bool * @return Response
* *
* @throws \Exception * @throws \Exception
*/ */
@ -114,16 +120,16 @@ class BuildStatusController extends Controller
/** /**
* @param \SimpleXMLElement $xml * @param \SimpleXMLElement $xml
* *
* @return boolean * @return Response
*/ */
protected function renderXml(\SimpleXMLElement $xml = null) protected function renderXml(\SimpleXMLElement $xml = null)
{ {
$this->response->setHeader('Content-Type', 'text/xml'); $response = new Response();
$this->response->setContent($xml->asXML());
$this->response->flush();
echo $xml->asXML();
return true; $response->setHeader('Content-Type', 'text/xml');
$response->setContent($xml->asXML());
return $response;
} }
/** /**
@ -179,11 +185,12 @@ class BuildStatusController extends Controller
$image = file_get_contents($cacheFile); $image = file_get_contents($cacheFile);
$this->response->disableLayout(); $response = new Response();
$this->response->setHeader('Content-Type', 'image/svg+xml');
$this->response->setContent($image);
return $this->response; $response->setHeader('Content-Type', 'image/svg+xml');
$response->setContent($image);
return $response;
} }
/** /**

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Controller; namespace PHPCensor\Controller;
use PHPCensor\Form; use PHPCensor\Form;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Http\Response\RedirectResponse; use PHPCensor\Http\Response\RedirectResponse;
use PHPCensor\Model\ProjectGroup; use PHPCensor\Model\ProjectGroup;
use PHPCensor\Helper\Lang; use PHPCensor\Helper\Lang;
@ -15,18 +15,22 @@ use PHPCensor\Store\Factory;
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class GroupController extends Controller class GroupController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layout';
/** /**
* @var \PHPCensor\Store\ProjectGroupStore * @var \PHPCensor\Store\ProjectGroupStore
*/ */
protected $groupStore; protected $groupStore;
/**
* Set up this controller.
*/
public function init() public function init()
{ {
parent::init();
$this->groupStore = Factory::getStore('ProjectGroup'); $this->groupStore = Factory::getStore('ProjectGroup');
} }

View file

@ -4,13 +4,18 @@ namespace PHPCensor\Controller;
use PHPCensor\Config; use PHPCensor\Config;
use PHPCensor\Helper\Lang; use PHPCensor\Helper\Lang;
use PHPCensor\Controller; use PHPCensor\WebController;
/** /**
* Home Controller - Displays the Dashboard. * Home Controller - Displays the Dashboard.
*/ */
class HomeController extends Controller class HomeController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layout';
/** /**
* Display dashboard: * Display dashboard:
*/ */

View file

@ -17,14 +17,20 @@ use PHPCensor\Http\Response\RedirectResponse;
use PHPCensor\View; use PHPCensor\View;
use PHPCensor\Store\Factory; use PHPCensor\Store\Factory;
use PHPCensor\Model\Project; use PHPCensor\Model\Project;
use PHPCensor\WebController;
/** /**
* Project Controller - Allows users to create, edit and view projects. * Project Controller - Allows users to create, edit and view projects.
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class ProjectController extends PHPCensor\Controller class ProjectController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layout';
/** /**
* @var \PHPCensor\Store\ProjectStore * @var \PHPCensor\Store\ProjectStore
*/ */
@ -50,6 +56,8 @@ class ProjectController extends PHPCensor\Controller
*/ */
public function init() public function init()
{ {
parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project'); $this->projectStore = Factory::getStore('Project');
$this->projectService = new ProjectService($this->projectStore); $this->projectService = new ProjectService($this->projectStore);
@ -69,10 +77,10 @@ class ProjectController extends PHPCensor\Controller
$perPage = (integer)$this->getParam('per_page', 10); $perPage = (integer)$this->getParam('per_page', 10);
$builds = $this->getLatestBuildsHtml($projectId, $branch, $environment, (($page - 1) * $perPage), $perPage); $builds = $this->getLatestBuildsHtml($projectId, $branch, $environment, (($page - 1) * $perPage), $perPage);
$this->response->disableLayout(); $response = new PHPCensor\Http\Response();
$this->response->setContent($builds[0]); $response->setContent($builds[0]);
return $this->response; return $response;
} }
/** /**
@ -327,10 +335,10 @@ class ProjectController extends PHPCensor\Controller
'ssh_private_key' => $this->getParam('key', null), 'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null), 'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null), 'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', 0), 'allow_public_status' => (boolean)$this->getParam('allow_public_status', 0),
'branch' => $this->getParam('branch', null), 'branch' => $this->getParam('branch', null),
'default_branch_only' => $this->getParam('default_branch_only', 0), 'default_branch_only' => (boolean)$this->getParam('default_branch_only', 0),
'group' => $this->getParam('group_id', null), 'group' => (integer)$this->getParam('group_id', null),
'environments' => $this->getParam('environments', null), 'environments' => $this->getParam('environments', null),
]; ];
@ -380,11 +388,11 @@ class ProjectController extends PHPCensor\Controller
$form = $this->projectForm($values, 'edit/' . $projectId); $form = $this->projectForm($values, 'edit/' . $projectId);
if ($method != 'POST' || ($method == 'POST' && !$form->validate())) { if ($method != 'POST' || ($method == 'POST' && !$form->validate())) {
$view = new View('Project/edit'); $view = new View('Project/edit');
$view->type = 'edit'; $view->type = 'edit';
$view->project = $project; $view->project = $project;
$view->form = $form; $view->form = $form;
$view->key = $values['pubkey']; $view->key = $values['pubkey'];
return $view->render(); return $view->render();
} }
@ -397,11 +405,11 @@ class ProjectController extends PHPCensor\Controller
'ssh_private_key' => $this->getParam('key', null), 'ssh_private_key' => $this->getParam('key', null),
'ssh_public_key' => $this->getParam('pubkey', null), 'ssh_public_key' => $this->getParam('pubkey', null),
'build_config' => $this->getParam('build_config', null), 'build_config' => $this->getParam('build_config', null),
'allow_public_status' => $this->getParam('allow_public_status', false), 'allow_public_status' => (boolean)$this->getParam('allow_public_status', false),
'archived' => $this->getParam('archived', false), 'archived' => (boolean)$this->getParam('archived', false),
'branch' => $this->getParam('branch', null), 'branch' => $this->getParam('branch', null),
'default_branch_only' => $this->getParam('default_branch_only', false), 'default_branch_only' => (boolean)$this->getParam('default_branch_only', false),
'group' => $this->getParam('group_id', null), 'group' => (integer)$this->getParam('group_id', null),
'environments' => $this->getParam('environments', null), 'environments' => $this->getParam('environments', null),
]; ];

View file

@ -5,7 +5,7 @@ namespace PHPCensor\Controller;
use PHPCensor\Form\Element\Csrf; use PHPCensor\Form\Element\Csrf;
use PHPCensor\Helper\Email; use PHPCensor\Helper\Email;
use PHPCensor\Helper\Lang; use PHPCensor\Helper\Lang;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Http\Response\RedirectResponse; use PHPCensor\Http\Response\RedirectResponse;
use PHPCensor\Security\Authentication\Service; use PHPCensor\Security\Authentication\Service;
use PHPCensor\Store\UserStore; use PHPCensor\Store\UserStore;
@ -16,8 +16,13 @@ use PHPCensor\Store\Factory;
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class SessionController extends Controller class SessionController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layoutSession';
/** /**
* @var UserStore * @var UserStore
*/ */
@ -33,7 +38,7 @@ class SessionController extends Controller
*/ */
public function init() public function init()
{ {
$this->response->disableLayout(); parent::init();
$this->userStore = Factory::getStore('User'); $this->userStore = Factory::getStore('User');
$this->authentication = Service::getInstance(); $this->authentication = Service::getInstance();

View file

@ -5,7 +5,7 @@ namespace PHPCensor\Controller;
use PHPCensor\Config; use PHPCensor\Config;
use PHPCensor\Exception\HttpException\NotFoundException; use PHPCensor\Exception\HttpException\NotFoundException;
use PHPCensor\Form; use PHPCensor\Form;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Helper\Lang; use PHPCensor\Helper\Lang;
use PHPCensor\Http\Response\RedirectResponse; use PHPCensor\Http\Response\RedirectResponse;
use PHPCensor\Model\User; use PHPCensor\Model\User;
@ -18,8 +18,13 @@ use PHPCensor\Store\Factory;
* *
* @author Dan Cryer <dan@block8.co.uk> * @author Dan Cryer <dan@block8.co.uk>
*/ */
class UserController extends Controller class UserController extends WebController
{ {
/**
* @var string
*/
public $layoutName = 'layout';
/** /**
* @var \PHPCensor\Store\UserStore * @var \PHPCensor\Store\UserStore
*/ */
@ -35,6 +40,8 @@ class UserController extends Controller
*/ */
public function init() public function init()
{ {
parent::init();
$this->userStore = Factory::getStore('User'); $this->userStore = Factory::getStore('User');
$this->userService = new UserService($this->userStore); $this->userService = new UserService($this->userStore);
} }
@ -70,7 +77,7 @@ class UserController extends Controller
$language = null; $language = null;
} }
$perPage = $this->getParam('per_page', null); $perPage = (integer)$this->getParam('per_page', null);
if (!$perPage) { if (!$perPage) {
$perPage = null; $perPage = null;
} }
@ -183,7 +190,7 @@ class UserController extends Controller
$name = $this->getParam('name', null); $name = $this->getParam('name', null);
$email = $this->getParam('email', null); $email = $this->getParam('email', null);
$password = $this->getParam('password', null); $password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0); $isAdmin = (boolean)$this->getParam('is_admin', 0);
$this->userService->createUser($name, $email, 'internal', ['type' => 'internal'], $password, $isAdmin); $this->userService->createUser($name, $email, 'internal', ['type' => 'internal'], $password, $isAdmin);
@ -224,7 +231,7 @@ class UserController extends Controller
$name = $this->getParam('name', null); $name = $this->getParam('name', null);
$email = $this->getParam('email', null); $email = $this->getParam('email', null);
$password = $this->getParam('password', null); $password = $this->getParam('password', null);
$isAdmin = (int)$this->getParam('is_admin', 0); $isAdmin = (boolean)$this->getParam('is_admin', 0);
$this->userService->updateUser($user, $name, $email, $password, $isAdmin); $this->userService->updateUser($user, $name, $email, $password, $isAdmin);

View file

@ -43,18 +43,6 @@ class WebhookController extends Controller
*/ */
protected $buildService; protected $buildService;
/**
* @param Config $config
* @param Request $request
* @param Response $response
*/
public function __construct(Config $config, Request $request, Response $response)
{
$this->config = $config;
$this->request = $request;
$this->response = $response;
}
/** /**
* Initialise the controller, set up stores and services. * Initialise the controller, set up stores and services.
*/ */
@ -77,7 +65,7 @@ class WebhookController extends Controller
{ {
$response = new Response\JsonResponse(); $response = new Response\JsonResponse();
try { try {
$data = call_user_func_array([$this, $action], $actionParams); $data = parent::handleAction($action, $actionParams);
if (isset($data['responseCode'])) { if (isset($data['responseCode'])) {
$response->setResponseCode($data['responseCode']); $response->setResponseCode($data['responseCode']);
unset($data['responseCode']); unset($data['responseCode']);

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Controller; namespace PHPCensor\Controller;
use PHPCensor\Model\Build; use PHPCensor\Model\Build;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Store\Factory; use PHPCensor\Store\Factory;
use PHPCensor\View; use PHPCensor\View;
use PHPCensor\Model\Project; use PHPCensor\Model\Project;
@ -15,7 +15,7 @@ use PHPCensor\Store\ProjectGroupStore;
/** /**
* Widget All Projects Controller * Widget All Projects Controller
*/ */
class WidgetAllProjectsController extends Controller class WidgetAllProjectsController extends WebController
{ {
/** /**
* @var BuildStore * @var BuildStore
@ -37,6 +37,8 @@ class WidgetAllProjectsController extends Controller
*/ */
public function init() public function init()
{ {
parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project'); $this->projectStore = Factory::getStore('Project');
$this->groupStore = Factory::getStore('ProjectGroup'); $this->groupStore = Factory::getStore('ProjectGroup');
@ -49,10 +51,10 @@ class WidgetAllProjectsController extends Controller
{ {
$this->view->groups = $this->getGroupInfo(); $this->view->groups = $this->getGroupInfo();
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->view->render()); $response->setContent($this->view->render());
return $this->response; return $response;
} }
/** /**
@ -142,9 +144,9 @@ class WidgetAllProjectsController extends Controller
$this->view->failed = $this->buildStore->getLastBuildByStatus($projectId, Build::STATUS_FAILED); $this->view->failed = $this->buildStore->getLastBuildByStatus($projectId, Build::STATUS_FAILED);
$this->view->counts = $counts; $this->view->counts = $counts;
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->view->render()); $response->setContent($this->view->render());
return $this->response; return $response;
} }
} }

View file

@ -5,14 +5,14 @@ namespace PHPCensor\Controller;
use PHPCensor\Store\Factory; use PHPCensor\Store\Factory;
use PHPCensor\View; use PHPCensor\View;
use PHPCensor\Http\Response; use PHPCensor\Http\Response;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Store\BuildStore; use PHPCensor\Store\BuildStore;
use PHPCensor\Store\ProjectStore; use PHPCensor\Store\ProjectStore;
/** /**
* Widget Build Errors Controller * Widget Build Errors Controller
*/ */
class WidgetBuildErrorsController extends Controller class WidgetBuildErrorsController extends WebController
{ {
/** /**
* @var BuildStore * @var BuildStore
@ -29,6 +29,8 @@ class WidgetBuildErrorsController extends Controller
*/ */
public function init() public function init()
{ {
parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project'); $this->projectStore = Factory::getStore('Project');
} }
@ -42,10 +44,10 @@ class WidgetBuildErrorsController extends Controller
$this->view->projects = $this->renderAllProjectsLatestBuilds($view); $this->view->projects = $this->renderAllProjectsLatestBuilds($view);
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->view->render()); $response->setContent($this->view->render());
return $this->response; return $response;
} }
/** /**
@ -53,10 +55,10 @@ class WidgetBuildErrorsController extends Controller
*/ */
public function update() public function update()
{ {
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->renderAllProjectsLatestBuilds($this->view)); $response->setContent($this->renderAllProjectsLatestBuilds($this->view));
return $this->response; return $response;
} }
/** /**

View file

@ -6,13 +6,13 @@ use PHPCensor\Store\Factory;
use PHPCensor\View; use PHPCensor\View;
use PHPCensor\Http\Response; use PHPCensor\Http\Response;
use PHPCensor\BuildFactory; use PHPCensor\BuildFactory;
use PHPCensor\Controller; use PHPCensor\WebController;
use PHPCensor\Store\BuildStore; use PHPCensor\Store\BuildStore;
/** /**
* Widget Last Builds Controller * Widget Last Builds Controller
*/ */
class WidgetLastBuildsController extends Controller class WidgetLastBuildsController extends WebController
{ {
/** /**
* @var BuildStore * @var BuildStore
@ -24,6 +24,8 @@ class WidgetLastBuildsController extends Controller
*/ */
public function init() public function init()
{ {
parent::init();
$this->buildStore = Factory::getStore('Build'); $this->buildStore = Factory::getStore('Build');
} }
@ -43,10 +45,10 @@ class WidgetLastBuildsController extends Controller
$view->builds = $builds; $view->builds = $builds;
$this->view->timeline = $view->render(); $this->view->timeline = $view->render();
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->view->render()); $response->setContent($this->view->render());
return $this->response; return $response;
} }
/** /**
@ -62,9 +64,9 @@ class WidgetLastBuildsController extends Controller
$this->view->builds = $builds; $this->view->builds = $builds;
$this->response->disableLayout(); $response = new Response();
$this->response->setContent($this->view->render()); $response->setContent($this->view->render());
return $this->response; return $response;
} }
} }

View file

@ -13,21 +13,6 @@ class Response
} }
} }
public function hasLayout()
{
return !isset($this->data['layout']) ? true : $this->data['layout'];
}
public function disableLayout()
{
$this->data['layout'] = false;
}
public function enableLayout()
{
$this->data['layout'] = true;
}
public function getData() public function getData()
{ {
return $this->data; return $this->data;

View file

@ -14,11 +14,6 @@ class JsonResponse extends Response
$this->setHeader('Content-Type', 'application/json'); $this->setHeader('Content-Type', 'application/json');
} }
public function hasLayout()
{
return false;
}
protected function flushBody() protected function flushBody()
{ {
if (isset($this->data['body'])) { if (isset($this->data['body'])) {

View file

@ -14,11 +14,6 @@ class RedirectResponse extends Response
$this->setResponseCode(302); $this->setResponseCode(302);
} }
public function hasLayout()
{
return false;
}
public function flush() public function flush()
{ {
parent::flush(); parent::flush();

View file

@ -1,207 +1,161 @@
<!DOCTYPE html> <?php if (!empty($latest)): ?>
<html>
<head>
<title><?= $project->getTitle(); ?> - PHP Censor</title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'> <?php
<link href="<?= APP_URL; ?>assets/vendor/admin-lte/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" /> $statusClass = null;
<link href="<?= APP_URL; ?>assets/vendor/admin-lte/dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css" /> $statusText = null;
<link href="<?= APP_URL; ?>assets/css/ansi-colors.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/css/main.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css" /> switch ($latest->getStatus()) {
<link href="<?= APP_URL; ?>assets/vendor/ionicons/css/ionicons.min.css" rel="stylesheet" type="text/css" /> case 0:
$statusClass = 'blue';
$statusText = 'Pending';
break;
case 1:
$statusClass = 'yellow';
$statusText = 'Running';
break;
case 2:
$statusClass = 'green';
$statusText = 'Success';
break;
case 3:
$statusClass = 'red';
$statusText = 'Failed';
break;
}
<script src="<?= APP_URL; ?>assets/vendor/admin-lte/plugins/jQuery/jquery-2.2.3.min.js"></script> ?>
<script src="<?= APP_URL; ?>assets/js/class.js"></script>
<script src="<?= APP_URL; ?>assets/vendor/sprintf-js/dist/sprintf.min.js"></script>
<script src="<?= APP_URL; ?>assets/js/app.js?v2" type="text/javascript"></script>
</head>
<body class="hold-transition skin-black layout-top-nav">
<div class="wrapper">
<header class="main-header">
<nav class="navbar navbar-static-top">
<div class="container">
<div class="navbar-header">
<a href="<?= APP_URL; ?>" class="logo" title="PHP Censor" style="background-color: #222D32; width: 170px; padding: 0;">
<img src="<?= APP_URL; ?>assets/img/php-censor-white.svg" width="170" height="auto" alt="PHP Censor" />
</a>
</div>
</div>
</nav>
</header>
<div class="content-wrapper">
<div class="container">
<section class="content" style="padding: 15px 0 15px;">
<?php if (!empty($latest)): ?>
<?php <div class="small-box small-box-full bg-<?= $statusClass; ?>">
<div class="inner">
<h3 class="box-title">
<?= $latest->getProject()->getTitle(); ?> #<?= $latest->getId(); ?> (<?= $statusText; ?>)
</h3>
<p>
<?php $latestCommitMessage = htmlspecialchars($latest->getCommitMessage()); ?>
<?php if ($latestCommitMessage): ?>
<?= $latestCommitMessage; ?><br /><br />
<?php endif; ?>
$statusClass = null; <strong>Branch: </strong> <?= $latest->getBranch(); ?><br />
$statusText = null; <strong>Committer: </strong> <?= $latest->getCommitterEmail(); ?>
switch ($latest->getStatus()) { <?php if (!empty($latest->getCommitId())): ?>
case 0: <br /><strong>Commit: </strong> <?= $latest->getCommitId(); ?><br>
$statusClass = 'blue'; <?php endif; ?>
$statusText = 'Pending'; </p>
break;
case 1:
$statusClass = 'yellow';
$statusText = 'Running';
break;
case 2:
$statusClass = 'green';
$statusText = 'Success';
break;
case 3:
$statusClass = 'red';
$statusText = 'Failed';
break;
}
?>
<div class="small-box small-box-full bg-<?= $statusClass; ?>">
<div class="inner">
<h3 class="box-title">
<?= $latest->getProject()->getTitle(); ?> #<?= $latest->getId(); ?> (<?= $statusText; ?>)
</h3>
<p>
<?php $latestCommitMessage = htmlspecialchars($latest->getCommitMessage()); ?>
<?php if ($latestCommitMessage): ?>
<?= $latestCommitMessage; ?><br /><br />
<?php endif; ?>
<strong>Branch: </strong> <?= $latest->getBranch(); ?><br />
<strong>Committer: </strong> <?= $latest->getCommitterEmail(); ?>
<?php if (!empty($latest->getCommitId())): ?>
<br /><strong>Commit: </strong> <?= $latest->getCommitId(); ?><br>
<?php endif; ?>
</p>
</div>
<div class="icon">
<i class="fa fa-<?= $project->getIcon(); ?>"></i>
</div>
<div style="clear: both;"></div>
</div>
<?php endif; ?>
<div class="box">
<div class="box-header"><h3 class="box-title">Builds</h3></div>
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Status</th>
<th>Date</th>
<th>Commit</th>
<th>Branch</th>
<th>Environment</th>
<th>Duration</th>
</tr>
</thead>
<tbody id="latest-builds">
<?php if(empty($builds) || !count($builds)): ?>
<tr class="">
<td colspan="6">No builds yet.</td>
</tr>
<?php endif; ?>
<?php foreach($builds as $build): ?>
<?php
switch($build->getStatus())
{
case 0:
$class = 'info';
$status = 'Pending';
break;
case 1:
$class = 'warning';
$status = 'Running';
break;
case 2:
$class = 'success';
$status = 'Success';
break;
case 3:
$class = 'danger';
$status = 'Failed';
break;
}
?>
<tr>
<td><a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>">#<?= str_pad($build->getId(), 6, '0', STR_PAD_LEFT); ?></a></td>
<td>
<span class='label label-<?= $class; ?>'><?= $status; ?></span>
</td>
<td><?= $build->getCreateDate()->format('Y-m-d H:i:s'); ?></td>
<td>
<?php
if (!empty($build->getCommitId())) {
print sprintf(
'<a href="%s">%s %s</a>',
$build->getCommitLink(),
substr($build->getCommitId(), 0, 7),
$build->getCommitterEmail() ? ('(' . $build->getCommitterEmail() . ')') : ''
);
} else {
print '&mdash;';
}
?>
</td>
<td>
<?php if (\PHPCensor\Model\Build::SOURCE_WEBHOOK_PULL_REQUEST === $build->getSource()): ?>
<a href="<?= $build->getRemoteBranchLink(); ?>">
<i class="fa fa-code-fork"></i>
<?= $build->getRemoteBranch(); ?> :
</a>
<?php endif; ?>
<a href="<?= $build->getBranchLink();?>">
<i class="fa fa-code-fork"></i>
<?= $build->getBranch(); ?>
</a>
<?php $branches = $build->getExtra('branches'); ?>
<?= $branches ? ' + '.implode(', ', $branches) : ''; ?>
<?php if ($tag = $build->getTag()): ?> /
<a href="<?= $build->getTagLink(); ?>">
<i class="fa fa-tag"></i>
<?= $tag; ?>
</a>
<?php endif; ?>
</td>
<td>
<?php
$environment = $build->getEnvironment();
echo !empty($environment) ? $environment : '—' ;
?>
</td>
<td>
<?= $build->getDuration(); ?> sec.
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</section>
</div>
</div> </div>
<!--<footer class="main-footer"> <div class="icon">
<div class="container"> <i class="fa fa-<?= $project->getIcon(); ?>"></i>
</div> </div>
</footer>--> <div style="clear: both;"></div>
</div> </div>
</body> <?php endif; ?>
</html>
<div class="box">
<div class="box-header"><h3 class="box-title">Builds</h3></div>
<table class="table table-hover">
<thead>
<tr>
<th>ID</th>
<th>Status</th>
<th>Date</th>
<th>Commit</th>
<th>Branch</th>
<th>Environment</th>
<th>Duration</th>
</tr>
</thead>
<tbody id="latest-builds">
<?php if(empty($builds) || !count($builds)): ?>
<tr class="">
<td colspan="6">No builds yet.</td>
</tr>
<?php endif; ?>
<?php foreach($builds as $build): ?>
<?php
switch($build->getStatus())
{
case 0:
$class = 'info';
$status = 'Pending';
break;
case 1:
$class = 'warning';
$status = 'Running';
break;
case 2:
$class = 'success';
$status = 'Success';
break;
case 3:
$class = 'danger';
$status = 'Failed';
break;
}
?>
<tr>
<td><a href="<?= APP_URL; ?>build/view/<?= $build->getId(); ?>">#<?= str_pad($build->getId(), 6, '0', STR_PAD_LEFT); ?></a></td>
<td>
<span class='label label-<?= $class; ?>'><?= $status; ?></span>
</td>
<td><?= $build->getCreateDate()->format('Y-m-d H:i:s'); ?></td>
<td>
<?php
if (!empty($build->getCommitId())) {
print sprintf(
'<a href="%s">%s %s</a>',
$build->getCommitLink(),
substr($build->getCommitId(), 0, 7),
$build->getCommitterEmail() ? ('(' . $build->getCommitterEmail() . ')') : ''
);
} else {
print '&mdash;';
}
?>
</td>
<td>
<?php if (\PHPCensor\Model\Build::SOURCE_WEBHOOK_PULL_REQUEST === $build->getSource()): ?>
<a href="<?= $build->getRemoteBranchLink(); ?>">
<i class="fa fa-code-fork"></i>
<?= $build->getRemoteBranch(); ?> :
</a>
<?php endif; ?>
<a href="<?= $build->getBranchLink();?>">
<i class="fa fa-code-fork"></i>
<?= $build->getBranch(); ?>
</a>
<?php $branches = $build->getExtra('branches'); ?>
<?= $branches ? ' + '.implode(', ', $branches) : ''; ?>
<?php if ($tag = $build->getTag()): ?> /
<a href="<?= $build->getTagLink(); ?>">
<i class="fa fa-tag"></i>
<?= $tag; ?>
</a>
<?php endif; ?>
</td>
<td>
<?php
$environment = $build->getEnvironment();
echo !empty($environment) ? $environment : '—' ;
?>
</td>
<td>
<?= $build->getDuration(); ?> sec.
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>

View file

@ -0,0 +1,43 @@
<!DOCTYPE html>
<html>
<head>
<title><?= $title; ?><?= (!empty($subtitle) ? ' - ' . $subtitle : ''); ?></title>
<meta content='width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no' name='viewport'>
<link href="<?= APP_URL; ?>assets/vendor/admin-lte/bootstrap/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/vendor/admin-lte/dist/css/AdminLTE.min.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/css/ansi-colors.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/css/main.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/vendor/font-awesome/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
<link href="<?= APP_URL; ?>assets/vendor/ionicons/css/ionicons.min.css" rel="stylesheet" type="text/css" />
<script src="<?= APP_URL; ?>assets/vendor/admin-lte/plugins/jQuery/jquery-2.2.3.min.js"></script>
<script src="<?= APP_URL; ?>assets/js/class.js"></script>
<script src="<?= APP_URL; ?>assets/vendor/sprintf-js/dist/sprintf.min.js"></script>
<script src="<?= APP_URL; ?>assets/js/app.js?v2" type="text/javascript"></script>
</head>
<body class="hold-transition skin-black layout-top-nav">
<div class="wrapper">
<header class="main-header">
<nav class="navbar navbar-static-top">
<div class="container">
<div class="navbar-header">
<a href="<?= APP_URL; ?>" class="logo" title="PHP Censor" style="background-color: #222D32; width: 170px; padding: 0;">
<img src="<?= APP_URL; ?>assets/img/php-censor-white.svg" width="170" height="auto" alt="PHP Censor" />
</a>
</div>
</div>
</nav>
</header>
<div class="content-wrapper">
<div class="container">
<section class="content" style="padding: 15px 0 15px;">
<?= $content; ?>
</section>
</div>
</div>
</div>
</body>
</html>

152
src/WebController.php Normal file
View file

@ -0,0 +1,152 @@
<?php
namespace PHPCensor;
use PHPCensor\Exception\HttpException\ForbiddenException;
use PHPCensor\Http\Response;
use PHPCensor\Http\Request;
use PHPCensor\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Store\UserStore;
abstract class WebController extends Controller
{
/**
* @var string
*/
protected $className;
/**
* @var View
*/
protected $view = null;
/**
* @var string
*/
public $layoutName = '';
/**
* @var View
*/
public $layout = null;
/**
* @param Config $config
* @param Request $request
*/
public function __construct(Config $config, Request $request)
{
parent::__construct($config, $request);
$class = explode('\\', get_class($this));
$this->className = substr(array_pop($class), 0, -10);
}
public function init()
{
if (!empty($this->layoutName)) {
$this->layout = new View($this->layoutName);
$this->layout->title = 'PHP Censor';
$this->layout->breadcrumb = [];
$this->layout->version = trim(file_get_contents(ROOT_DIR . 'VERSION.md'));
$groups = [];
$groupStore = Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) {
$thisGroup = ['title' => $group->getTitle()];
$projects = Factory::getStore('Project')->getByGroupId($group->getId(), false);
$thisGroup['projects'] = $projects['items'];
$groups[] = $thisGroup;
}
$archivedProjects = Factory::getStore('Project')->getAll(true);
$this->layout->archived_projects = $archivedProjects['items'];
$this->layout->groups = $groups;
}
}
/**
* Handle the incoming request.
*
* @param string $action
* @param array $actionParams
*
* @return Response
*/
public function handleAction($action, $actionParams)
{
if (View::exists($this->className . '/' . $action)) {
$this->view = new View($this->className . '/' . $action);
}
$result = parent::handleAction($action, $actionParams);
if ($result instanceof Response) {
return $result;
}
$content = '';
if (is_string($result)) {
$content = $result;
} elseif ($this->view) {
$content = $this->view->render();
}
$response = new Response();
if ($this->layout) {
$this->layout->content = $content;
$response->setContent($this->layout->render());
} else {
$response->setContent($content);
}
return $response;
}
/**
* Require that the currently logged in user is an administrator.
*
* @throws ForbiddenException
*/
protected function requireAdmin()
{
if (!$this->currentUserIsAdmin()) {
throw new ForbiddenException('You do not have permission to do that.');
}
}
/**
* Check if the currently logged in user is an administrator.
*
* @return boolean
*/
protected function currentUserIsAdmin()
{
$user = $this->getUser();
if (!$user) {
return false;
}
return $this->getUser()->getIsAdmin();
}
/**
* @return User|null
*/
protected function getUser()
{
if (empty($_SESSION['php-censor-user-id'])) {
return null;
}
/** @var UserStore $userStore */
$userStore = Factory::getStore('User');
return $userStore->getById($_SESSION['php-censor-user-id']);
}
}