Commit d3f11fcd authored by Jacob Priddy's avatar Jacob Priddy 👌

add request repository interfaces

parent 00307dc6
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Request extends Model
{
protected $fillable = ['title', 'request', 'reply', 'accepted', 'user_id'];
/**
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
...@@ -46,6 +46,14 @@ class User extends Authenticatable ...@@ -46,6 +46,14 @@ class User extends Authenticatable
return $this->hasMany(Override::class); return $this->hasMany(Override::class);
} }
/**
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function requests(): HasMany
{
return $this->hasMany(Request::class);
}
public static function boot() public static function boot()
{ {
parent::boot(); parent::boot();
...@@ -69,6 +77,11 @@ class User extends Authenticatable ...@@ -69,6 +77,11 @@ class User extends Authenticatable
foreach ($user->overrides() as $override) { foreach ($user->overrides() as $override) {
$override->delete(); $override->delete();
} }
/** @var \App\Request $request */
foreach ($user->requests() as $request) {
$request->delete();
}
}); });
} }
} }
...@@ -198,6 +198,7 @@ return [ ...@@ -198,6 +198,7 @@ return [
Source\Gateways\Entries\EntriesRepositoryServiceProvider::class, Source\Gateways\Entries\EntriesRepositoryServiceProvider::class,
Source\Gateways\Attempts\AttemptsRepositoryServiceProvider::class, Source\Gateways\Attempts\AttemptsRepositoryServiceProvider::class,
Source\Gateways\DoorUser\DoorUserRepositoryServiceProvider::class, Source\Gateways\DoorUser\DoorUserRepositoryServiceProvider::class,
Source\Gateways\Requests\RequestsRepositoryServiceProvider::class,
Source\Gateways\Schedules\SchedulesRepositoryServiceProvider::class, Source\Gateways\Schedules\SchedulesRepositoryServiceProvider::class,
Source\Gateways\DoorGroup\DoorGroupRepositoryServiceProvider::class, Source\Gateways\DoorGroup\DoorGroupRepositoryServiceProvider::class,
Source\Gateways\GroupUser\GroupUserRepositoryServiceProvider::class, Source\Gateways\GroupUser\GroupUserRepositoryServiceProvider::class,
......
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateRequestsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up(): void
{
Schema::create('requests', static function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('request');
$table->text('reply')->nullable();
$table->boolean('accepted')->nullable();
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down(): void
{
Schema::dropIfExists('requests');
}
}
<?php
namespace Source\Entities;
use Carbon\Carbon;
class Request
{
protected int $id;
protected string $title;
protected int $userId;
protected string $request;
protected ?string $reply;
protected ?bool $accepted;
/**
* @var \Carbon\Carbon|null
*/
protected ?Carbon $createdAt;
/**
* @var \Carbon\Carbon|null
*/
protected ?Carbon $updatedAt;
public function __construct(
int $id,
string $title,
int $userId,
string $request,
?string $reply = null,
?bool $accepted = null,
?Carbon $createdAt = null,
?Carbon $updatedAt = null
)
{
$this->id = $id;
$this->title = $title;
$this->userId = $userId;
$this->request = $request;
$this->reply = $reply;
$this->accepted = $accepted;
$this->createdAt = $createdAt;
$this->updatedAt = $updatedAt;
}
/**
* @return int
*/
public function getId(): int
{
return $this->id;
}
/**
* @return string
*/
public function getTitle(): string
{
return $this->title;
}
/**
* @return int
*/
public function getUserId(): int
{
return $this->userId;
}
/**
* @return string
*/
public function getRequest(): string
{
return $this->request;
}
/**
* @return string|null
*/
public function getReply(): ?string
{
return $this->reply;
}
/**
* @return bool|null
*/
public function getAccepted(): ?bool
{
return $this->accepted;
}
/**
* @return \Carbon\Carbon|null
*/
public function getCreatedAt(): ?Carbon
{
return $this->createdAt;
}
/**
* @return \Carbon\Carbon|null
*/
public function getUpdatedAt(): ?Carbon
{
return $this->updatedAt;
}
/**
* @param string $id
* @return bool
*/
public function hasIdOf(?string $id): bool
{
if ($id === null) {
return false;
}
return $this->getId() === (int)$id;
}
/**
* @param string|null $userId
* @return bool
*/
public function hasUserIdOf(?string $userId): bool
{
if ($userId === null) {
return false;
}
return $this->getUserId() === (int)$userId;
}
/**
* @param int $id
*/
public function setId(int $id): void
{
$this->id = $id;
}
}
...@@ -173,10 +173,6 @@ class DatabaseDoorsRepository implements DoorsRepository ...@@ -173,10 +173,6 @@ class DatabaseDoorsRepository implements DoorsRepository
throw new EntityNotFoundException('Could not update door. Door not found.'); throw new EntityNotFoundException('Could not update door. Door not found.');
} }
if ($dbDoor->getAttribute('name') !== $door->getName() && $this->findByName($door->getName())) {
throw new EntityExistsException();
}
$this->saveDoor($dbDoor, $door); $this->saveDoor($dbDoor, $door);
return self::makeDoorFromDb($dbDoor); return self::makeDoorFromDb($dbDoor);
......
...@@ -13,7 +13,7 @@ interface DoorsRepository ...@@ -13,7 +13,7 @@ interface DoorsRepository
* Create a new door * Create a new door
* *
* @param \Source\Entities\Door $door * @param \Source\Entities\Door $door
* @return \Source\Entities\Door|null * @return \Source\Entities\Door
* @throws \Source\Exceptions\EntityExistsException * @throws \Source\Exceptions\EntityExistsException
*/ */
public function create(Door $door): Door; public function create(Door $door): Door;
......
<?php
namespace Source\Gateways\Requests;
use Source\Entities\Request;
use Source\Sanitize\CastsTo;
use Illuminate\Database\Eloquent\Builder;
use Source\Exceptions\EntityNotFoundException;
class DatabaseRequestsRepository implements RequestsRepository
{
use CastsTo;
/**
* @param \App\Request $dbRequest
* @param \Source\Entities\Request $request
*/
protected static function saveRequest(\App\Request $dbRequest, Request $request): void
{
$dbRequest->setAttribute('title', $request->getTitle());
$dbRequest->setAttribute('request', $request->getRequest());
$dbRequest->setAttribute('reply', $request->getReply());
$dbRequest->setAttribute('accepted', $request->getAccepted());
$dbRequest->setAttribute('user_id', $request->getUserId());
$dbRequest->save();
}
/**
* @param \App\Request $request
* @return \Source\Entities\Request
*/
protected static function makeRequestFromDb(\App\Request $request): Request
{
return new Request(
$request->getAttribute('id'),
$request->getAttribute('title'),
$request->getAttribute('user_id'),
$request->getAttribute('request'),
$request->getAttribute('reply'),
$request->getAttribute('accepted'),
$request->getAttribute('created_at'),
$request->getAttribute('updated_at')
);
}
/**
* @inheritDoc
*/
public function create(Request $request): Request
{
$dbRequest = new \App\Request();
self::saveRequest($dbRequest, $request);
return self::makeRequestFromDb($dbRequest);
}
/**
* @inheritDoc
*/
public function search(?string $query = null): array
{
$q = \App\Request::query()->orderByDesc('updated_at');
if (!$query) {
$requests = $q->get()->values()->all();
} else {
$requests = $q
->where('title', 'ILIKE', "%$query%")
->orWhere('request', 'ILIKE', "%$query%")
->orWhere('reply', 'ILIKE', "%$query%")
->get()->values()->all();
}
return array_map(static function (\App\Request $request): Request {
return self::makeRequestFromDb($request);
}, $requests);
}
/**
* @inheritDoc
*/
public function pending(): array
{
$requests = \App\Request::query()
->whereNull('accepted')
->orderByDesc('created_at')
->get()->values()->all();
return array_map(static function (\App\Request $request): Request {
return self::makeRequestFromDb($request);
}, $requests);
}
/**
* @inheritDoc
*/
public function get(string $requestId): ?Request
{
/** @var \App\Request|null $request */
$request = \App\Request::query()->find(self::castToInt($requestId));
if (!$request) {
return null;
}
return self::makeRequestFromDb($request);
}
/**
* @inheritDoc
*/
public function filter(?string $userId = null, ?bool $accepted = null, ?bool $replied = null): array
{
$query = \App\Request::query()->orderByDesc('updated_at');
if ($userId !== null) {
$query->where('user_id', self::castToInt($userId));
}
if ($accepted !== null) {
$query->where('accepted', $accepted);
}
if ($replied !== null) {
if ($replied) {
$query->where(static function (Builder $builder) {
$builder->whereNotNull('reply')->orWhereNotNull('accepted');
});
} else {
$query->whereNull('reply')->whereNull('accepted');
}
}
return array_map(static function (\App\Request $request): Request {
return self::makeRequestFromDb($request);
}, $query->get()->values()->all());
}
/**
* @inheritDoc
*/
public function update(string $requestId, Request $request): Request
{
/** @var \App\Request|null $dbRequest */
$dbRequest = \App\Request::query()->find(self::castToInt($requestId));
if (!$dbRequest) {
throw new EntityNotFoundException('Could not update request. Request not found.');
}
self::saveRequest($dbRequest, $request);
return self::makeRequestFromDb($dbRequest);
}
}
<?php
namespace Source\Gateways\Requests;
use Source\Entities\Request;
use Source\Exceptions\EntityNotFoundException;
class InMemoryRequestsRepository implements RequestsRepository
{
/**
* @var \Source\Entities\Request[]
*/
protected array $requests = [];
/**
* @inheritDoc
*/
public function create(Request $request): Request
{
$this->requests[] = $request;
return $request;
}
/**
* @inheritDoc
*/
public function search(?string $query = null): array
{
if (!$query) {
return $this->requests;
}
return array_filter($this->requests, static function (Request $request) use ($query): bool {
return stripos($request->getTitle(), $query) !== false
|| stripos($request->getRequest(), $query) !== false
|| stripos($request->getReply(), $query) !== false;
});
}
/**
* @inheritDoc
*/
public function pending(): array
{
return array_filter($this->requests, fn (Request $request) => $request->getAccepted() === null);
}
/**
* @inheritDoc
*/
public function get(string $requestId): ?Request
{
foreach ($this->requests as $request) {
if ($request->hasIdOf($requestId)) {
return $request;
}
}
return null;
}
/**
* @inheritDoc
*/
public function filter(?string $userId = null, ?bool $accepted = null, ?bool $replied = null): array
{
$requests = $this->requests;
if ($userId !== null) {
$requests = array_filter($requests, fn (Request $request) => $request->hasUserIdOf($userId));
}
if ($accepted !== null) {
$requests = array_filter($requests, fn (Request $request) => $request->getAccepted() === $accepted);
}
if ($replied !== null) {
$requests = array_filter($requests, fn (Request $request) => $request->getAccepted() !== null || $request->getReply() !== null);
}
return $requests;
}
/**
* @inheritDoc
*/
public function update(string $requestId, Request $request): Request
{
foreach ($this->requests as &$requestBase) {
if ($requestBase->hasIdOf($requestId)) {
$request->setId($requestBase->getId());
$requestBase = $request;
return $requestBase;
}
}
throw new EntityNotFoundException('Request not found.');
}
}
<?php
namespace Source\Gateways\Requests;
use Carbon\Carbon;
use Source\Entities\Request;
use Source\Gateways\Users\LocalUsersRepository;
class LocalRequestsRepository extends InMemoryRequestsRepository
{
/**
* @throws \Source\Exceptions\EntityExistsException
* @throws \Exception
*/
public function __construct()
{
$now = Carbon::now();
$this->create(new Request(
1,
'gif access pls',
LocalUsersRepository::getComputerScienceStudent()->getId(),
'Please give 24 hour access to CSP315',
'No, you may not have 24 hour access, but you have working hour access',
true,
$now,
$now
));
$this->create(new Request(
2,
'Remove my access',
LocalUsersRepository::getComputerScienceStudent()->getId(),
'I don\'t want access to anything',
'No, you must have accesss.',
false,
$now,
$now
));
$this->create(new Request(
3,
'Pending request',
LocalUsersRepository::getEngineeringLabAccessStudent()->getId(),
'unpend my request you wench',
null,
null,
$now,
$now
));
$this->create(new Request(
4,
'Admins Pending request',
LocalUsersRepository::getAdminUser()->getId(),
'this is a pending request from the admin user',