%PDF- %PDF-
| Direktori : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Db/ |
| Current File : /www/varak.net/nextcloud.varak.net/apps_old/apps/passwords/lib/Db/AbstractMapper.php |
<?php
/*
* @copyright 2022 Passwords App
*
* @author Marius David Wieschollek
* @license AGPL-3.0
*
* This file is part of the Passwords App
* created by Marius David Wieschollek.
*/
namespace OCA\Passwords\Db;
use Exception;
use OCA\Passwords\Services\EnvironmentService;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\AppFramework\Db\QBMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
/**
* Class AbstractMapper
*
* @package OCA\Passwords\Db
*/
abstract class AbstractMapper extends QBMapper {
const TABLE_NAME = '';
const ALLOWED_OPERATORS = ['eq', 'neq', 'lt', 'gt', 'lte', 'gte'];
const FORBIDDEN_FIELDS = [];
/**
* @var string|null
*/
protected ?string $userId;
/**
* @var array
*/
protected array $entityCache = [];
/**
* AbstractMapper constructor.
*
* @param IDBConnection $db
* @param EnvironmentService $environment
*/
public function __construct(IDBConnection $db, EnvironmentService $environment) {
parent::__construct($db, static::TABLE_NAME);
$this->userId = $environment->getUserId();
}
/**
* @param Entity|EntityInterface $entity
*
* @return Entity|EntityInterface
* @throws \OCP\DB\Exception
*/
public function delete(Entity $entity): Entity {
if(isset($this->entityCache[ $entity->getUuid() ])) {
unset($this->entityCache[ $entity->getUuid() ]);
}
return parent::delete($entity);
}
/**
* @param Entity|EntityInterface $entity
*
* @return Entity|EntityInterface
* @throws \OCP\DB\Exception
*/
public function insert(Entity $entity): Entity {
$this->entityCache[ $entity->getUuid() ] = $entity;
return parent::insert($entity);
}
/**
* @param Entity|EntityInterface $entity
*
* @return Entity|EntityInterface
* @throws \OCP\DB\Exception
*/
public function update(Entity $entity): Entity {
$this->entityCache[ $entity->getUuid() ] = $entity;
return parent::update($entity);
}
/**
* @param string $uuid
*
* @return EntityInterface|Entity
*
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
*/
public function findByUuid(string $uuid): EntityInterface {
if(isset($this->entityCache[ $uuid ])) {
return $this->entityCache[ $uuid ];
}
return $this->findOneByField('uuid', $uuid);
}
/**
* @param string $userId
*
* @return EntityInterface[]
* @throws Exception
*/
public function findAllByUserId(string $userId): array {
return $this->findAllByField('user_id', $userId);
}
/**
* @return EntityInterface[]
* @throws \OCP\DB\Exception
*/
public function findAllDeleted(string $userId = null): array {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from(static::TABLE_NAME)
->where(
$qb->expr()->eq('deleted', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
);
if($this->userId !== null) {
$qb->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($this->userId))
);
} else if($userId !== null) {
$qb->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
);
}
return $this->findEntities($qb);
}
/**
* @return EntityInterface[]
* @throws \OCP\DB\Exception
*/
public function findAll(): array {
$sql = $this->getStatement();
return $this->findEntities($sql);
}
/**
* @param string $field
* @param string $value
* @param int $type
* @param string $operator
*
* @return EntityInterface|Entity
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
*/
public function findOneByField(string $field, string $value, int $type = IQueryBuilder::PARAM_STR, string $operator = 'eq'): EntityInterface {
return $this->findOneByFields([$field, $value, $type, $operator]);
}
/**
* @param string $field
* @param mixed $value
* @param int $type
* @param string $operator
*
* @return EntityInterface[]
* @throws Exception
*/
public function findAllByField(string $field, mixed $value, int $type = IQueryBuilder::PARAM_STR, string $operator = 'eq'): array {
return $this->findAllByFields([$field, $value, $type, $operator]);
}
/**
* @param array ...$fields
*
* @return EntityInterface|Entity
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
* @throws Exception
*/
public function findOneByFields(array ...$fields): EntityInterface {
$sql = $this->buildQuery($fields);
return $this->findEntity($sql);
}
/**
* @param array ...$fields
*
* @return array|Entity[]
* @throws Exception
*/
public function findAllByFields(array ...$fields): array {
$sql = $this->buildQuery($fields);
return $this->findEntities($sql);
}
/**
* Count all available items
* Respects user limitations
*
* @return int
*/
public function count(): int {
$qb = $this->db->getQueryBuilder();
$qb->selectAlias($qb->func()->count('id'), 'count')
->from(static::TABLE_NAME)
->where(
$qb->expr()->eq('deleted', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
);
if($this->userId !== null) {
$qb->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($this->userId))
);
}
return $qb->executeQuery()->fetch()['count'] ?? 0;
}
/**
* Clears the entity cache
*/
public function clearEntityCache(): void {
$this->entityCache = [];
}
/**
* @return IQueryBuilder
*/
protected function getStatement(): IQueryBuilder {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from(static::TABLE_NAME)
->where(
$qb->expr()->eq('deleted', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
);
if($this->userId !== null) {
$qb->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($this->userId))
);
}
return $qb;
}
/**
* @param string $toTable
* @param string $fromField
* @param string $toField
*
* @return IQueryBuilder
*/
protected function getJoinStatement(string $toTable, string $fromField = 'revision', string $toField = 'uuid'): IQueryBuilder {
$sql = $this->db->getQueryBuilder();
$sql->select('a.*')
->from(static::TABLE_NAME, 'a')
->innerJoin('a', $toTable, 'b', "a.`{$fromField}` = b.`{$toField}`")
->where(
$sql->expr()->eq('a.deleted', $sql->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
);
if($this->userId !== null) {
$sql->andWhere(
$sql->expr()->eq('a.user_id', $sql->createNamedParameter($this->userId)),
$sql->expr()->eq('b.user_id', $sql->createNamedParameter($this->userId))
);
}
return $sql;
}
/**
* @param array $fields
*
* @return IQueryBuilder
* @throws Exception
*/
protected function buildQuery(array $fields): IQueryBuilder {
$sql = $this->getStatement();
foreach($fields as $field) {
if(!isset($field[0])) throw new Exception('Field name is required but not set');
$name = $field[0];
$value = $field[1] ?? '';
$type = $field[2] ?? IQueryBuilder::PARAM_STR;
$op = $field[3] ?? 'eq';
if(in_array($name, static::FORBIDDEN_FIELDS)) throw new Exception('Forbidden field in database query');
if(!in_array($op, self::ALLOWED_OPERATORS)) throw new Exception('Forbidden operator in database query');
if($type !== IQueryBuilder::PARAM_NULL && $value !== null) {
$sql->andWhere(
$sql->expr()->{$op}($name, $sql->createNamedParameter($value, $type))
);
} else {
$op = $op === 'eq' ? 'isNull':'isNotNull';
$sql->andWhere($sql->expr()->{$op}($name));
}
}
return $sql;
}
/**
* @param array $row
*
* @return Entity
*/
protected function mapRowToEntity(array $row): Entity {
if(isset($row['uuid']) && isset($this->entityCache[ $row['uuid'] ])) {
return $this->entityCache[ $row['uuid'] ];
}
$entity = parent::mapRowToEntity($row);
if(isset($row['uuid'])) {
$this->entityCache[ $row['uuid'] ] = $entity;
}
return $entity;
}
}