Skip to content

Commit

Permalink
Add PdoRepository abstracting Pdo Searcher calls
Browse files Browse the repository at this point in the history
  • Loading branch information
glensc committed Oct 1, 2020
1 parent d3de027 commit 414c95b
Show file tree
Hide file tree
Showing 3 changed files with 188 additions and 114 deletions.
167 changes: 167 additions & 0 deletions src/Xhgui/Db/PdoRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php

namespace XHGui\Db;

use Generator;
use PDO;
use RuntimeException;

class PdoRepository
{
/** @var PDO */
private $pdo;

/** @var string */
private $table;

/**
* @param PDO $pdo An open database connection
* @param string $table Table name where Xhgui profiles are stored
*/
public function __construct(PDO $pdo, string $table)
{
$this->pdo = $pdo;
$this->table = sprintf('"%s"', $table);
}

public function getLatest(): array
{
$query = sprintf('
SELECT
"id",
"profile",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro,"
"request_date"
FROM %s
ORDER BY "request_date" ASC
LIMIT 1',
$this->table
);
$stmt = $this->pdo->query($query);

$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
throw new RuntimeException('No profile available yet.');
}

return $row;
}

public function getById(string $id): array
{
$query = sprintf('
SELECT
"profile",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro",
"request_date"
FROM %s
WHERE id = :id
', $this->table);
$stmt = $this->pdo->prepare($query);
$stmt->execute(['id' => $id]);

$row = $stmt->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
throw new RuntimeException('No profile data found.');
}

return $row;
}

public function countByUrl(string $url): int
{
$query = sprintf('
SELECT COUNT(*) AS count
FROM %s
WHERE "simple_url" LIKE :url
', $this->table);
$stmt = $this->pdo->prepare($query);
$stmt->execute(['url' => '%' . $url . '%']);

return (int)$stmt->fetchColumn();
}

public function findByUrl(string $url, string $direction, int $skip, int $perPage): Generator
{
$query = sprintf('
SELECT
"id",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro",
"request_date",
"main_wt",
"main_ct",
"main_cpu",
"main_mu",
"main_pmu"
FROM %s
WHERE "simple_url" LIKE :url
ORDER BY "request_ts" %s
LIMIT %d OFFSET %d',
$this->table,
$direction,
$skip,
$perPage
);
$stmt = $this->pdo->prepare($query);
$stmt->execute(['url' => '%' . $url . '%']);

while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
yield $row;
}
}

public function deleteById(string $id)
{
$stmt = $this->pdo->prepare(sprintf('
DELETE FROM %s
WHERE id = :id
', $this->table));

$stmt->execute(['id' => $id]);
}

public function deleteAll()
{
return is_int(
$this->pdo->exec(sprintf('DELETE FROM %s', $this->table))
);
}

public function getStatistics()
{
$stmt = $this->pdo->query(
sprintf(
'
SELECT
COUNT(*) AS profiles,
MAX("request_ts") AS latest,
SUM(LENGTH("profile")) AS bytes
FROM %s',
$this->table
),
PDO::FETCH_ASSOC
);

$row = $stmt->fetch(PDO::FETCH_ASSOC);

return $row ?: null;
}
}
128 changes: 15 additions & 113 deletions src/Xhgui/Searcher/PdoSearcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,58 +2,25 @@

namespace XHGui\Searcher;

use Exception;
use PDO;
use XHGui\Db\PdoRepository;
use XHGui\Profile;

class PdoSearcher implements SearcherInterface
{
/**
* @var PDO
*/
private $pdo;

/**
* @var string
*/
private $table;
/** @var PdoRepository */
private $db;

/**
* @param PDO $pdo An open database connection
* @param string $table Table name where Xhgui profiles are stored
*/
public function __construct(PDO $pdo, $table)
public function __construct(PdoRepository $db)
{
$this->pdo = $pdo;
$this->table = $table;
$this->db = $db;
}

/**
* {@inheritdoc}
*/
public function latest()
public function latest(): Profile
{
$stmt = $this->pdo->query('
SELECT
"id",
"profile",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro,"
"request_date"
FROM "' . $this->table . '"
ORDER BY "request_date" ASC
LIMIT 1
');

$row = $stmt->fetch(PDO::FETCH_ASSOC);
if (false === $row) {
throw new Exception('No profile available yet.');
}
$row = $this->db->getLatest();

return new Profile([
'_id' => $row['id'],
Expand Down Expand Up @@ -82,28 +49,9 @@ public function query($conditions, $limit, $fields = [])
/**
* {@inheritdoc}
*/
public function get($id)
public function get($id): Profile
{
$stmt = $this->pdo->prepare('
SELECT
"profile",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro",
"request_date"
FROM "' . $this->table . '"
WHERE id = :id
');

$stmt->execute(['id' => $id]);

if (false === $row = $stmt->fetch(PDO::FETCH_ASSOC)) {
throw new Exception('No profile data found.');
}
$row = $this->db->getById($id);

return new Profile([
'_id' => $id,
Expand Down Expand Up @@ -150,53 +98,22 @@ public function getAvgsForUrl($url, $search = [])
*/
public function getAll($options = [])
{
$sort = $options['sort'];
$direction = $options['direction'];
$page = (int)$options['page'];
if ($page < 1) {
$page = 1;
}
$perPage = (int)$options['perPage'];
$url = $options['conditions']['url'] ?? "";

$stmt = $this->pdo->prepare('
SELECT COUNT(*) AS count
FROM "' . $this->table . '"
WHERE "simple_url" LIKE :url
');
$stmt->execute(['url' => '%'.$url.'%']);
$totalRows = (int)$stmt->fetchColumn();

$totalRows = $this->db->countByUrl($url);
$totalPages = max(ceil($totalRows/$perPage), 1);
if ($page > $totalPages) {
$page = $totalPages;
}
$skip = ($page-1) * $perPage;

$stmt = $this->pdo->prepare('
SELECT
"id",
"url",
"SERVER",
"GET",
"ENV",
"simple_url",
"request_ts",
"request_ts_micro",
"request_date",
"main_wt",
"main_ct",
"main_cpu",
"main_mu",
"main_pmu"
FROM "' . $this->table . '"
WHERE "simple_url" LIKE :url
ORDER BY "request_ts" ' . $direction. '
LIMIT ' . $skip . ' OFFSET ' . $perPage);
$stmt->execute(['url' => '%'.$url.'%']);

$results = [];
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
foreach ($this->db->findByUrl($url, $direction, $skip, $perPage) as $row) {
$results[] = new Profile([
'_id' => $row['id'],
'meta' => [
Expand Down Expand Up @@ -236,22 +153,15 @@ public function getAll($options = [])
*/
public function delete($id)
{
$stmt = $this->pdo->prepare('
DELETE FROM "' . $this->table . '"
WHERE id = :id
');

$stmt->execute(['id' => $id]);
$this->db->deleteById($id);
}

/**
* {@inheritdoc}
*/
public function truncate()
{
return is_int(
$this->pdo->exec('DELETE FROM "' . $this->table . '"')
);
return $this->db->deleteAll();
}

/**
Expand Down Expand Up @@ -282,17 +192,9 @@ public function truncateWatches()
*/
public function stats()
{
$stmt = $this->pdo->query('
SELECT
COUNT(*) AS profiles,
MAX("request_ts") AS latest,
SUM(LENGTH("profile")) AS bytes
FROM "' . $this->table . '"
', PDO::FETCH_ASSOC);

$row = $stmt->fetch(PDO::FETCH_ASSOC);
$row = $this->db->getStatistics();

if (false === $row) {
if (!$row) {
$row = [
'profiles' => 0,
'latest' => 0,
Expand Down
7 changes: 6 additions & 1 deletion src/Xhgui/ServiceContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Slim\Middleware\SessionCookie;
use Slim\Slim;
use Slim\Views\Twig;
use XHGui\Db\PdoRepository;
use XHGui\Middleware\RenderMiddleware;
use XHGui\Searcher\MongoSearcher;
use XHGui\Searcher\PdoSearcher;
Expand Down Expand Up @@ -129,12 +130,16 @@ protected function _services()
);
};

$this[PdoRepository::class] = static function ($c) {
return new PdoRepository($c['pdo'], $c['config']['pdo']['table']);
};

$this['searcher.mongodb'] = static function ($c) {
return new MongoSearcher($c['db']);
};

$this['searcher.pdo'] = static function ($c) {
return new PdoSearcher($c['pdo'], $c['config']['pdo']['table']);
return new PdoSearcher($c[PdoRepository::class]);
};

$this['searcher'] = static function ($c) {
Expand Down

0 comments on commit 414c95b

Please sign in to comment.