Skip to content

Commit

Permalink
feat: create onion architectue with successfully testing register
Browse files Browse the repository at this point in the history
  • Loading branch information
Caknoooo committed Dec 6, 2023
1 parent 4dcf96d commit e44397d
Show file tree
Hide file tree
Showing 17 changed files with 628 additions and 22 deletions.
106 changes: 106 additions & 0 deletions app/Core/Application/Image/ImageUpload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

namespace App\Core\Application\Image;

use App\Exceptions\UserException;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;

class ImageUpload
{
private UploadedFile $uploaded_file;
private array $available_type;
private array $available_mime_type;
private int $max_size;
private string $path;
private string $seed;
private string $file_name;

/**
* @param UploadedFile $uploaded_file
* @param array $available_type
* @param array $available_mime_type
* @param int $max_size
* @param string $path
* @param string $seed
*/
public function __construct(

Check failure on line 27 in app/Core/Application/Image/ImageUpload.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @param references unknown parameter: $available_mime_type

Check failure on line 27 in app/Core/Application/Image/ImageUpload.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @param references unknown parameter: $available_type

Check failure on line 27 in app/Core/Application/Image/ImageUpload.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @param references unknown parameter: $max_size
UploadedFile $uploaded_file,
string $path,
string $seed,
string $file_name,
) {
$this->uploaded_file = $uploaded_file;

$this->available_type = [
'jpg',
'jpeg',
'png',
];

$this->available_mime_type = [
'image/jpeg',
'image/png',
'image/jpg',
];

$this->max_size = 1024 * 1024 * 2;
$this->path = $path;
$this->seed = $seed;
$this->file_name = trim($file_name);

$this->check();
}

/**
* @throws Exception
*/
public static function create(

Check failure on line 58 in app/Core/Application/Image/ImageUpload.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @throws with type App\Core\Application\Image\Exception is not subtype of Throwable
UploadedFile $uploaded_file,
string $path,
string $seed,
string $file_name,
): self {
return new self($uploaded_file, $path, $seed, $file_name);
}

/**
* @throws Exception
*/
public function check(): void

Check failure on line 70 in app/Core/Application/Image/ImageUpload.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @throws with type App\Core\Application\Image\Exception is not subtype of Throwable
{
if(!in_array($this->uploaded_file->getClientOriginalExtension(), $this->available_type)) {
throw new UserException('file type not allowed', 400);
}

if(!in_array($this->uploaded_file->getMimeType(), $this->available_mime_type)) {
throw new UserException('file mime type not allowed', 400);
}

if($this->uploaded_file->getSize() > $this->max_size) {
throw new UserException('file size greather than 2Mb', 400);
}
}

/**
* @return string
*/
public function upload(): string
{
$file_front = str_replace(" ", "_", strtolower($this->file_name));
$encrypted_seed = base64_encode($this->seed);
$uploaded = Storage::putFileAs(
"public/" . $this->path,
$this->uploaded_file,
$file_front . "_" . $encrypted_seed . "." . $this->uploaded_file->getClientOriginalExtension()
);

if(!$uploaded) {
throw new UserException('file upload failed', 500);
}

$full_path = "/storage/" . $this->path . "/" . $file_front . "_" . $encrypted_seed . "." . $this->uploaded_file->getClientOriginalExtension();

return $full_path;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace App\Core\Application\Service\User\RegisterUser;

use Illuminate\Http\UploadedFile;

class RegisterUserRequest
{
private string $name;
private string $email;
private UploadedFile $image;
private string $password;

public function __construct(
string $name,
string $email,
UploadedFile $image,
string $password
) {
$this->name = $name;
$this->email = $email;
$this->image = $image;
$this->password = $password;
}

/**
* @return string
*/
public function getName(): string
{
return $this->name;
}

/**
* @return string
*/
public function getEmail(): string
{
return $this->email;
}

/**
* @return UploadedFile
*/
public function getImage(): UploadedFile
{
return $this->image;
}

/**
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace App\Core\Application\Service\User\RegisterUser;

use App\Core\Application\Image\ImageUpload;
use App\Core\Domain\Infrastructure\Interfaces\UserRepositoryInterface;
use App\Core\Domain\Models\Email;
use App\Core\Domain\Models\User\User;
use App\Exceptions\UserException;

class RegisterUserService
{
private UserRepositoryInterface $user_repository;

/**
* @param UserRepositoryInterface $user_repository
*/
public function __construct(UserRepositoryInterface $user_repository)
{
$this->user_repository = $user_repository;
}

/**
* @throws UserException
*/
public function execute(RegisterUserRequest $request)
{
$registeredUser = $this->user_repository->getUserByEmail($request->getEmail());
if($registeredUser) {
throw new UserException('email telah terdaftar', 1002, 404);
}

$image_url = ImageUpload::create(
$request->getImage(),
'images',
$request->getEmail(),
'profile'
)->upload();

$user = User::create(
$request->getName(),
new Email($request->getEmail()),
$image_url,
$request->getPassword()
);

$this->user_repository->persist($user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Core\Domain\Infrastructure\Interfaces;

use App\Core\Domain\Models\User\User;

interface UserRepositoryInterface
{
public function persist(User $user): void;

public function find(string $id): ?User;

public function getAll(): ?array;

public function getUserByEmail(string $email): ?User;

public function updateUser(User $user): void;

public function constructFromRows(array $rows): ?array;
}
95 changes: 95 additions & 0 deletions app/Core/Domain/Infrastructure/Repository/SqlUserRepository.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace App\Core\Domain\Infrastructure\Repository;

use App\Core\Domain\Infrastructure\Interfaces\UserRepositoryInterface;
use App\Core\Domain\Models\Email;
use App\Core\Domain\Models\User\User;
use App\Core\Domain\Models\User\UserId;
use Illuminate\Support\Facades\DB;
use Exception;

class SqlUserRepository implements UserRepositoryInterface
{
public function persist(User $user): void
{
DB::table('users')->upsert([
'id' => $user->getId()->toString(),
'name' => $user->getName(),
'email' => $user->getEmail()->toString(),
'image_url' => $user->getImageUrl(),
'password' => $user->getHashPassword(),
], 'id');
}

/**
* @throws Exception
*/
public function find(string $id): ?User
{
$row = DB::table('users')->where('id', $id)->first();
if ($row === null) {
return null;
}

return $this->constructFromRows([$row])[0];
}

/**
* @throws Exception
*/
public function getAll(): ?array
{
$rows = DB::table('users')->get();
if ($rows === null) {

Check failure on line 44 in app/Core/Domain/Infrastructure/Repository/SqlUserRepository.php

View workflow job for this annotation

GitHub Actions / composer-analyze

Strict comparison using === between Illuminate\Support\Collection and null will always evaluate to false.
return null;
}

return $this->constructFromRows($rows->all());
}

/**
* @throws Exception
*/
public function getUserByEmail(string $email): ?User
{
$row = DB::table('users')->where('email', $email)->first();
if ($row === null) {
return null;
}

return $this->constructFromRows([$row])[0];
}

/**
* @throws Exception
*/
public function updateUser(User $user): void
{
DB::table('users')->where('id', $user->getId()->toString())->update([
'name' => $user->getName(),
'email' => $user->getEmail(),
'image_url' => $user->getImageUrl(),
'password' => $user->getHashPassword(),
]);
}

/**
* @throws Exception
*/
public function constructFromRows(array $rows): ?array
{
$users = [];
foreach ($rows as $row) {
$users[] = new User(
new UserId($row->id),
$row->name,
new Email($row->email),
$row->image_url,
$row->password
);
}

return $users;
}
}
7 changes: 7 additions & 0 deletions app/Core/Domain/Infrastructure/dependencies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

use App\Core\Domain\Infrastructure\Interfaces\UserRepositoryInterface;
use App\Core\Domain\Infrastructure\Repository\SqlUserRepository;

/** @var Application $app */
$app->singleton(UserRepositoryInterface::class, SqlUserRepository::class);

Check failure on line 7 in app/Core/Domain/Infrastructure/dependencies.php

View workflow job for this annotation

GitHub Actions / composer-analyze

Call to method singleton() on an unknown class Application.

Check failure on line 7 in app/Core/Domain/Infrastructure/dependencies.php

View workflow job for this annotation

GitHub Actions / composer-analyze

PHPDoc tag @var for variable $app contains unknown class Application.
19 changes: 2 additions & 17 deletions app/Models/User.php → app/Core/Domain/Models/Auth/User.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Models;
namespace App\Core\Domain\Models\Auth;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
Expand All @@ -20,26 +20,11 @@ class User extends Authenticatable
protected $fillable = [
'name',
'email',
'image_url',
'password',
];

/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];

/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
Loading

0 comments on commit e44397d

Please sign in to comment.