Skip to content

Commit 288a2b4

Browse files
authored
Merge pull request #3 from zunnu/dev
Pagination
2 parents 4978009 + 1fc056f commit 288a2b4

File tree

3 files changed

+168
-37
lines changed

3 files changed

+168
-37
lines changed

src/Controller/LogReaderController.php

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
class LogReaderController extends AppController
99
{
10+
/**
11+
* initialize method
12+
*
13+
* @return void
14+
*/
1015
public function initialize() {
1116
parent::initialize();
1217
}
@@ -26,10 +31,22 @@ public function index($date = null) {
2631
}
2732

2833
$this->Reader = new Reader($conditions);
29-
$this->set('logs', $this->Reader->read());
34+
$logs = $this->Reader->read();
35+
36+
// paginate
37+
$pagination = [
38+
'limit' => !empty($conditions['limit']) ? $conditions['limit'] : 100,
39+
'total' => sizeof($logs),
40+
'page' => !empty($conditions['page']) ? $conditions['page'] : 1,
41+
];
42+
$pagination['pages'] = ceil($pagination['total'] / $pagination['limit']);
43+
$pagination['offset'] = ($pagination['page'] * $pagination['limit']) - $pagination['limit'];
44+
$logs = array_slice($logs, $pagination['offset'], $pagination['limit'], true);
45+
46+
$this->set(compact('logs', 'pagination'));
3047
$this->set('files', $this->Reader->getFiles());
3148
$this->set('types', $this->Reader->getLogTypes());
32-
$this->set('selectedFiles', !empty($conditions['files']) ? $conditions['files'] : ['debug.log', 'error.log']);
49+
$this->set('selectedFiles', !empty($conditions['files']) ? $conditions['files'] : []);
3350
$this->set('selectedTypes', !empty($conditions['types']) ? $conditions['types'] : []);
3451
}
3552
}

src/Reader.php

Lines changed: 57 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,20 @@
44
use Cake\Filesystem\Folder;
55
use Cake\Filesystem\File;
66

7+
/**
8+
* Reader class
9+
*/
710
class Reader {
8-
// prefixes
9-
protected $config = [];
11+
/*
12+
* Class config
13+
* Options:
14+
* Types: Used to filter the results. Available types are in $logTypes
15+
* Files: The files where to read the logs from
16+
*/
17+
protected $config = [
18+
'types' => [],
19+
'files' => [],
20+
];
1021

1122
private $logTypes = [
1223
'info' => 'Info',
@@ -23,6 +34,10 @@ public function __construct($config = []) {
2334
$this->config = $config;
2435
}
2536

37+
/**
38+
* Get the date of the files
39+
* @return array List of different dates of files
40+
*/
2641
public function getFileDates() {
2742
$dates = [];
2843
$folder = new Folder(LOGS);
@@ -42,7 +57,11 @@ public function getFileDates() {
4257
return array_unique($dates);
4358
}
4459

45-
// return the path to the model dir
60+
/**
61+
* Main reader function
62+
* The files and types that are parsed need to be set in config
63+
* @return array List of logs
64+
*/
4665
public function read() {
4766
$date = !empty($this->config['date']) ? $this->config['date'] : null;
4867
$selectedTypes = !empty($this->config['types']) ? $this->config['types'] : [];
@@ -83,23 +102,34 @@ public function read() {
83102
return $logs;
84103
}
85104

105+
/**
106+
* Get logs inside file or files
107+
* @param array $selectedFiles List of files to get the logs from
108+
* @return array Content of the selected files
109+
*/
86110
private function getLogFile($selectedFiles = []) {
87111
$folder = new Folder(LOGS);
88112
$files = $folder->findRecursive('.*', true);
89113
$data = [];
90114

91-
// load default files
92115
if(empty($selectedFiles)) {
93-
$selectedFiles = ['debug.log', 'error.log'];
116+
return [];
117+
// $selectedFiles = ['debug.log', 'error.log'];
94118
}
95119

96120
if(!empty($files)) {
97121
foreach($files as $file) {
98122
$file = new File($file);
99123
$info = $file->info();
124+
$path = null;
125+
126+
// check if file is under a folder inside logs folder
127+
if(strpos($info['dirname'], 'logs/') !== false) {
128+
$path = substr($info['dirname'], strrpos($info['dirname'], '/') + 1);
129+
}
100130

101131
if(!empty($selectedFiles)) {
102-
if(!in_array($info['basename'], $selectedFiles)) {
132+
if(!in_array((!empty($path) ? $path . '/' : '') . $info['basename'], $selectedFiles)) {
103133
continue;
104134
}
105135
}
@@ -131,6 +161,10 @@ private function getLogFile($selectedFiles = []) {
131161
return false;
132162
}
133163

164+
/**
165+
* Get list of log files inside the logs folder
166+
* @return array List of files
167+
*/
134168
public function getFiles() {
135169
$filesList = [];
136170
$folder = new Folder(LOGS);
@@ -141,10 +175,16 @@ public function getFiles() {
141175
$file = new File($file);
142176
$date = date('Y-m-d H:i:s', $file->lastChange());
143177
$info = $file->info();
178+
$path = null;
179+
180+
// check if file is under a folder inside logs folder
181+
if(strpos($info['dirname'], 'logs/') !== false) {
182+
$path = substr($info['dirname'], strrpos($info['dirname'], '/') + 1);
183+
}
144184

145185
if($date) {
146186
$filesList[] = [
147-
'name' => $info['basename'],
187+
'name' => (!empty($path) ? $path . '/' : '') . $info['basename'],
148188
'date' => $date,
149189
'type' => strpos($file->name(), 'cli-debug') !== false || strpos($file->name(), 'cli-error') !== false ? 'cli' : 'app',
150190
];
@@ -155,7 +195,12 @@ public function getFiles() {
155195
return $filesList;
156196
}
157197

158-
// move this to regex later
198+
/**
199+
* Parse log file content
200+
* Move this to use regex later
201+
* @param array $data Content of log file
202+
* @return array Parsed data with type, date and content
203+
*/
159204
private function _parseData($data) {
160205
$data = preg_split("/\r\n|\n|\r/", $data);
161206
$buildData = [];
@@ -209,6 +254,10 @@ private function _parseData($data) {
209254
return $buildData;
210255
}
211256

257+
/**
258+
* Return available log file types
259+
* @return array
260+
*/
212261
public function getLogTypes() {
213262
return $this->logTypes;
214263
}

src/Template/LogReader/index.ctp

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
}
88
}
99

10-
$selectedFiles = json_encode($selectedFiles);
11-
$selectedTypes = json_encode($selectedTypes);
12-
1310
function getBadgeClass($type) {
1411
$type = strtolower($type);
1512

@@ -27,6 +24,8 @@
2724

2825
return '';
2926
}
27+
28+
$queryParams = $this->getRequest()->getQueryParams();
3029
?>
3130

3231
<!DOCTYPE html>
@@ -51,8 +50,8 @@
5150
</style>
5251

5352
<script type="text/javascript">
54-
var selectedFiles = <?= $selectedFiles ?>;
55-
var selectedTypes = <?= $selectedTypes ?>;
53+
var selectedFiles = <?= json_encode($selectedFiles) ?>;
54+
var selectedTypes = <?= json_encode($selectedTypes) ?>;
5655
</script>
5756

5857
<body>
@@ -87,7 +86,21 @@
8786
'onchange' => 'this.form.submit()',
8887
'class' => 'form-control',
8988
'templates' => [
90-
'inputContainer' => '<div class="form-group col-md-6 col-lg-6">{{content}}</div>'
89+
'inputContainer' => '<div class="form-group col-md-4 col-lg-4">{{content}}</div>'
90+
]
91+
]); ?>
92+
93+
<?= $this->Form->control('limit', [
94+
'label' => 'Limit',
95+
'required' => false,
96+
'id' => 'limit',
97+
'options' => ['25' => '25', '50' => '50', '100' => '100', '500' => '500', '1000' => '1000'],
98+
'default' => '100',
99+
'value' => $pagination['limit'],
100+
'onchange' => 'this.form.submit()',
101+
'class' => 'form-control',
102+
'templates' => [
103+
'inputContainer' => '<div class="form-group col-md-2 col-lg-2">{{content}}</div>'
91104
]
92105
]); ?>
93106
</div>
@@ -97,27 +110,79 @@
97110

98111
<div class="row">
99112
<div class="col-md-12">
100-
<div class="table-responsive">
101-
<table class="table table-white-bordered">
102-
<thead class="thead-dark">
103-
<tr>
104-
<th width="200" scope="col">Date</th>
105-
<th width="120" scope="col">Type</th>
106-
<th width="1100" scope="col">Message</th>
107-
</tr>
108-
</thead>
109-
<tbody>
110-
<?php foreach ($logs as $log): ?>
111-
<?php $badgeClass = getBadgeClass($log['type']); ?>
112-
<tr>
113-
<td><?= $log['date'] ?></td>
114-
<td class="badge <?= $badgeClass ?>"><?= $log['type'] ?></td>
115-
<td><?= $log['message'] ?></td>
116-
</tr>
117-
<?php endforeach; ?>
118-
</tbody>
119-
</table>
120-
</div>
113+
<?php if(!empty($selectedFiles)) : ?>
114+
<div class="table-responsive">
115+
<table class="table table-white-bordered">
116+
<thead class="thead-dark">
117+
<tr>
118+
<th width="200" scope="col">Date</th>
119+
<th width="120" scope="col">Type</th>
120+
<th width="1100" scope="col">Message</th>
121+
</tr>
122+
</thead>
123+
<tbody>
124+
<?php foreach ($logs as $log): ?>
125+
<?php $badgeClass = getBadgeClass($log['type']); ?>
126+
<tr>
127+
<td><?= $log['date'] ?></td>
128+
<td class="badge <?= $badgeClass ?>"><?= $log['type'] ?></td>
129+
<td><?= $log['message'] ?></td>
130+
</tr>
131+
<?php endforeach; ?>
132+
</tbody>
133+
</table>
134+
</div>
135+
136+
<nav aria-label="Page navigation">
137+
<ul class="pagination justify-content-center">
138+
<?php
139+
$pageLimit = $pagination['page'] + 10;
140+
$i = $pagination['page'] - 10;
141+
if($i < 1) $i = 1;
142+
?>
143+
144+
<?php if($pagination['page'] > 1) : ?>
145+
<li class="page-item <?= ($pagination['page'] == 1) ? 'disabled' : ''; ?>">
146+
<?php $queryParams['page'] = 1; ?>
147+
<a class="page-link" href="<?= '?' . http_build_query($queryParams); ?>">First</a>
148+
</li>
149+
<?php endif; ?>
150+
151+
<li class="page-item <?= ($pagination['page'] == 1) ? 'disabled' : ''; ?>">
152+
<?php $queryParams['page'] = $pagination['page'] - 1; ?>
153+
<a class="page-link" href="<?= '?' . http_build_query($queryParams); ?>">Previous</a>
154+
</li>
155+
156+
<?php for($i; $i <= $pagination['pages']; $i++) : ?>
157+
<?php
158+
if($i > $pageLimit) break;
159+
$queryParams['page'] = $i;
160+
$buildParams = '?' . http_build_query($queryParams);
161+
?>
162+
<li class="page-item <?= ($pagination['page'] == $i) ? 'active' : ''; ?>">
163+
<a class="page-link" href="<?= $buildParams ?>"><?= $i ?></a>
164+
</li>
165+
<?php endfor; ?>
166+
167+
<?php if(($pagination['page'] + 1) <= $pagination['pages']) : ?>
168+
<?php $queryParams['page'] = ++$pagination['page']; ?>
169+
<li class="page-item <?= ($pagination['page'] >= $pagination['pages']) ? 'disabled' : '' ?>">
170+
<a class="page-link" href="<?= '?' . http_build_query($queryParams); ?>">Next</a>
171+
</li>
172+
<?php endif; ?>
173+
174+
<?php if($pagination['page'] < $pagination['pages']) : ?>
175+
<?php $queryParams['page'] = $pagination['pages']; ?>
176+
<li class="page-item <?= ($pagination['page'] >= $pagination['pages']) ? 'disabled' : '' ?>">
177+
<a class="page-link" href="<?= '?' . http_build_query($queryParams); ?>">Last</a>
178+
</li>
179+
<?php endif; ?>
180+
</ul>
181+
</nav>
182+
183+
<?php else : ?>
184+
<h3><?= __d('LogReader', 'Please select one or more files for viewing') ?></h3>
185+
<?php endif; ?>
121186
</div>
122187
</div>
123188
</div>

0 commit comments

Comments
 (0)