6 use Friendica\Capabilities\ICanCreateFromTableRow;
7 use Friendica\Database\Database;
8 use Friendica\Database\DBA;
9 use Friendica\Network\HTTPException\NotFoundException;
10 use Psr\Log\LoggerInterface;
13 * Depositories are meant to store and retrieve Entities from the database.
15 * The reason why there are methods prefixed with an underscore is because PHP doesn't support generic polymorphism
16 * which means we can't direcly overload base methods and make parameters more strict (from a parent class to a child
19 * Similarly, we can't make an overloaded method return type more strict until we only support PHP version 7.4 but this
22 abstract class BaseDepository
27 * @var string This should be set to the main database table name the depository is using
29 protected static $table_name;
34 /** @var LoggerInterface */
37 /** @var ICanCreateFromTableRow */
40 public function __construct(Database $database, LoggerInterface $logger, ICanCreateFromTableRow $factory)
42 $this->db = $database;
43 $this->logger = $logger;
44 $this->factory = $factory;
48 * Populates the collection according to the condition. Retrieves a limited subset of entities depending on the
49 * boundaries and the limit. The total count of rows matching the condition is stored in the collection.
51 * Depends on the corresponding table featuring a numerical auto incremented column called `id`.
53 * max_id and min_id are susceptible to the query order:
54 * - min_id alone only reliably works with ASC order
55 * - max_id alone only reliably works with DESC order
56 * If the wrong order is detected in either case, we reverse the query order and the entity list order after the query
60 * @param array $condition
61 * @param array $params
62 * @param int|null $min_id Retrieve models with an id no fewer than this, as close to it as possible
63 * @param int|null $max_id Retrieve models with an id no greater than this, as close to it as possible
65 * @return BaseCollection
68 protected function _selectByBoundaries(
69 array $condition = [],
73 int $limit = self::LIMIT
75 $totalCount = $this->count($condition);
77 $boundCondition = $condition;
79 $reverseOrder = false;
82 $boundCondition = DBA::mergeConditions($boundCondition, ['`id` > ?', $min_id]);
83 if (!isset($max_id) && isset($params['order']['id']) && ($params['order']['id'] === true || $params['order']['id'] === 'DESC')) {
86 $params['order']['id'] = 'ASC';
91 $boundCondition = DBA::mergeConditions($boundCondition, ['`id` < ?', $max_id]);
92 if (!isset($min_id) && (!isset($params['order']['id']) || $params['order']['id'] === false || $params['order']['id'] === 'ASC')) {
95 $params['order']['id'] = 'DESC';
99 $params['limit'] = $limit;
101 $Entities = $this->_select($boundCondition, $params);
103 $Entities->reverse();
106 return new BaseCollection($Entities->getArrayCopy(), $totalCount);
110 * @param array $condition
111 * @param array $params
112 * @return BaseCollection
115 protected function _select(array $condition, array $params = []): BaseCollection
117 $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params);
119 $Entities = new BaseCollection();
120 foreach ($rows as $fields) {
121 $Entities[] = $this->factory->createFromTableRow($fields);
128 * @param array $condition
129 * @param array $params
131 * @throws NotFoundException
133 protected function _selectOne(array $condition, array $params = []): BaseEntity
135 $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params);
136 if (!$this->db->isResult($fields)) {
137 throw new NotFoundException();
140 return $this->factory->createFromTableRow($fields);
144 * @param array $condition
145 * @param array $params
149 public function count(array $condition, array $params = []): int
151 return $this->db->count(static::$table_name, $condition, $params);
155 * @param array $condition
159 public function exists(array $condition): bool
161 return $this->db->exists(static::$table_name, $condition);