Commit: 9531cd154db3a5e41b6e806226e9e371d2699f52
Author: Pieter Hordijk <[email protected]> Wed, 22 May 2019
21:06:46 +0300
Committer: Peter Kokot <[email protected]> Thu, 23 May 2019 02:46:24
+0200
Parents: e8bab3538a9d05d0da584c2ff8b18c7d9eea2fdd
Branches: master
Link:
http://git.php.net/?p=web/bugs.git;a=commitdiff;h=9531cd154db3a5e41b6e806226e9e371d2699f52
Log:
Converted the current admin pages (/admin) to use proper templates and
repositories
Changed paths:
M config/container.php
A src/Repository/DatabaseStatusRepository.php
A src/Repository/PhpInfoRepository.php
M src/Repository/ReasonRepository.php
A templates/pages/admin/database_status.php
A templates/pages/admin/mailing_lists.php
A templates/pages/admin/menu.php
A templates/pages/admin/phpinfo.php
A templates/pages/admin/quick_responses.php
M www/admin/index.php
M www/css/style.css
diff --git a/config/container.php b/config/container.php
index 59e3045..d869f44 100644
--- a/config/container.php
+++ b/config/container.php
@@ -33,6 +33,10 @@ $container->set(App\Repository\CommentRepository::class,
function ($c) {
return new App\Repository\CommentRepository($c->get(\PDO::class));
});
+$container->set(App\Repository\DatabaseStatusRepository::class, function ($c) {
+ return new App\Repository\DatabaseStatusRepository($c->get(\PDO::class));
+});
+
$container->set(App\Repository\ObsoletePatchRepository::class, function ($c) {
return new App\Repository\ObsoletePatchRepository($c->get(\PDO::class));
});
@@ -45,6 +49,10 @@ $container->set(App\Repository\PatchRepository::class,
function ($c) {
return new App\Repository\PatchRepository($c->get(\PDO::class),
$c->get('uploads_dir'));
});
+$container->set(App\Repository\PhpInfoRepository::class, function ($c) {
+ return new App\Repository\PhpInfoRepository();
+});
+
$container->set(App\Repository\PullRequestRepository::class, function ($c) {
return new App\Repository\PullRequestRepository($c->get(\PDO::class));
});
diff --git a/src/Repository/DatabaseStatusRepository.php
b/src/Repository/DatabaseStatusRepository.php
new file mode 100644
index 0000000..971ba42
--- /dev/null
+++ b/src/Repository/DatabaseStatusRepository.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace App\Repository;
+
+/**
+ * Repository class for fetching database status data presented under /admin
+ */
+class DatabaseStatusRepository
+{
+ /**
+ * Database handler.
+ * @var \PDO
+ */
+ private $dbh;
+
+ /**
+ * Class constructor.
+ */
+ public function __construct(\PDO $dbh)
+ {
+ $this->dbh = $dbh;
+ }
+
+ public function getMysqlVersion(): string
+ {
+ return $this->dbh->query('SELECT version()
mysql_version')->fetchColumn(0);
+ }
+
+ /**
+ * @return string[]
+ */
+ public function findAllTables(): array
+ {
+ return $this->dbh->query('SHOW TABLES')->fetchAll(\PDO::FETCH_COLUMN);
+ }
+
+ /**
+ * @return array<int,string>
+ */
+ public function getNumberOfRowsInTables(): array
+ {
+ $numberOfRowsPerTable = [];
+
+ foreach ($this->findAllTables() as $tableName) {
+ $sql = sprintf('SELECT COUNT(*) FROM `%s`', $tableName);
+
+ $numberOfRowsPerTable[$tableName] =
$this->dbh->query($sql)->fetchColumn(0);
+ }
+
+ return $numberOfRowsPerTable;
+ }
+
+ /**
+ * @return array<int,array<string,mixed>>
+ */
+ public function getStatusOfTables(): array
+ {
+ return $this->dbh->query('SHOW TABLE STATUS')->fetchAll();
+ }
+}
diff --git a/src/Repository/PhpInfoRepository.php
b/src/Repository/PhpInfoRepository.php
new file mode 100644
index 0000000..6542357
--- /dev/null
+++ b/src/Repository/PhpInfoRepository.php
@@ -0,0 +1,46 @@
+<?php
+
+namespace App\Repository;
+
+/**
+ * Repository class for fetching information about PHP's configuration
+ */
+class PhpInfoRepository
+{
+ public function getInfo(): string
+ {
+ ob_start();
+ phpinfo();
+
+ $phpInfo = $this->replaceSensitiveInformation(ob_get_clean());
+ $phpInfo = $this->cleanHtml($phpInfo);
+
+ return $phpInfo;
+ }
+
+ private function replaceSensitiveInformation(string $phpInfo): string
+ {
+ return str_replace([
+ getenv('AUTH_TOKEN'),
+ getenv('USER_TOKEN'),
+ getenv('USER_PWD_SALT'),
+ ], '<hidden>', $phpInfo);
+ }
+
+ /**
+ * This method unwrap the information from the body tag, removes zend and
php logos and fixes sizes
+ * for presentation purposes
+ *
+ * We might want to do it proper at some point using DOM methods
+ */
+ private function cleanHtml(string $phpInfo): string
+ {
+ preg_match('!<body.*?>(.*)</body>!ims', $phpInfo, $m);
+
+ $m[1] = preg_replace('!<a
href="http://www.php.net/"><img.*?></a>!ims', '', $m[1]);
+ $m[1] = preg_replace('!<a
href="http://www.zend.com/"><img.*?></a>!ims', '', $m[1]);
+ $m[1] = str_replace(' width="600"', ' width="80%"', $m[1]);
+
+ return $m[1];
+ }
+}
diff --git a/src/Repository/ReasonRepository.php
b/src/Repository/ReasonRepository.php
index fd4f411..b33d60a 100644
--- a/src/Repository/ReasonRepository.php
+++ b/src/Repository/ReasonRepository.php
@@ -52,4 +52,14 @@ class ReasonRepository
return [$resolves, $variations];
}
+
+ /**
+ * @return array<int,array<string,mixed>>
+ */
+ public function findAll(): array
+ {
+ $sql = 'SELECT * FROM bugdb_resolves';
+
+ return $this->dbh->query($sql)->fetchAll();
+ }
}
diff --git a/templates/pages/admin/database_status.php
b/templates/pages/admin/database_status.php
new file mode 100644
index 0000000..a1237ce
--- /dev/null
+++ b/templates/pages/admin/database_status.php
@@ -0,0 +1,75 @@
+<?php $this->extends('layout.php', ['title' => 'Admin :: Database status']) ?>
+
+<?php $this->start('content') ?>
+
+<?php $this->include('pages/admin/menu.php', ['action' => $action]); ?>
+
+<p>Running MySQL <b><?= $this->e($mysqlVersion); ?></b></p>
+
+<h3>Number of rows:</h3>
+
+<table>
+ <tbody>
+ <tr class="bug_header">
+ <th>Table</th>
+ <th>Rows</th>
+ </tr>
+ <?php foreach ($numberOfRowsPerTable as $tableName => $numberOfRows):
?>
+ <tr>
+ <td class="bug_bg0"><?= $this->e($tableName); ?></td>
+ <td class="bug_bg1"><?= $this->e($numberOfRows); ?></td>
+ </tr>
+ <?php endforeach ?>
+ </tbody>
+</table>
+
+<h3>Table status:</h3>
+
+<table>
+ <tbody>
+ <tr class="bug_header">
+ <th>Name</th>
+ <th>Engine</th>
+ <th>Version</th>
+ <th>Row_format</th>
+ <th>Rows</th>
+ <th>Avg_row_length</th>
+ <th>Data_length</th>
+ <th>Max_data_length</th>
+ <th>Index_length</th>
+ <th>Data_free</th>
+ <th>Auto_increment</th>
+ <th>Create_time</th>
+ <th>Update_time</th>
+ <th>Check_time</th>
+ <th>Collation</th>
+ <th>Checksum</th>
+ <th>Create_options</th>
+ <th>Comment</th>
+ </tr>
+ <?php foreach ($statusPerTable as $tableStatus): ?>
+ <tr>
+ <td class="bug_bg0"><?= $this->e($tableStatus['Name']); ?></td>
+ <td class="bug_bg1"><?= $this->e($tableStatus['Engine']);
?></td>
+ <td class="bug_bg0"><?= $tableStatus['Version']; ?></td>
+ <td class="bug_bg1"><?= $this->e($tableStatus['Row_format']);
?></td>
+ <td class="bug_bg0"><?= $tableStatus['Rows']; ?></td>
+ <td class="bug_bg1"><?= $tableStatus['Avg_row_length']; ?></td>
+ <td class="bug_bg0"><?= $tableStatus['Data_length']; ?></td>
+ <td class="bug_bg1"><?= $tableStatus['Max_data_length'];
?></td>
+ <td class="bug_bg0"><?= $tableStatus['Index_length']; ?></td>
+ <td class="bug_bg1"><?= $tableStatus['Data_free']; ?></td>
+ <td class="bug_bg0"><?= $tableStatus['Auto_increment']; ?></td>
+ <td class="bug_bg1"><?= $this->e($tableStatus['Create_time']);
?></td>
+ <td class="bug_bg0"><?= $this->e($tableStatus['Update_time']);
?></td>
+ <td class="bug_bg1"><?php echo $tableStatus['Check_time'] ?
$this->e($tableStatus['Check_time']) : ''; ?></td>
+ <td class="bug_bg0"><?= $this->e($tableStatus['Collation']);
?></td>
+ <td class="bug_bg1"><?php echo $tableStatus['Checksum'] ?
$this->e($tableStatus['Checksum']) : ''; ?></td>
+ <td class="bug_bg0"><?=
$this->e($tableStatus['Create_options']); ?></td>
+ <td class="bug_bg1"><?= $this->e($tableStatus['Comment']);
?></td>
+ </tr>
+ <?php endforeach ?>
+ </tbody>
+</table>
+
+<?php $this->end('content') ?>
diff --git a/templates/pages/admin/mailing_lists.php
b/templates/pages/admin/mailing_lists.php
new file mode 100644
index 0000000..e0e307d
--- /dev/null
+++ b/templates/pages/admin/mailing_lists.php
@@ -0,0 +1,18 @@
+<?php $this->extends('layout.php', ['title' => 'Admin :: Package mailing
lists']) ?>
+
+<?php $this->start('content') ?>
+
+<?php $this->include('pages/admin/menu.php', ['action' => $action]); ?>
+
+<dl>
+ <?php foreach ($lists as $list): ?>
+ <dt><?= $this->e($list['name']); ?>: </dt>
+ <dd>
+ <a href="mailto:<?= $this->noHtml($list['list_email']); ?>">
+ <?= $this->e($list['list_email']); ?>
+ </a>
+ </dd>
+ <?php endforeach ?>
+</dl>
+
+<?php $this->end('content') ?>
diff --git a/templates/pages/admin/menu.php b/templates/pages/admin/menu.php
new file mode 100644
index 0000000..7d716f7
--- /dev/null
+++ b/templates/pages/admin/menu.php
@@ -0,0 +1,17 @@
+<p>
+ <a href="/admin/?action=phpinfo" <?= ('phpinfo' === $action) ?
'class="active"' : ''; ?>>
+ phpinfo()
+ </a>
+ |
+ <a href="/admin/?action=list_lists" <?= ('list_lists' === $action) ?
'class="active"' : ''; ?>>
+ Package mailing lists
+ </a>
+ |
+ <a href="/admin/?action=list_responses" <?= ('list_responses' === $action)
? 'class="active"' : ''; ?>>
+ Quick fix responses
+ </a>
+ |
+ <a href="/admin/?action=mysql" <?= ('mysql' === $action) ?
'class="active"' : ''; ?>>
+ Database status
+ </a>
+</p>
diff --git a/templates/pages/admin/phpinfo.php
b/templates/pages/admin/phpinfo.php
new file mode 100644
index 0000000..c04b33e
--- /dev/null
+++ b/templates/pages/admin/phpinfo.php
@@ -0,0 +1,9 @@
+<?php $this->extends('layout.php', ['title' => 'Admin :: phpinfo()']) ?>
+
+<?php $this->start('content') ?>
+
+<?php $this->include('pages/admin/menu.php', ['action' => $action]); ?>
+
+<?= $info; ?>
+
+<?php $this->end('content') ?>
diff --git a/templates/pages/admin/quick_responses.php
b/templates/pages/admin/quick_responses.php
new file mode 100644
index 0000000..64dde7a
--- /dev/null
+++ b/templates/pages/admin/quick_responses.php
@@ -0,0 +1,38 @@
+<?php $this->extends('layout.php', ['title' => 'Admin :: Quick fix
responses']) ?>
+
+<?php $this->start('content') ?>
+
+<?php $this->include('pages/admin/menu.php', ['action' => $action]); ?>
+
+<h3>List Responses</h3>
+
+<table>
+ <tbody>
+ <tr class="bug_header">
+ <th>id</th>
+ <th>name</th>
+ <th>status</th>
+ <th>title</th>
+ <th>message</th>
+ <th>project</th>
+ <th>package_name</th>
+ <th>webonly</th>
+ </tr>
+ <?php foreach ($responses as $response): ?>
+ <tr>
+ <td class="bug_bg0"><?= $response['id']; ?></td>
+ <td class="bug_bg1"><?= $this->e($response['name']); ?></td>
+ <td class="bug_bg0"><?php echo $response['status'] ?
$this->e($response['status']) : ''; ?></td>
+ <td class="bug_bg1"><?= $this->e($response['title']); ?></td>
+ <td class="bug_bg0 tbl-row-message">
+ <?= nl2br($this->e($response['message'])); ?>
+ </td>
+ <td class="bug_bg1"><?= $this->e($response['project']); ?></td>
+ <td class="bug_bg0"><?php echo $response['package_name'] ?
$this->e($response['package_name']) : ''; ?></td>
+ <td class="bug_bg1"><?= $response['webonly']; ?></td>
+ </tr>
+ <?php endforeach ?>
+ </tbody>
+</table>
+
+<?php $this->end('content') ?>
diff --git a/www/admin/index.php b/www/admin/index.php
index 3d3affd..43dd0b6 100644
--- a/www/admin/index.php
+++ b/www/admin/index.php
@@ -1,11 +1,15 @@
<?php
+use App\Repository\DatabaseStatusRepository;
use App\Repository\PackageRepository;
+use App\Repository\PhpInfoRepository;
+use App\Repository\ReasonRepository;
+// Application bootstrap
require_once '../../include/prepend.php';
-session_start();
-bugs_authenticate($user, $pw, $logged_in, $user_flags);
+// Authentication
+require_once __DIR__.'/../../include/auth.php';
if (!$logged_in) {
response_header("Bugs admin suite");
@@ -13,102 +17,37 @@ if (!$logged_in) {
exit;
}
-$actions = [
- 'phpinfo' => 'phpinfo()',
- 'list_lists' => 'Package mailing lists',
- 'list_responses' => 'Quick fix responses',
- 'mysql' => 'Database status',
-];
-
-$action = !empty($_GET['action']) && isset($actions[$_GET['action']]) ?
$_GET['action'] : 'list_lists';
-
-response_header("Bugs admin suite");
-inline_content_menu('/admin/', $action, $actions);
-
-if ($action === 'phpinfo') {
- ob_start();
- phpinfo();
-
- $phpinfo = ob_get_clean();
-
- // Attempt to hide certain ENV vars
- $vars = [
- getenv('AUTH_TOKEN'),
- getenv('USER_TOKEN'),
- getenv('USER_PWD_SALT')
- ];
-
- $phpinfo = str_replace($vars, '<hidden>', $phpinfo);
-
- // Semi stolen from php-web
- $m = [];
-
- preg_match('!<body.*?>(.*)</body>!ims', $phpinfo, $m);
-
- $m[1] = preg_replace('!<a href="http://www.php.net/"><img.*?></a>!ims',
'', $m[1]);
- $m[1] = preg_replace('!<a href="http://www.zend.com/"><img.*?></a>!ims',
'', $m[1]);
- $m[1] = str_replace(' width="600"', ' width="80%"', $m[1]);
-
- echo $m[1];
-
-} elseif ($action === 'list_lists') {
- echo "<dl>\n";
- foreach ($container->get(PackageRepository::class)->findLists() as $row) {
- echo "<dt>", $row['name'], ": </dt>\n<dd>", mailto_list(explode(',',
$row['list_email'])), "</dd>\n";
- }
- echo "</dl>\n";
-} elseif ($action === 'list_responses') {
-
- $res = $dbh->query("
- SELECT *
- FROM bugdb_resolves
- ");
-
- echo "<h3>List Responses</h3>\n";
-
- $rows = [];
- while ($row = $res->fetch()) {
- // This is ugly but works (tm)
- $row['message'] = nl2br($row['message']);
-
- $rows[] = $row;
- }
-
- admin_table_dynamic($rows);
-} elseif ($action === 'mysql') {
- $res = $dbh->query("SHOW TABLES");
-
- $sql = "SELECT version() mysql_version\n";
-
- while ($row = $res->fetch(\PDO::FETCH_NUM)) {
- $table = $row[0];
- $sql .= "\t, (SELECT COUNT(*) FROM `$table`) `cnt_$table`\n";
- }
-
- $res = $dbh->query($sql);
- $row = $res->fetch();
-
- echo "<p>Running MySQL <b>".$row['mysql_version']."</b></p>";
- unset($row['mysql_version']);
-
- echo "<h3>Number of rows:</h3>\n";
-
- $rows = [];
-
- foreach($row as $key => $value) {
- $rows[] = [str_replace('cnt_', '', $key), $value];
- }
-
- admin_table_static(['Table', 'Rows'], $rows);
-
- $rows = [];
- $res = $dbh->query("SHOW TABLE STATUS");
- echo "<h3>Table status:</h3>\n";
- while ($row = $res->fetch()) {
- $rows[] = $row;
- }
-
- admin_table_dynamic($rows);
+$action = $_GET['action'] ?? 'list_lists';
+
+switch ($action) {
+ case 'phpinfo':
+ echo $template->render('pages/admin/phpinfo.php', [
+ 'action' => $action,
+ 'info' => $container->get(PhpInfoRepository::class)->getInfo(),
+ ]);
+ break;
+
+ case 'list_responses':
+ echo $template->render('pages/admin/quick_responses.php', [
+ 'action' => $action,
+ 'responses' => $container->get(ReasonRepository::class)->findAll(),
+ ]);
+ break;
+
+ case 'mysql':
+ echo $template->render('pages/admin/database_status.php', [
+ 'action' => $action,
+ 'mysqlVersion' =>
$container->get(DatabaseStatusRepository::class)->getMysqlVersion(),
+ 'numberOfRowsPerTable' =>
$container->get(DatabaseStatusRepository::class)->getNumberOfRowsInTables(),
+ 'statusPerTable' =>
$container->get(DatabaseStatusRepository::class)->getStatusOfTables(),
+ ]);
+ break;
+
+ case 'list_lists':
+ default:
+ echo $template->render('pages/admin/mailing_lists.php', [
+ 'action' => $action,
+ 'lists' => $container->get(PackageRepository::class)->findLists(),
+ ]);
+ break;
}
-
-response_footer();
diff --git a/www/css/style.css b/www/css/style.css
index a9b07b5..743ea14 100644
--- a/www/css/style.css
+++ b/www/css/style.css
@@ -676,6 +676,13 @@ td.tbl-row-message {
text-align: left;
}
+/* menu */
+a.active {
+ font-weight: bold;
+ color: black;
+ text-decoration: none;
+}
+
/* phpinfo() */
div.center {
margin: 0px auto;
--
PHP Webmaster List Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php