Skip to content

Commit

Permalink
List all productables endpoint (#50)
Browse files Browse the repository at this point in the history
* List all productables endpoint

* src/routes.php

* Removed DB::raw
  • Loading branch information
pa-cholek authored Mar 11, 2022
1 parent a8e54e4 commit 1df7860
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Contracts/Productable.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ public function toJsonResourceForShop(): JsonResource;
*/
public function getName(): string;

/**
* Get productable name column
*/
public function getNameColumn(): ?string;

/**
* Get productable description
*/
Expand Down
10 changes: 9 additions & 1 deletion src/Contracts/ProductableTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,15 @@ public function toJsonResourceForShop(): JsonResource

public function getName(): string
{
return $this->name ?? $this->title ?? __('No name field');
if (empty($this->getNameColumn()) || empty($this->{$this->getNameColumn()})) {
return $this->name ?? $this->title ?? __('No name field');
}
return $this->{$this->getNameColumn()};
}

public function getNameColumn(): ?string
{
return 'name';
}

public function getDescription(): ?string
Expand Down
6 changes: 6 additions & 0 deletions src/Http/Controllers/Admin/ProductableAdminApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use EscolaLms\Cart\Http\Requests\Admin\ProductableAttachRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableDetachRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableListRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableProductRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableRegisteredListRequest;
use EscolaLms\Cart\Http\Resources\ProductResource;
Expand All @@ -24,6 +25,11 @@ public function __construct(ProductServiceContract $productService, ShopServiceC
$this->shopService = $shopService;
}

public function index(ProductableListRequest $request): JsonResponse
{
return $this->sendResponse($this->productService->listAllProductables()->toArray(), __('List of Productables'));
}

public function attach(ProductableAttachRequest $request): JsonResponse
{
$productable = $this->productService->findProductable($request->getProductableType(), $request->getProductableId());
Expand Down
19 changes: 19 additions & 0 deletions src/Http/Requests/Admin/ProductableListRequest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace EscolaLms\Cart\Http\Requests\Admin;

use EscolaLms\Cart\Enums\CartPermissionsEnum;
use Illuminate\Foundation\Http\FormRequest;

class ProductableListRequest extends FormRequest
{
public function authorize()
{
return $this->user()->can(CartPermissionsEnum::MANAGE_PRODUCTS);
}

public function rules(): array
{
return [];
}
}
42 changes: 42 additions & 0 deletions src/Http/Swagger/Admin/ProductableAdminSwagger.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,54 @@

use EscolaLms\Cart\Http\Requests\Admin\ProductableAttachRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableDetachRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableListRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableProductRequest;
use EscolaLms\Cart\Http\Requests\Admin\ProductableRegisteredListRequest;
use Illuminate\Http\JsonResponse;

interface ProductableAdminSwagger
{
/**
* @OA\Get(
* path="/api/admin/productables/",
* description="Get list of all productables",
* tags={"Admin Product"},
* security={
* {"passport": {}},
* },
* @OA\Response(
* response=200,
* description="successful operation",
* @OA\MediaType(
* mediaType="application/json",
* ),
* @OA\Schema(
* type="object",
* @OA\Property(
* property="data",
* type="array",
* ),
* @OA\Property(
* property="success",
* type="boolean"
* ),
* @OA\Property(
* property="message",
* type="string"
* )
* )
* ),
* @OA\Response(
* response=422,
* description="Bad request",
* @OA\MediaType(
* mediaType="application/json"
* )
* )
* )
*/
public function index(ProductableListRequest $request): JsonResponse;

/**
* @OA\Post(
* path="/api/admin/productables/attach",
Expand Down
2 changes: 2 additions & 0 deletions src/Services/Contracts/ProductServiceContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@
use EscolaLms\Core\Models\User;
use Illuminate\Contracts\Pagination\LengthAwarePaginator;
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Collection;

interface ProductServiceContract
{
public function registerProductableClass(string $productableClass): void;
public function isProductableClassRegistered(string $productableClass): bool;
public function listRegisteredProductableClasses(): array;
public function listAllProductables(): Collection;
public function canonicalProductableClass(string $productableClass): ?string;

public function findSingleProductForProductable(Productable $productable): ?Product;
Expand Down
19 changes: 19 additions & 0 deletions src/Services/ProductService.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class ProductService implements ProductServiceContract
Expand Down Expand Up @@ -57,6 +58,24 @@ public function listRegisteredProductableClasses(): array
return $this->productables;
}

public function listAllProductables(): Collection
{
$collection = Collection::empty();
foreach ($this->listRegisteredProductableClasses() as $productableClass) {
/** @var Model&Productable $model */
$model = new $productableClass();
$productables = $model::query()->getQuery()->select(
'id AS productable_id',
($model->getNameColumn() . ' AS name'),
)->get();
$collection = $collection->merge($productables->map(function ($row) use ($productableClass) {
$row->productable_type = $productableClass;
return $row;
}));
}
return $collection;
}

public function canonicalProductableClass(string $productableClass): ?string
{
if (in_array($productableClass, $this->productables)) {
Expand Down
1 change: 1 addition & 0 deletions src/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
Route::post('/products/{id}/attach', [ProductAdminApiController::class, 'attach'])->whereNumber('id');
Route::post('/products/{id}/detach', [ProductAdminApiController::class, 'detach'])->whereNumber('id');

Route::get('/productables', [ProductableAdminApiController::class, 'index']);
Route::get('/productables/registered', [ProductableAdminApiController::class, 'registered']);
Route::get('/productables/product', [ProductableAdminApiController::class, 'product']);
Route::post('/productables/attach', [ProductableAdminApiController::class, 'attach']);
Expand Down
14 changes: 14 additions & 0 deletions tests/API/AdminApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,20 @@ public function test_get_registered_productables_list()
]);
}

public function test_list_productables()
{
$productables = ExampleProductable::factory()->count(10)->create();

$this->response = $this->actingAs($this->user, 'api')->json('GET', '/api/admin/productables/');
$this->response->assertOk();
$this->response->assertJsonCount(10, 'data');
$this->response->assertJsonFragment([
'productable_id' => $productables->get(0)->id,
'productable_type' => ExampleProductable::class,
'name' => $productables->get(0)->getName(),
]);
}

public function test_find_single_product_for_productable()
{
/** @var Product $product */
Expand Down

0 comments on commit 1df7860

Please sign in to comment.