168 lines
5.7 KiB
PHP
168 lines
5.7 KiB
PHP
<?php
|
|
|
|
namespace php;
|
|
|
|
use Monolog\Logger;
|
|
use PDO;
|
|
|
|
|
|
/**
|
|
* Manages interaction with the database in the context of trackings.
|
|
*/
|
|
class TrackingManager
|
|
{
|
|
/**
|
|
* The maximum length of a Wikipedia page title.
|
|
*/
|
|
private const MAX_TITLE_LENGTH = 255;
|
|
|
|
/**
|
|
* @var Logger The logger to use for logging.
|
|
*/
|
|
private Logger $logger;
|
|
/**
|
|
* @var string The filename of the database to interact with.
|
|
*/
|
|
private string $db_filename;
|
|
/**
|
|
* @var Mediawiki The Mediawiki instance to use for interacting with Wikipedia.
|
|
*/
|
|
private Mediawiki $mediawiki;
|
|
|
|
|
|
/**
|
|
* Constructs a new tracking manager.
|
|
*
|
|
* @param Logger $logger the logger to use for logging
|
|
* @param string $db_filename the filename of the database to interact with
|
|
*/
|
|
public function __construct(Logger $logger, Mediawiki $mediawiki, string $db_filename)
|
|
{
|
|
$this->logger = $logger;
|
|
$this->mediawiki = $mediawiki;
|
|
$this->db_filename = $db_filename;
|
|
}
|
|
|
|
|
|
/**
|
|
* Populates the database with the necessary structures for users.
|
|
*
|
|
* @return void
|
|
*/
|
|
public function install(): void
|
|
{
|
|
$conn = Database::connect($this->db_filename);
|
|
$conn->exec("CREATE TABLE trackings(user_uuid text not null, person_name text not null, status text not null, PRIMARY KEY (user_uuid, person_name));");
|
|
}
|
|
|
|
/**
|
|
* Adds a tracking to the database.
|
|
*
|
|
* @param string $user_uuid the user to whom the tracking belongs
|
|
* @param string $person_name the name of the person to track
|
|
* @return Response a response with no message, and a status indicating whether the insertion succeeded
|
|
*/
|
|
public function add_tracking(string $user_uuid, string $person_name): Response
|
|
{
|
|
if (strlen($person_name) > self::MAX_TITLE_LENGTH)
|
|
return new Response("Invalid page name: too long.", false);
|
|
if (!$this->mediawiki->pages_exist([$person_name])[$person_name])
|
|
return new Response("Page does not exist.", false);
|
|
|
|
$status = $this->mediawiki->people_statuses([$person_name])[$person_name];
|
|
if ($status === null)
|
|
return new Response("Page does not refer to a person.", false);
|
|
|
|
$conn = Database::connect($this->db_filename);
|
|
$conn->beginTransaction();
|
|
|
|
$stmt = $conn->prepare("SELECT COUNT(*) as count FROM trackings WHERE user_uuid=:user_uuid AND person_name=:person_name;");
|
|
$stmt->bindValue(":user_uuid", $user_uuid);
|
|
$stmt->bindValue(":person_name", $person_name);
|
|
$stmt->execute();
|
|
if ($stmt->fetch(PDO::FETCH_ASSOC)["count"] > 0) {
|
|
$conn->rollBack();
|
|
return new Response("Tracking already exists.", false);
|
|
}
|
|
|
|
$stmt = $conn->prepare("INSERT INTO trackings (user_uuid, person_name, status) VALUES (:user_uuid, :person_name, :status);");
|
|
$stmt->bindValue(":user_uuid", $user_uuid);
|
|
$stmt->bindValue(":person_name", $person_name);
|
|
$stmt->bindValue(":status", $status);
|
|
$stmt->execute();
|
|
|
|
$conn->commit();
|
|
return new Response(null, true);
|
|
}
|
|
|
|
/**
|
|
* Removes a tracking from the database.
|
|
*
|
|
* @param string $user_uuid the user to whom the tracking belongs
|
|
* @param string $person_name the name of the tracked person to remove
|
|
* @return Response a response with no message, and a status indicating whether the removal succeeded
|
|
*/
|
|
public function remove_tracking(string $user_uuid, string $person_name): Response
|
|
{
|
|
if (strlen($person_name) > self::MAX_TITLE_LENGTH)
|
|
return new Response(null, false);
|
|
|
|
$conn = Database::connect($this->db_filename);
|
|
$stmt = $conn->prepare("DELETE FROM trackings WHERE user_uuid=:user_uuid AND person_name=:person_name;");
|
|
$stmt->bindValue(":user_uuid", $user_uuid);
|
|
$stmt->bindValue(":person_name", $person_name);
|
|
$stmt->execute();
|
|
|
|
return new Response(null, true);
|
|
}
|
|
|
|
/**
|
|
* Lists all trackings of the indicated user.
|
|
*
|
|
* @param string $user_uuid the user to return the trackings of
|
|
* @return Response a response with all trackings of the indicated user
|
|
*/
|
|
public function list_trackings(string $user_uuid): Response
|
|
{
|
|
$conn = Database::connect($this->db_filename);
|
|
$stmt = $conn->prepare("SELECT person_name, status FROM trackings WHERE user_uuid=:user_uuid;");
|
|
$stmt->bindValue(":user_uuid", $user_uuid);
|
|
$stmt->execute();
|
|
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
return new Response($results, true);
|
|
}
|
|
|
|
/**
|
|
* Lists all unique names being tracked in the database.
|
|
*
|
|
* @return string[] the unique names in the database
|
|
*/
|
|
public function list_all_trackings(): array
|
|
{
|
|
$conn = Database::connect($this->db_filename);
|
|
$stmt = $conn->prepare("SELECT DISTINCT person_name FROM trackings;");
|
|
$stmt->execute();
|
|
return array_column($stmt->fetchAll(PDO::FETCH_ASSOC), "person_name");
|
|
}
|
|
|
|
/**
|
|
* Updates trackings for the given names.
|
|
*
|
|
* @param string[] $people_names the names of the pages to update the tracking of
|
|
* @return void
|
|
*/
|
|
public function update_trackings(array $people_names): void
|
|
{
|
|
// TODO: Handle removed pages
|
|
$people_statuses = $this->mediawiki->people_statuses($people_names);
|
|
|
|
$conn = Database::connect($this->db_filename);
|
|
$stmt = $conn->prepare("UPDATE trackings SET status=:status WHERE person_name=:person_name;");
|
|
$stmt->bindParam(":status", $person_status);
|
|
$stmt->bindParam(":person_name", $person_name);
|
|
foreach ($people_statuses as $person_name => $person_status)
|
|
$stmt->execute();
|
|
}
|
|
}
|