From 6b102f214eb253bcb03de0114be23ae5112b7ee0 Mon Sep 17 00:00:00 2001 From: Dmitry Khomutov Date: Sun, 29 Oct 2017 14:06:41 +0700 Subject: [PATCH] Added Paginator for build errors. Issue #85. --- public/assets/js/build.js | 5 +- src/PHPCensor/Controller/BuildController.php | 82 ++++++++++++++++--- .../Controller/ProjectController.php | 67 ++++++++++----- src/PHPCensor/Store/BuildErrorStore.php | 62 ++++---------- src/PHPCensor/View/Build/view.phtml | 14 ++++ src/PHPCensor/View/Project/view.phtml | 22 +---- src/PHPCensor/View/layout.phtml | 27 +++--- src/PHPCensor/View/pagination.phtml | 28 +++++++ 8 files changed, 190 insertions(+), 117 deletions(-) create mode 100644 src/PHPCensor/View/pagination.phtml diff --git a/public/assets/js/build.js b/public/assets/js/build.js index 9229a512..919e3829 100644 --- a/public/assets/js/build.js +++ b/public/assets/js/build.js @@ -22,7 +22,7 @@ var Build = Class.extend({ self.buildData = data.queryData; - // If the build has finished, stop updating every 10 seconds: + // If the build has finished, stop updating every 5 seconds: if (self.buildData && self.buildData.status > 1) { self.cancelQuery('build-updated'); $(window).trigger({type: 'build-complete'}); @@ -34,6 +34,7 @@ var Build = Class.extend({ $('.build-finished').html(self.buildData.finish_date ? self.buildData.finish_date : ''); $('#log pre').html(self.buildData.log); $('.errors-table tbody').html(self.buildData.error_html); + $('#paginator').html(self.buildData.paginator); if (self.buildData.errors == 0) { $('.errors-label').hide(); @@ -77,7 +78,7 @@ var Build = Class.extend({ var fullUri = window.APP_URL + uri; if (name == 'build-updated') { - fullUri = window.APP_URL + 'build/ajax-data/' + self.buildId; + fullUri = window.APP_URL + 'build/ajax-data/' + self.buildId + '?per_page=' + PER_PAGE + '&page=' + PAGE; } $.ajax({ diff --git a/src/PHPCensor/Controller/BuildController.php b/src/PHPCensor/Controller/BuildController.php index a00d4a93..bf4ceb54 100644 --- a/src/PHPCensor/Controller/BuildController.php +++ b/src/PHPCensor/Controller/BuildController.php @@ -5,11 +5,13 @@ namespace PHPCensor\Controller; use b8; use b8\Exception\HttpException\NotFoundException; use b8\Http\Response\JsonResponse; +use JasonGrimes\Paginator; use PHPCensor\BuildFactory; use PHPCensor\Helper\AnsiConverter; use PHPCensor\Helper\Lang; use PHPCensor\Model\Build; use PHPCensor\Model\Project; +use PHPCensor\Model\User; use PHPCensor\Service\BuildService; use PHPCensor\Controller; @@ -40,10 +42,16 @@ class BuildController extends Controller } /** - * View a specific build. - */ + * View a specific build. + * + * @param integer $buildId + * + * @throws NotFoundException + */ public function view($buildId) { + $page = (integer)$this->getParam('page', 1); + try { $build = BuildFactory::getBuildById($buildId); } catch (\Exception $ex) { @@ -54,9 +62,24 @@ class BuildController extends Controller throw new NotFoundException(Lang::get('build_x_not_found', $buildId)); } - $this->view->plugins = $this->getUiPlugins(); - $this->view->build = $build; - $this->view->data = $this->getBuildData($build); + /** @var User $user */ + $user = $_SESSION['php-censor-user']; + $perPage = $user->getFinalPerPage(); + $data = $this->getBuildData($build, (($page - 1) * $perPage), $perPage); + $pages = ($data['errors'] === 0) + ? 1 + : (integer)ceil($data['errors'] / $perPage); + + if ($page > $pages) { + $page = $pages; + } + + $this->view->plugins = $this->getUiPlugins(); + $this->view->build = $build; + $this->view->data = $data; + $this->view->page = $page; + $this->view->perPage = $perPage; + $this->view->paginator = $this->getPaginatorHtml($buildId, $data['errors'], $perPage, $page); $this->layout->title = Lang::get('build_n', $buildId); $this->layout->subtitle = $build->getProjectTitle(); @@ -121,9 +144,15 @@ class BuildController extends Controller } /** - * Get build data from database and json encode it: - */ - protected function getBuildData(Build $build) + * Get build data from database and json encode it. + * + * @param Build $build + * @param integer $start + * @param integer $perPage + * + * @return array + */ + protected function getBuildData(Build $build, $start = 0, $perPage = 10) { $data = []; $data['status'] = (int)$build->getStatus(); @@ -135,19 +164,40 @@ class BuildController extends Controller /** @var \PHPCensor\Store\BuildErrorStore $errorStore */ $errorStore = b8\Store\Factory::getStore('BuildError'); - $errors = $errorStore->getErrorsForBuild($build->getId()); + $errors = $errorStore->getByBuildId($build->getId(), $perPage, $start); $errorView = new b8\View('Build/errors'); $errorView->build = $build; - $errorView->errors = $errors; + $errorView->errors = $errors['items']; - $data['errors'] = $errorStore->getErrorTotalForBuild($build->getId()); + $data['errors'] = (integer)$errorStore->getErrorTotalForBuild($build->getId()); $data['error_html'] = $errorView->render(); - $data['since'] = (new \DateTime())->format('Y-m-d H:i:s'); return $data; } + /** + * @param integer $buildId + * @param integer $total + * @param integer $perPage + * @param integer $page + * + * @return string + */ + protected function getPaginatorHtml($buildId, $total, $perPage, $page) + { + $view = new b8\View('pagination'); + + $urlPattern = APP_URL . 'build/view/' . $buildId; + + $urlPattern = $urlPattern . '?' . str_replace('%28%3Anum%29', '(:num)', http_build_query(['page' => '(:num)'])) . '#errors'; + $paginator = new Paginator($total, $perPage, $page, $urlPattern); + + $view->paginator = $paginator; + + return $view->render(); + } + /** * Create a build using an existing build as a template: */ @@ -230,6 +280,9 @@ class BuildController extends Controller public function ajaxData($buildId) { + $page = (integer)$this->getParam('page', 1); + $perPage = (integer)$this->getParam('per_page', 10); + $response = new JsonResponse(); $build = BuildFactory::getBuildById($buildId); @@ -240,7 +293,10 @@ class BuildController extends Controller return $response; } - $response->setContent($this->getBuildData($build)); + $data = $this->getBuildData($build, (($page - 1) * $perPage), $perPage); + $data['paginator'] = $this->getPaginatorHtml($buildId, $data['errors'], $perPage, $page); + + $response->setContent($data); return $response; } diff --git a/src/PHPCensor/Controller/ProjectController.php b/src/PHPCensor/Controller/ProjectController.php index 836f0461..a8b909ae 100644 --- a/src/PHPCensor/Controller/ProjectController.php +++ b/src/PHPCensor/Controller/ProjectController.php @@ -94,30 +94,18 @@ class ProjectController extends PHPCensor\Controller throw new NotFoundException(Lang::get('project_x_not_found', $projectId)); } - $perPage = $_SESSION['php-censor-user']->getFinalPerPage(); + /** @var PHPCensor\Model\User $user */ + $user = $_SESSION['php-censor-user']; + $perPage = $user->getFinalPerPage(); $builds = $this->getLatestBuildsHtml($projectId, $environment, $branch, (($page - 1) * $perPage), $perPage); - $pages = $builds[1] == 0 ? 1 : (integer)ceil($builds[1] / $perPage); + $pages = ($builds[1] === 0) + ? 1 + : (integer)ceil($builds[1] / $perPage); if ($page > $pages) { - $response = new RedirectResponse(); - $response->setHeader('Location', APP_URL . 'project/view/' . $projectId); - - return $response; + $page = $pages; } - $urlPattern = APP_URL . 'project/view/' . $project->getId(); - $params = []; - if (!empty($branch)) { - $params['branch'] = $branch; - } - - if (!empty($environment)) { - $params['environment'] = $environment; - } - - $urlPattern = $urlPattern . '?' . str_replace('%28%3Anum%29', '(:num)', http_build_query(array_merge($params, ['page' => '(:num)']))); - $paginator = new Paginator($builds[1], $perPage, $page, $urlPattern); - $this->view->builds = $builds[0]; $this->view->total = $builds[1]; $this->view->project = $project; @@ -127,7 +115,7 @@ class ProjectController extends PHPCensor\Controller $this->view->environments = $project->getEnvironmentsNames(); $this->view->page = $page; $this->view->perPage = $perPage; - $this->view->paginator = $paginator; + $this->view->paginator = $this->getPaginatorHtml($projectId, $branch, $environment, $builds[1], $perPage, $page); $this->layout->title = $project->getTitle(); $this->layout->subtitle = ''; @@ -141,6 +129,38 @@ class ProjectController extends PHPCensor\Controller return $this->view->render(); } + /** + * @param integer $projectId + * @param string $branch + * @param string $environment + * @param integer $total + * @param integer $perPage + * @param integer $page + * + * @return string + */ + protected function getPaginatorHtml($projectId, $branch, $environment, $total, $perPage, $page) + { + $view = new b8\View('pagination'); + + $urlPattern = APP_URL . 'project/view/' . $projectId; + $params = []; + if (!empty($branch)) { + $params['branch'] = $branch; + } + + if (!empty($environment)) { + $params['environment'] = $environment; + } + + $urlPattern = $urlPattern . '?' . str_replace('%28%3Anum%29', '(:num)', http_build_query(array_merge($params, ['page' => '(:num)']))); + $paginator = new Paginator($total, $perPage, $page, $urlPattern); + + $view->paginator = $paginator; + + return $view->render(); + } + /** * Create a new pending build for a project. * @@ -259,9 +279,12 @@ class ProjectController extends PHPCensor\Controller $build = BuildFactory::getBuild($build); } - $view->builds = $builds['items']; + $view->builds = $builds['items']; - return [$view->render(), $builds['count']]; + return [ + $view->render(), + (integer)$builds['count'] + ]; } /** diff --git a/src/PHPCensor/Store/BuildErrorStore.php b/src/PHPCensor/Store/BuildErrorStore.php index f716fc70..fd97b530 100644 --- a/src/PHPCensor/Store/BuildErrorStore.php +++ b/src/PHPCensor/Store/BuildErrorStore.php @@ -60,23 +60,33 @@ class BuildErrorStore extends Store * * @param integer $buildId * @param integer $limit - * @param string $useConnection + * @param integer $offset * * @return array * * @throws HttpException */ - public function getByBuildId($buildId, $limit = 1000, $useConnection = 'read') + public function getByBuildId($buildId, $limit = null, $offset = 0) { if (is_null($buildId)) { throw new HttpException('Value passed to ' . __FUNCTION__ . ' cannot be null.'); } - - $query = 'SELECT * FROM {{build_error}} WHERE {{build_id}} = :build_id LIMIT :limit'; - $stmt = Database::getConnection($useConnection)->prepareCommon($query); + $query = 'SELECT * FROM {{build_error}} WHERE {{build_id}} = :build_id ORDER BY plugin, severity'; + if (null !== $limit) { + $query .= ' LIMIT :limit'; + } + if ($offset) { + $query .= ' OFFSET :offset'; + } + $stmt = Database::getConnection()->prepareCommon($query); $stmt->bindValue(':build_id', $buildId); - $stmt->bindValue(':limit', (int)$limit, \PDO::PARAM_INT); + if (null !== $limit) { + $stmt->bindValue(':limit', (integer)$limit, \PDO::PARAM_INT); + } + if ($offset) { + $stmt->bindValue(':offset', (integer)$offset, \PDO::PARAM_INT); + } if ($stmt->execute()) { $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); @@ -94,46 +104,6 @@ class BuildErrorStore extends Store } } - /** - * Get a list of errors for a given build, since a given time. - * - * @param integer $buildId - * @param string $since date string - * - * @return array - */ - public function getErrorsForBuild($buildId, $since = null) - { - $query = 'SELECT * FROM {{build_error}} WHERE {{build_id}} = :build'; - - if (!is_null($since)) { - $query .= ' AND created_date > :since'; - } - - $query .= ' LIMIT 15000'; - - $stmt = Database::getConnection('read')->prepareCommon($query); - - $stmt->bindValue(':build', $buildId, \PDO::PARAM_INT); - - if (!is_null($since)) { - $stmt->bindValue(':since', $since); - } - - if ($stmt->execute()) { - $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); - - $map = function ($item) { - return new BuildError($item); - }; - $rtn = array_map($map, $res); - - return $rtn; - } else { - return []; - } - } - /** * Gets the total number of errors for a given build. * diff --git a/src/PHPCensor/View/Build/view.phtml b/src/PHPCensor/View/Build/view.phtml index 8288fd5a..4ca2c143 100644 --- a/src/PHPCensor/View/Build/view.phtml +++ b/src/PHPCensor/View/Build/view.phtml @@ -204,6 +204,9 @@ use PHPCensor\Model\Build; +
+ +
@@ -214,10 +217,21 @@ use PHPCensor\Model\Build;
-
- +
+
diff --git a/src/PHPCensor/View/layout.phtml b/src/PHPCensor/View/layout.phtml index 5556256a..0d68a4ea 100644 --- a/src/PHPCensor/View/layout.phtml +++ b/src/PHPCensor/View/layout.phtml @@ -14,6 +14,19 @@ + + + + + + + + + + + + + - - - - -
@@ -245,14 +253,5 @@
- - - - - - - - - diff --git a/src/PHPCensor/View/pagination.phtml b/src/PHPCensor/View/pagination.phtml new file mode 100644 index 00000000..c1bc12cb --- /dev/null +++ b/src/PHPCensor/View/pagination.phtml @@ -0,0 +1,28 @@ + +