Skip to content

Commit

Permalink
Update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
JakubKermes committed Apr 26, 2024
1 parent b47c367 commit a355485
Show file tree
Hide file tree
Showing 11 changed files with 1,000 additions and 635 deletions.
95 changes: 58 additions & 37 deletions app/Http/Controllers/Api/Admin/ProviderController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,58 +5,43 @@
namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\ProviderRequest;
use App\Http\Requests\ApiProviderRequest;
use App\Http\Resources\ProviderResource;
use App\Models\Provider;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Response;

class ProviderController extends Controller
{
public const ITEMS_PER_PAGE = 15;

public function index(): JsonResponse
{
$providers = Provider::query()
->search("name")
->orderByName()
->orderByTimeRange()
->paginate(self::ITEMS_PER_PAGE)
->withQueryString();

$providers = Provider::all();
return response()->json([
"providers" => ProviderResource::collection($providers),
]);
}

public function store(ProviderRequest $request): JsonResponse
public function store(ApiProviderRequest $request): JsonResponse
{
Provider::query()->create($request->validated());
$provider = Provider::create($request->validated());

$fileName = $this->getFilename($request->name, $request->file("file"));
$fileContents = $request->file("file")->get();

Storage::disk("public")->put("providers/" . $fileName, $fileContents);
if ($request->has("file")) {
if (!$this->processProviderImage($request->file, $provider->name)) {
return response()->json(["message" => __("The image must be 150x100 pixels.")], Response::HTTP_UNPROCESSABLE_ENTITY);
}
}

return response()->json(["message" => __("Provider created successfully.")], 201);
return response()->json(["message" => __("Provider created successfully.")], Response::HTTP_CREATED);
}

public function update(ProviderRequest $request, Provider $provider): JsonResponse
public function update(ApiProviderRequest $request, Provider $provider): JsonResponse
{
$provider->update($request->validated());

$imageName = $this->getFilename($request->name, $request->file("file"));
$storageImagePath = storage_path("app/public/providers/" . $imageName);
$resourceImagePath = resource_path("providers/" . $imageName);
$imageContents = $request->file("file")->get();

if (file_exists($resourceImagePath)) {
file_put_contents($resourceImagePath, $imageContents);
Storage::put($storageImagePath, file_get_contents($imageContents));
} else {
Storage::put($storageImagePath, file_get_contents($imageContents));
if ($request->has("file")) {
$this->replaceProviderImage($request->file, $provider->name);
}

return response()->json(["message" => __("Provider updated successfully.")]);
Expand All @@ -65,19 +50,15 @@ public function update(ProviderRequest $request, Provider $provider): JsonRespon
public function destroy(Provider $provider): JsonResponse
{
$provider->delete();
$imagePath = storage_path("app/public/providers/" . strtolower($provider["name"]) . ".png");
$imagePath = $this->providerImagePath($provider->name);
File::delete($imagePath);

return response()->json(["message" => __("Provider deleted successfully.")]);
}

public function showLogo(string $filename): JsonResponse
{
$imagePath = storage_path("app/public/providers/" . $filename);

if (!file_exists($imagePath)) {
$imagePath = storage_path("app/public/providers/unknown.png");
}
$imagePath = $this->providerImagePath($filename, true);

$imageData = base64_encode(file_get_contents($imagePath));

Expand All @@ -87,8 +68,48 @@ public function showLogo(string $filename): JsonResponse
]);
}

private function getFilename(string $name, UploadedFile $file): string
private function providerImagePath(string $name, bool $useDefault = false): string
{
$path = storage_path("app/public/providers/" . strtolower($name) . ".png");

return file_exists($path) || !$useDefault ? $path : storage_path("app/public/providers/unknown.png");
}

private function processProviderImage(string $encodedFile, string $name): bool
{
[$decodedFile, $mimeType] = $this->decodeFile($encodedFile);

if (!$this->validateImageDimensions($decodedFile)) {
return false;
}

Storage::disk("public")->put("providers/" . strtolower($name) . "." . $mimeType, $decodedFile);

return true;
}

private function replaceProviderImage(string $encodedFile, string $name): void
{
return strtolower($name) . "." . $file->getClientOriginalExtension();
$oldImagePath = $this->providerImagePath($name);
Storage::disk("public")->delete($oldImagePath);
$this->processProviderImage($encodedFile, $name);
}

private function decodeFile(string $encodedFile): array
{
preg_match('/^data:image\/(\w+);base64,/', $encodedFile, $matches);
$decodedFile = base64_decode(explode(",", $encodedFile)[1] ?? "", true);

return [$decodedFile, $matches[1] ?? "png"];
}

private function validateImageDimensions(string $decodedFile): bool
{
$imageResource = imagecreatefromstring($decodedFile);
$width = imagesx($imageResource);
$height = imagesy($imageResource);
imagedestroy($imageResource);

return $width === 150 && $height === 100;
}
}
35 changes: 35 additions & 0 deletions app/Http/Requests/ApiProviderRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Unique;

class ApiProviderRequest extends FormRequest
{
public function rules(): array
{
return [
"name" => ["required", "string", "regex:/^[A-Z\s]/", "max:100", $this->uniqueRuleForProvider("name")],
"color" => ["required", "string", "size:7"],
"url" => ["nullable", "url"],
"android_url" => ["nullable", "url"],
"ios_url" => ["nullable", "url"],
"file" => [
"required",
"string",
"regex:/^data:image\/(png);base64,[a-zA-Z0-9+\/]+=*$/",
],
];
}

protected function uniqueRuleForProvider(string $column): Unique
{
$currentProviderId = $this->route(param: "provider");

return Rule::unique(table: "providers", column: $column)->ignore($currentProviderId);
}
}
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@
"require": {
"php": "^8.2",
"ext-dom": "*",
"ext-gd": "*",
"ext-pdo": "*",
"dedoc/scramble": "^0.9.0",
"guzzlehttp/guzzle": "^7.7",
"inertiajs/inertia-laravel": "^0.6.9",
"intervention/image": "2.*",
"laravel/framework": "^10.13.0",
"laravel/sanctum": "^3.2.5",
"laravel/socialite": "^5.10",
Expand Down
Loading

0 comments on commit a355485

Please sign in to comment.