From 9cf558a9ca712ec4a96b5b829cc948be784c94dc Mon Sep 17 00:00:00 2001
From: Kenneth Ezekiel <88850771+KenEzekiel@users.noreply.github.com>
Date: Mon, 25 Sep 2023 13:16:48 +0700
Subject: [PATCH] create Bases

---
 src/base/BaseController.php |  38 ++++++
 src/base/BaseModel.php      |  21 ++++
 src/base/BaseRepository.php | 234 ++++++++++++++++++++++++++++++++++++
 src/base/BaseService.php    |  16 +++
 4 files changed, 309 insertions(+)
 create mode 100644 src/base/BaseController.php
 create mode 100644 src/base/BaseModel.php
 create mode 100644 src/base/BaseRepository.php
 create mode 100644 src/base/BaseService.php

diff --git a/src/base/BaseController.php b/src/base/BaseController.php
new file mode 100644
index 0000000..7418ea5
--- /dev/null
+++ b/src/base/BaseController.php
@@ -0,0 +1,38 @@
+<?php
+
+require_once PROJECT_ROOT_PATH . "/src/exceptions/BadRequestException.php";
+require_once PROJECT_ROOT_PATH . "/src/exceptions/MethodNotAllowedException.php";
+
+abstract class BaseController {
+  protected static $instance;
+  protected $service;
+
+  protected function __construct($service) {
+    $this->service = $service;
+  }
+
+  public static function getInstance() {
+    if (!isset(self::$instance)) {
+      self::$instance = new static(null);
+    }
+    return self::$instance;
+  }
+
+  protected function get($urlParams) {
+    throw new MethodNotAllowedException("Method not allowed");  
+  }
+  protected function post($urlParams) {
+    throw new MethodNotAllowedException("Method not allowed");  
+  }
+  protected function put($urlParams) {
+    throw new MethodNotAllowedException("Method not allowed");  
+  }
+  protected function delete($urlParams) {
+    throw new MethodNotAllowedException("Method not allowed");
+  }
+
+  public function handle($method, $urlParams) {
+    $lowMethod = strtolower($method);
+    echo $this->$lowMethod($urlParams);
+  }
+}
\ No newline at end of file
diff --git a/src/base/BaseModel.php b/src/base/BaseModel.php
new file mode 100644
index 0000000..5e4a050
--- /dev/null
+++ b/src/base/BaseModel.php
@@ -0,0 +1,21 @@
+<?php
+
+abstract class BaseModel {
+  public $_primary_key = '';
+
+  public function __construct() {
+    return $this;
+  }
+
+  public function set($attr, $value) {
+    $this->$attr = $value;
+    return $this;
+  }
+
+  public function get($attr) {
+    return $this->$attr;
+  }
+  
+  abstract public function constructFromArray($array);
+  abstract public function toResponse();
+}
\ No newline at end of file
diff --git a/src/base/BaseRepository.php b/src/base/BaseRepository.php
new file mode 100644
index 0000000..fef3bb8
--- /dev/null
+++ b/src/base/BaseRepository.php
@@ -0,0 +1,234 @@
+<?php
+
+// Using PHP Data Objects Extension
+require_once PROJECT_ROOT_PATH . "/src/db/PDOInstance.php";
+
+abstract class BaseRepository
+{
+  protected static $instance;
+  // Holds instance of PDO connection
+  protected $pdo;
+  // Database table
+  protected $tableName = '';
+
+  protected function __construct()
+  {
+    $this->pdo = PDOInstance::getInstance()->getPDO();
+  }
+
+  public static function getInstance()
+  {
+    if (!isset(self::$instance)) {
+      self::$instance = new static();
+    }
+    return self::$instance;
+  }
+
+  public function getPDO()
+  {
+    return $this->pdo;
+  }
+
+  public function getAll()
+  {
+    $sql = "SELECT * FROM $this->tableName";
+    return $this->pdo->query($sql);
+  }
+
+  // Where (key: column name, value(0: value, 1: data type, 2: type of comparison either LIKE or =)) 
+
+  public function countRow($where = []) {
+    $sql = "SELECT COUNT(*) FROM $this->tableName";
+
+    if (count($where) > 0) {
+      // WHERE Query Building
+      $sql .= " WHERE ";
+      // Append Conditions
+      $sql .= implode(" AND ", array_map(function ($key, $value) {
+        if ($value[2] == 'LIKE') {
+          return "$key LIKE :$key";
+        }
+
+        return "$key = :$key";
+      }, array_keys($where), array_values($where)));
+    }
+    // Hydrating statement, for sanitizing
+    $stmt = $this->pdo->prepare($sql);
+    // Bind values
+    foreach ($where as $key => $value) {
+      // Binds parameter with appropriate data type 
+      if ($value[2] == 'LIKE') {
+        $stmt->bindValue(":$key", "%$value[0]%", $value[1]);
+      } else {
+        $stmt->bindValue(":$key", $value[0], $value[1]);
+      }
+    }
+
+    $stmt->execute();
+    return $stmt->fetchColumn();
+  }
+
+  public function findAll(
+    $where = [],
+    $order = null,
+    $pageNo = null,
+    $pageSize = null,
+    $isDesc = false,
+  ) {
+    $sql = "SELECT * FROM $this->tableName";
+
+    // Mapping where
+    if (count($where) > 0) {
+      $sql .= " WHERE ";
+      $sql .= implode(" AND ", array_map(function ($key, $value) {
+        if ($value[2] == 'LIKE') {
+          return "$key LIKE :$key";
+        }
+
+        return "$key = :$key";
+      }, array_keys($where), array_values($where)));
+    }
+
+    if ($order) {
+      $sql .= " ORDER BY $order";
+    }
+
+    if ($isDesc) {
+      $sql .= " DESC";
+    } else {
+      $sql .= " ASC";
+    }
+
+    if ($pageSize && $pageNo) {
+      $sql .= " LIMIT :pageSize";
+      $sql .= " OFFSET :pageNo";
+    }
+
+    // Hydrating statement, for sanitizing
+    $stmt = $this->pdo->prepare($sql);
+    
+    foreach ($where as $key => $value) {
+      if ($value[2] == 'LIKE') {
+        $stmt->bindValue(":$key", "%$value[0]%", $value[1]);
+      } else {
+        $stmt->bindValue(":$key", $value[0], $value[1]);
+      }
+    }
+
+    if ($pageSize && $pageNo) {
+      $offset = $pageSize * ($pageNo - 1);
+
+      $stmt->bindValue(":pageSize", $pageSize, PDO::PARAM_INT);
+      $stmt->bindValue(":offset", $offset, PDO::PARAM_INT);
+    }
+
+    $stmt->execute();
+
+    return $stmt->fetchAll();
+  }
+
+  public function findOne($where)
+  {
+    if (count($where) > 0) {
+      $sql .= " WHERE";
+      $sql .= implode(" AND ", array_map(function ($key, $value) {
+        if ($value[2] == 'LIKE') {
+          return "$key LIKE :$key";
+        }
+
+        return "$key = :$key";
+      }, array_keys($where), array_values($where)));
+    }
+
+    // Hydrating statement, for sanitizing
+    $stmt = $this->pdo->prepare($sql);
+    
+    foreach ($where as $key => $value) {
+      if ($value[2] == 'LIKE') {
+        $stmt->bindValue(":$key", "%$value[0]%", $value[1]);
+      } else {
+        $stmt->bindValue(":$key", $value[0], $value[1]);
+      }
+    }
+
+    $stmt->execute();
+
+    return $stmt->fetch();
+  }
+
+  public function insert($model, $arrParams)
+  {
+    $sql = "INSERT INTO $this->tableName (";
+    $sql .= implode(", ", array_keys($arrParams));
+    $sql .= ") VALUES (";
+    $sql .= implode(", ", array_map(function ($key, $value) {
+      return ":$key";
+    }, array_keys($arrParams), array_values($arrParams)));
+    $sql .= ")";
+
+    $stmt = $this->pdo->prepare($sql);
+    // Hydrating and sanitizing
+    foreach($arrParams as $key => $value) {
+      $stmt->bindValue(":$key", $model->get($key), $value);
+    }
+
+    $stmt->execute();
+    return $this->pdo->lastInsertId();
+    
+  }
+
+  public function update($model, $where)
+  {
+    $sql = "UPDATE $this->tableName SET ";
+    $sql .= implode(", ", array_map(function ($key, $value) {
+      return "$key = :$key";
+    }, array_keys($arrParams), array_values($arrParams)));
+    $sql .= ")";
+    $primaryKey = $model->get('_primary_key');
+    $sql .= " WHERE $primaryKey = :primaryKey";
+    
+    $stmt = $this->pdo->prepare($sql);
+    // Hydrating and sanitizing
+    foreach($arrParams as $key => $value) {
+      $stmt->bindValue(":$key", $model->get($key), $value);
+    }
+
+    $stmt->bindValue(":primaryKey", $model->get($primaryKey), PDO::PARAM_INT);
+
+    $stmt->execute();
+    return $stmt->rowCount();
+  }
+
+  public function delete($model)
+  {
+    $sql = "DELETE FROM $this->tableName WHERE ";
+    $primaryKey = $model->get('_primary_key');
+    $sql .= "$primaryKey = :primaryKey";
+
+    $stmt = $this->pdo->prepare($sql);
+    $stmt->bindValue(":primaryKey", $model->get('$primaryKey'), PDO::PARAM_INT);
+
+    $stmt->execute();
+    return $stmt->rowCount();
+  }
+
+  public function getNLastRow($N)
+  {
+    $sql = "SELECT COUNT(*) FROM $this->tableName";
+    $stmt = $this->pdo->prepare($sql);
+    $stmt->execute();
+    $count = $stmt->fetchColumn();
+
+    if ($count < $N) {
+      $N = $count;
+    }
+
+    $offset = $count - $N;
+    $sql = "SELECT * FROM $this->tableName LIMIT :limit OFFSET :offset";
+    $stmt = $this->pdo->prepare($sql);
+    $stmt->bindValue(":limit", $N, PDO::PARAM_INT);
+    $stmt->bindValue(":offset", $offset, PDO::PARAM_INT);
+    $stmt->execute();
+    return $stmt->fetchAll();
+  }
+}
\ No newline at end of file
diff --git a/src/base/BaseService.php b/src/base/BaseService.php
new file mode 100644
index 0000000..92c3140
--- /dev/null
+++ b/src/base/BaseService.php
@@ -0,0 +1,16 @@
+<?php
+
+abstract class BaseService {
+  protected static $instance;
+  protected $repository;
+
+  protected function __construct() {
+  }
+
+  public static function getInstance() {
+    if (!isset(self::$instance)) {
+      self::$instance = new static();
+    }
+    return self::$instance;
+  }
+}
\ No newline at end of file
-- 
GitLab