From ff69fa162959cb77384c1b4107c4e5a3c3be75c5 Mon Sep 17 00:00:00 2001
From: Hypolite Petovan <hypolite@mrpetovan.com>
Date: Wed, 11 Dec 2019 03:30:29 -0500
Subject: [PATCH] Add new BaseModel class

---
 src/BaseModel.php | 95 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 95 insertions(+)
 create mode 100644 src/BaseModel.php

diff --git a/src/BaseModel.php b/src/BaseModel.php
new file mode 100644
index 0000000000..32011c7db2
--- /dev/null
+++ b/src/BaseModel.php
@@ -0,0 +1,95 @@
+<?php
+
+namespace Friendica;
+
+use Friendica\Database\Database;
+use Friendica\Network\HTTPException;
+use Psr\Log\LoggerInterface;
+
+/**
+ * Class BaseModel
+ *
+ * The Model classes inheriting from this abstract class are meant to represent a single database record.
+ * The associated table name has to be provided in the child class, and the table is expected to have a unique `id` field.
+ *
+ * @property int id
+ */
+abstract class BaseModel
+{
+	protected static $table_name;
+
+	/** @var Database */
+	protected $dba;
+	/** @var LoggerInterface */
+	protected $logger;
+
+	/**
+	 * Model record abstraction.
+	 * Child classes never have to interact directly with it.
+	 * Please use the magic getter instead.
+	 *
+	 * @var array
+	 */
+	private $data = [];
+
+	public function __construct(Database $dba, LoggerInterface $logger)
+	{
+		$this->dba = $dba;
+		$this->logger = $logger;
+	}
+
+	/**
+	 * Magic getter. This allows to retrieve model fields with the following syntax:
+	 * - $model->field (outside of class)
+	 * - $this->field (inside of class)
+	 *
+	 * @param $name
+	 * @return mixed
+	 * @throws HTTPException\InternalServerErrorException
+	 */
+	public function __get($name)
+	{
+		if (empty($this->data['id'])) {
+			throw new HTTPException\InternalServerErrorException(static::class . ' record uninitialized');
+		}
+
+		if (!array_key_exists($name, $this->data)) {
+			throw new HTTPException\InternalServerErrorException('Field ' . $name . ' not found in ' . static::class);
+		}
+
+		return $this->data[$name];
+	}
+
+	/**
+	 * Fetches a single model record. The condition array is expected to contain a unique index (primary or otherwise).
+	 *
+	 * Chainable.
+	 *
+	 * @param array $condition
+	 * @return BaseModel
+	 * @throws HTTPException\NotFoundException
+	 */
+	public function fetch(array $condition)
+	{
+		$intro = $this->dba->selectFirst(static::$table_name, [], $condition);
+
+		if (!$intro) {
+			throw new HTTPException\NotFoundException(static::class . ' record not found.');
+		}
+
+		$this->data = $intro;
+
+		return $this;
+	}
+
+	/**
+	 * Deletes the model record from the database.
+	 * Prevents further methods from being called by wiping the internal model data.
+	 */
+	public function delete()
+	{
+		if ($this->dba->delete(static::$table_name, ['id' => $this->id])) {
+			$this->data = [];
+		}
+	}
+}