summaryrefslogtreecommitdiff
path: root/frontend/Model.php
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/Model.php')
-rw-r--r--frontend/Model.php138
1 files changed, 138 insertions, 0 deletions
diff --git a/frontend/Model.php b/frontend/Model.php
new file mode 100644
index 0000000..0f70aa2
--- /dev/null
+++ b/frontend/Model.php
@@ -0,0 +1,138 @@
+<?php
+class ModelNotFoundException extends Exception {}
+class ModelCreateFailedException extends Exception {}
+class ModelIllegalAccessException extends Exception {}
+class ModelSetFailedException extends Exception {}
+
+abstract class Model {
+ public static
+ $table = '',
+ $primary_key = 'id',
+ $protected_columns = ['id'],
+ $fillable_columns = [],
+ $timestamps = [],
+ $dates = [],
+ $booleans = [];
+
+ protected $pdo, $data;
+
+ const TABLE_PREFIX = '';
+
+ public function __construct($pdo, $id) {
+ $this->pdo = $pdo;
+
+ $stmt = $this->pdo->prepare("SELECT * FROM `".self::table()."` WHERE `".static::$primary_key."`=?");
+ $stmt->execute([$id]);
+ if ($stmt->rowCount() == 0) {
+ throw new ModelNotFoundException("The ".static::$table." with id '$id' could not be found.");
+ }
+ $this->data = $stmt->fetch(PDO::FETCH_ASSOC);
+ }
+
+ public function __set($key, $value) {
+ if (!in_array($key, static::$fillable_columns)) {
+ throw new ModelIllegalAccessException("Column `".self::table()."`.`$key` cannot be edited.");
+ }
+ if ($this->data[$key] == $value) {
+ return;
+ }
+ $stmt = $this->pdo->prepare("UPDATE `".self::table()."` SET `$key`=? WHERE `".static::$primary_key."`=?");
+ $stmt->execute([
+ $this->mutator($key, $value),
+ $this->data[static::$primary_key]
+ ]);
+ if ($stmt->rowCount() != 1) {
+ throw new ModelSetFailedException("Failed to update `".self::table()."`.`$key` to '$value'.");
+ }
+ $this->data[$key] = $value;
+ }
+
+ public function __get($key) {
+ return $this->accessor($key, $this->data[$key]);
+ }
+
+ public static function create($pdo, $values) {
+ $class = get_called_class();
+
+ $columns = array_combine(static::$fillable_columns, $values);
+ $questions = [];
+
+ foreach ($columns as $column => $value) {
+ $columns[$column] = $class::mutator($column, $value);
+ $questions[] = '?';
+ }
+
+ $stmt = $pdo->prepare(
+ "INSERT INTO `".self::table()."` " .
+ "(`" . implode('`, `', array_keys($columns)) . "`) " .
+ "VALUES (" . implode(',', $questions) . ")");
+ $stmt->execute(array_values($columns));
+
+ if ($stmt->rowCount() != 1)
+ throw new ModelCreateFailedException();
+
+ return new $class($pdo, $pdo->lastInsertId());
+ }
+
+ public static function searchIds($pdo, $where = [], $values = []) {
+ $stmt = $pdo->prepare("SELECT `id` FROM `".static::table()."`" . ((count($where) > 0) ? (" WHERE (" . implode(') AND (', $where) . ")") : ""));
+ $stmt->execute($values);
+
+ $ids = [];
+ foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
+ $ids[] = $row['id'];
+ }
+ return $ids;
+ }
+
+ public static function search($pdo, $where = [], $values = []) {
+ $class = get_called_class();
+
+ $items = [];
+ foreach (self::searchIds($pdo, $where, $values) as $id) {
+ $items[] = new $class($pdo, $id);
+ }
+ return $items;
+ }
+
+ public static function count($pdo, $where = [], $values = []) {
+ $class = get_called_class();
+
+ $stmt = $pdo->prepare("SELECT COUNT(*) FROM `".static::table()."`" . ((count($where) > 0) ? (" WHERE (" . implode(') AND (', $where) . ")") : ""));
+ $stmt->execute($values);
+
+ return $stmt->fetchColumn();
+ }
+
+ protected static function accessor($key, $value) {
+ if (is_null($value)) {
+ return null;
+ } elseif (in_array($key, static::$booleans)) {
+ return (bool) $value;
+ } elseif (in_array($key, static::$dates) || in_array($key, static::$timestamps)) {
+ return strtotime($value);
+ } else {
+ return $value;
+ }
+ }
+
+ protected static function mutator($key, $value) {
+ if (in_array($key, static::$dates) && is_int($value)) {
+ return date('Y-m-d', $value);
+ } elseif (in_array($key, static::$timestamps) && is_int($value)) {
+ return date('Y-m-d H:i:s', $value);
+ } else {
+ return (string) $value;
+ }
+ }
+
+ public function delete() {
+ $stmt = $this->pdo->prepare("DELETE FROM `".self::table()."` WHERE `".static::$primary_key."`=?");
+ $stmt->execute([$this->data[static::$primary_key]]);
+ return $stmt->rowCount() != 0;
+ }
+
+ private static function table() {
+ return self::TABLE_PREFIX . static::$table;
+ }
+}