mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-20 12:30:56 +01:00
Improve web tools for viewing daemons
Summary: - Provides an "all daemons" view to look at more than the first 15 daemons. - Provides a "combined log" view with a large page size, to quickly look at the log across all the daemons, making it easier to find issues when you have a bunch of the same daemon and only one is having issues. - When viewing the web console on the same host as a daemon, show whether it's running or not. Test Plan: Clicked the various daemon log interfaces. Reviewed By: aran Reviewers: jungejason, tuomaspelkonen, aran CC: aran Differential Revision: 215
This commit is contained in:
parent
8370f93048
commit
6229cdadd8
16 changed files with 428 additions and 77 deletions
|
@ -271,12 +271,16 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitMethodCallLog' => 'applications/conduit/storage/methodcalllog',
|
||||
'PhabricatorController' => 'applications/base/controller/base',
|
||||
'PhabricatorDaemon' => 'infrastructure/daemon/base',
|
||||
'PhabricatorDaemonCombinedLogController' => 'applications/daemon/controller/combined',
|
||||
'PhabricatorDaemonConsoleController' => 'applications/daemon/controller/console',
|
||||
'PhabricatorDaemonControl' => 'infrastructure/daemon/control',
|
||||
'PhabricatorDaemonController' => 'applications/daemon/controller/base',
|
||||
'PhabricatorDaemonDAO' => 'infrastructure/daemon/storage/base',
|
||||
'PhabricatorDaemonLog' => 'infrastructure/daemon/storage/log',
|
||||
'PhabricatorDaemonLogEvent' => 'infrastructure/daemon/storage/event',
|
||||
'PhabricatorDaemonLogEventsView' => 'applications/daemon/view/daemonlogevents',
|
||||
'PhabricatorDaemonLogListController' => 'applications/daemon/controller/loglist',
|
||||
'PhabricatorDaemonLogListView' => 'applications/daemon/view/daemonloglist',
|
||||
'PhabricatorDaemonLogViewController' => 'applications/daemon/controller/logview',
|
||||
'PhabricatorDaemonReference' => 'infrastructure/daemon/control/reference',
|
||||
'PhabricatorDaemonTimelineConsoleController' => 'applications/daemon/controller/timeline',
|
||||
|
@ -675,11 +679,15 @@ phutil_register_library_map(array(
|
|||
'PhabricatorConduitMethodCallLog' => 'PhabricatorConduitDAO',
|
||||
'PhabricatorController' => 'AphrontController',
|
||||
'PhabricatorDaemon' => 'PhutilDaemon',
|
||||
'PhabricatorDaemonCombinedLogController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonConsoleController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonController' => 'PhabricatorController',
|
||||
'PhabricatorDaemonDAO' => 'PhabricatorLiskDAO',
|
||||
'PhabricatorDaemonLog' => 'PhabricatorDaemonDAO',
|
||||
'PhabricatorDaemonLogEvent' => 'PhabricatorDaemonDAO',
|
||||
'PhabricatorDaemonLogEventsView' => 'AphrontView',
|
||||
'PhabricatorDaemonLogListController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonLogListView' => 'AphrontView',
|
||||
'PhabricatorDaemonLogViewController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonTimelineConsoleController' => 'PhabricatorDaemonController',
|
||||
'PhabricatorDaemonTimelineEventController' => 'PhabricatorDaemonController',
|
||||
|
|
|
@ -231,6 +231,8 @@ class AphrontDefaultApplicationConfiguration
|
|||
'/daemon/' => array(
|
||||
'task/(?P<id>\d+)/$' => 'PhabricatorWorkerTaskDetailController',
|
||||
'log/' => array(
|
||||
'$' => 'PhabricatorDaemonLogListController',
|
||||
'combined/$' => 'PhabricatorDaemonCombinedLogController',
|
||||
'(?P<id>\d+)/$' => 'PhabricatorDaemonLogViewController',
|
||||
),
|
||||
'timeline/$' => 'PhabricatorDaemonTimelineConsoleController',
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorDaemonCombinedLogController
|
||||
extends PhabricatorDaemonController {
|
||||
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setOffset($request->getInt('page'));
|
||||
$pager->setPageSize(1000);
|
||||
|
||||
$events = id(new PhabricatorDaemonLogEvent())->loadAllWhere(
|
||||
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
|
||||
$pager->getOffset(),
|
||||
$pager->getPageSize() + 1);
|
||||
|
||||
$events = $pager->sliceResults($events);
|
||||
$pager->setURI($request->getRequestURI(), 'page');
|
||||
|
||||
$event_view = new PhabricatorDaemonLogEventsView();
|
||||
$event_view->setEvents($events);
|
||||
$event_view->setCombinedLog(true);
|
||||
|
||||
$log_panel = new AphrontPanelView();
|
||||
$log_panel->setHeader('Combined Daemon Logs');
|
||||
$log_panel->appendChild($event_view);
|
||||
$log_panel->appendChild($pager);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$log_panel,
|
||||
array(
|
||||
'title' => 'Combined Daemon Log',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
18
src/applications/daemon/controller/combined/__init__.php
Normal file
18
src/applications/daemon/controller/combined/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/daemon/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/daemon/view/daemonlogevents');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/storage/event');
|
||||
phutil_require_module('phabricator', 'view/control/pager');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorDaemonCombinedLogController.php');
|
|
@ -22,48 +22,26 @@ class PhabricatorDaemonConsoleController extends PhabricatorDaemonController {
|
|||
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
|
||||
'1 = 1 ORDER BY id DESC LIMIT 15');
|
||||
|
||||
$rows = array();
|
||||
foreach ($logs as $log) {
|
||||
$epoch = $log->getDateCreated();
|
||||
|
||||
$rows[] = array(
|
||||
phutil_escape_html($log->getDaemon()),
|
||||
phutil_escape_html($log->getHost()),
|
||||
$log->getPID(),
|
||||
date('M j, Y', $epoch),
|
||||
date('g:i A', $epoch),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/daemon/log/'.$log->getID().'/',
|
||||
'class' => 'button small grey',
|
||||
),
|
||||
'View Log'),
|
||||
);
|
||||
}
|
||||
|
||||
$daemon_table = new AphrontTableView($rows);
|
||||
$daemon_table->setHeaders(
|
||||
array(
|
||||
'Daemon',
|
||||
'Host',
|
||||
'PID',
|
||||
'Date',
|
||||
'Time',
|
||||
'View',
|
||||
));
|
||||
$daemon_table->setColumnClasses(
|
||||
array(
|
||||
'wide wrap',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'right',
|
||||
'action',
|
||||
));
|
||||
$daemon_table = new PhabricatorDaemonLogListView();
|
||||
$daemon_table->setDaemonLogs($logs);
|
||||
|
||||
$daemon_panel = new AphrontPanelView();
|
||||
$daemon_panel->setHeader('Recently Launched Daemons');
|
||||
$daemon_panel->setHeader(
|
||||
'Recently Launched Daemons'.
|
||||
' · '.
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/daemon/log/',
|
||||
),
|
||||
'View All Daemons').
|
||||
' · '.
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/daemon/log/combined/',
|
||||
),
|
||||
'View Combined Log'));
|
||||
$daemon_panel->appendChild($daemon_table);
|
||||
|
||||
$tasks = id(new PhabricatorWorkerTask())->loadAllWhere(
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/daemon/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/daemon/view/daemonloglist');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/storage/log');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/timeline/storage/cursor');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/workers/storage/task');
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
class PhabricatorDaemonLogListController extends PhabricatorDaemonController {
|
||||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
|
||||
$pager = new AphrontPagerView();
|
||||
$pager->setOffset($request->getInt('page'));
|
||||
|
||||
$logs = id(new PhabricatorDaemonLog())->loadAllWhere(
|
||||
'1 = 1 ORDER BY id DESC LIMIT %d, %d',
|
||||
$pager->getOffset(),
|
||||
$pager->getPageSize() + 1);
|
||||
|
||||
$logs = $pager->sliceResults($logs);
|
||||
$pager->setURI($request->getRequestURI(), 'page');
|
||||
|
||||
$daemon_table = new PhabricatorDaemonLogListView();
|
||||
$daemon_table->setDaemonLogs($logs);
|
||||
|
||||
$daemon_panel = new AphrontPanelView();
|
||||
$daemon_panel->setHeader('Launched Daemons');
|
||||
$daemon_panel->appendChild($daemon_table);
|
||||
$daemon_panel->appendChild($pager);
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$daemon_panel,
|
||||
array(
|
||||
'title' => 'All Daemons',
|
||||
));
|
||||
}
|
||||
|
||||
}
|
18
src/applications/daemon/controller/loglist/__init__.php
Normal file
18
src/applications/daemon/controller/loglist/__init__.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'applications/daemon/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/daemon/view/daemonloglist');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/storage/log');
|
||||
phutil_require_module('phabricator', 'view/control/pager');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorDaemonLogListController.php');
|
|
@ -34,7 +34,7 @@ class PhabricatorDaemonLogViewController extends PhabricatorDaemonController {
|
|||
}
|
||||
|
||||
$events = id(new PhabricatorDaemonLogEvent())->loadAllWhere(
|
||||
'logID = %d ORDER BY id DESC LIMIT 200',
|
||||
'logID = %d ORDER BY id DESC LIMIT 1000',
|
||||
$log->getID());
|
||||
|
||||
$content = array();
|
||||
|
@ -72,44 +72,19 @@ class PhabricatorDaemonLogViewController extends PhabricatorDaemonController {
|
|||
|
||||
$content[] = $panel;
|
||||
|
||||
$rows = array();
|
||||
foreach ($events as $event) {
|
||||
$rows[] = array(
|
||||
phutil_escape_html($event->getLogType()),
|
||||
date('M j, Y', $event->getEpoch()),
|
||||
date('g:i:s A', $event->getEpoch()),
|
||||
str_replace("\n", '<br />', phutil_escape_html($event->getMessage())),
|
||||
);
|
||||
}
|
||||
|
||||
$log_table = new AphrontTableView($rows);
|
||||
$log_table->setHeaders(
|
||||
array(
|
||||
'Type',
|
||||
'Date',
|
||||
'Time',
|
||||
'Message',
|
||||
));
|
||||
$log_table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'',
|
||||
'right',
|
||||
'wide wrap',
|
||||
));
|
||||
$event_view = new PhabricatorDaemonLogEventsView();
|
||||
$event_view->setEvents($events);
|
||||
|
||||
$log_panel = new AphrontPanelView();
|
||||
$log_panel->setHeader('Daemon Logs');
|
||||
$log_panel->appendChild($log_table);
|
||||
$log_panel->appendChild($event_view);
|
||||
|
||||
$content[] = $log_panel;
|
||||
|
||||
|
||||
|
||||
return $this->buildStandardPageResponse(
|
||||
$content,
|
||||
array(
|
||||
'title' => 'Log',
|
||||
'title' => 'Daemon Log',
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,15 +8,14 @@
|
|||
|
||||
phutil_require_module('phabricator', 'aphront/response/404');
|
||||
phutil_require_module('phabricator', 'applications/daemon/controller/base');
|
||||
phutil_require_module('phabricator', 'applications/daemon/view/daemonlogevents');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/storage/event');
|
||||
phutil_require_module('phabricator', 'infrastructure/daemon/storage/log');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
phutil_require_module('phabricator', 'view/form/base');
|
||||
phutil_require_module('phabricator', 'view/form/control/static');
|
||||
phutil_require_module('phabricator', 'view/form/control/textarea');
|
||||
phutil_require_module('phabricator', 'view/layout/panel');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorDaemonLogEventsView extends AphrontView {
|
||||
|
||||
private $events;
|
||||
private $combinedLog;
|
||||
|
||||
public function setEvents(array $events) {
|
||||
$this->events = $events;
|
||||
}
|
||||
|
||||
public function setCombinedLog($is_combined) {
|
||||
$this->combinedLog = $is_combined;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$rows = array();
|
||||
|
||||
foreach ($this->events as $event) {
|
||||
$row = array(
|
||||
phutil_escape_html($event->getLogType()),
|
||||
date('M j, Y', $event->getEpoch()),
|
||||
date('g:i:s A', $event->getEpoch()),
|
||||
str_replace("\n", '<br />', phutil_escape_html($event->getMessage())),
|
||||
);
|
||||
|
||||
if ($this->combinedLog) {
|
||||
array_unshift(
|
||||
$row,
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/daemon/log/'.$event->getLogID().'/',
|
||||
),
|
||||
phutil_escape_html('Daemon '.$event->getLogID())));
|
||||
}
|
||||
|
||||
$rows[] = $row;
|
||||
}
|
||||
|
||||
$classes = array(
|
||||
'',
|
||||
'',
|
||||
'right',
|
||||
'wide wrap',
|
||||
);
|
||||
|
||||
$headers = array(
|
||||
'Type',
|
||||
'Date',
|
||||
'Time',
|
||||
'Message',
|
||||
);
|
||||
|
||||
if ($this->combinedLog) {
|
||||
array_unshift($classes, 'pri');
|
||||
array_unshift($headers, 'Daemon');
|
||||
}
|
||||
|
||||
$log_table = new AphrontTableView($rows);
|
||||
$log_table->setHeaders($headers);
|
||||
$log_table->setColumnClasses($classes);
|
||||
|
||||
return $log_table->render();
|
||||
}
|
||||
|
||||
}
|
15
src/applications/daemon/view/daemonlogevents/__init__.php
Normal file
15
src/applications/daemon/view/daemonlogevents/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorDaemonLogEventsView.php');
|
|
@ -0,0 +1,113 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* Copyright 2011 Facebook, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
final class PhabricatorDaemonLogListView extends AphrontView {
|
||||
|
||||
private $daemonLogs;
|
||||
|
||||
public function setDaemonLogs(array $daemon_logs) {
|
||||
$this->daemonLogs = $daemon_logs;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$rows = array();
|
||||
|
||||
foreach ($this->daemonLogs as $log) {
|
||||
$epoch = $log->getDateCreated();
|
||||
|
||||
if ($log->getHost() == php_uname('n')) {
|
||||
|
||||
// This will probably fail since apache can't signal the process, but
|
||||
// we can check the error code to figure out if the process exists.
|
||||
$is_running = posix_kill($log->getPID(), 0);
|
||||
if (posix_get_last_error() == 1) {
|
||||
// "Operation Not Permitted", indicates that the PID exists. If it
|
||||
// doesn't, we'll get an error 3 ("No such process") instead.
|
||||
$is_running = true;
|
||||
}
|
||||
|
||||
if ($is_running) {
|
||||
$running = phutil_render_tag(
|
||||
'span',
|
||||
array(
|
||||
'style' => 'color: #00cc00',
|
||||
'title' => 'Running',
|
||||
),
|
||||
'•');
|
||||
} else {
|
||||
$running = phutil_render_tag(
|
||||
'span',
|
||||
array(
|
||||
'style' => 'color: #cc0000',
|
||||
'title' => 'Not running',
|
||||
),
|
||||
'•');
|
||||
}
|
||||
} else {
|
||||
$running = phutil_render_tag(
|
||||
'span',
|
||||
array(
|
||||
'style' => 'color: #888888',
|
||||
'title' => 'Not on this host',
|
||||
),
|
||||
'?');
|
||||
}
|
||||
|
||||
$rows[] = array(
|
||||
$running,
|
||||
phutil_escape_html($log->getDaemon()),
|
||||
phutil_escape_html($log->getHost()),
|
||||
$log->getPID(),
|
||||
date('M j, Y', $epoch),
|
||||
date('g:i A', $epoch),
|
||||
phutil_render_tag(
|
||||
'a',
|
||||
array(
|
||||
'href' => '/daemon/log/'.$log->getID().'/',
|
||||
'class' => 'button small grey',
|
||||
),
|
||||
'View Log'),
|
||||
);
|
||||
}
|
||||
|
||||
$daemon_table = new AphrontTableView($rows);
|
||||
$daemon_table->setHeaders(
|
||||
array(
|
||||
'',
|
||||
'Daemon',
|
||||
'Host',
|
||||
'PID',
|
||||
'Date',
|
||||
'Time',
|
||||
'View',
|
||||
));
|
||||
$daemon_table->setColumnClasses(
|
||||
array(
|
||||
'',
|
||||
'wide wrap',
|
||||
'',
|
||||
'',
|
||||
'',
|
||||
'right',
|
||||
'action',
|
||||
));
|
||||
|
||||
return $daemon_table->render();
|
||||
}
|
||||
|
||||
}
|
15
src/applications/daemon/view/daemonloglist/__init__.php
Normal file
15
src/applications/daemon/view/daemonloglist/__init__.php
Normal file
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
/**
|
||||
* This file is automatically generated. Lint this module to rebuild it.
|
||||
* @generated
|
||||
*/
|
||||
|
||||
|
||||
|
||||
phutil_require_module('phabricator', 'view/base');
|
||||
phutil_require_module('phabricator', 'view/control/table');
|
||||
|
||||
phutil_require_module('phutil', 'markup');
|
||||
|
||||
|
||||
phutil_require_source('PhabricatorDaemonLogListView.php');
|
|
@ -30,11 +30,7 @@ class PhabricatorFileListController extends PhabricatorFileController {
|
|||
$pager->getOffset(),
|
||||
$pager->getPageSize() + 1);
|
||||
|
||||
if (count($files) > $pager->getPageSize()) {
|
||||
$files = array_slice($files, 0, $pager->getPageSize(), true);
|
||||
$pager->setHasMorePages(true);
|
||||
}
|
||||
|
||||
$files = $pager->sliceResults($files);
|
||||
$pager->setURI($request->getRequestURI(), 'page');
|
||||
|
||||
$rows = array();
|
||||
|
|
|
@ -80,6 +80,32 @@ final class AphrontPagerView extends AphrontView {
|
|||
return $this->count !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A common paging strategy is to select one extra record and use that to
|
||||
* indicate that there's an additional page (this doesn't give you a
|
||||
* complete page count but is often faster than counting the total number
|
||||
* of items). This method will take a result array, slice it down to the
|
||||
* page size if necessary, and call setHasMorePages() if there are more than
|
||||
* one page of results.
|
||||
*
|
||||
* $results = queryfx_all(
|
||||
* $conn,
|
||||
* 'SELECT ... LIMIT %d, %d',
|
||||
* $pager->getOffset(),
|
||||
* $pager->getPageSize() + 1);
|
||||
* $results = $pager->sliceResults($results);
|
||||
*
|
||||
* @param list Result array.
|
||||
* @return list One page of results.
|
||||
*/
|
||||
public function sliceResults(array $results) {
|
||||
if (count($results) > $this->getPageSize()) {
|
||||
$results = array_slice($results, 0, $this->getPageSize(), true);
|
||||
$this->setHasMorePages(true);
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
public function render() {
|
||||
if (!$this->uri) {
|
||||
throw new Exception(
|
||||
|
|
Loading…
Reference in a new issue