Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: create onion architectue with successfully testing register #8

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading