Forked from harrysbaraini/App\Http\Resources\EventResource.php
Created
June 3, 2021 01:50
-
-
Save mirlisboa/58e9a8e1a1a4be80f6beea9dd4ca5298 to your computer and use it in GitHub Desktop.
Laravel API Resources with permissions and links
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources; | |
use App\Http\Handlers\Admin\UploadMediaFile; | |
use App\Http\Resources\Support\ResourceLink; | |
use App\Policies\EventPolicy; | |
use Illuminate\Support\Facades\Auth; | |
class EventResource extends ItemResource | |
{ | |
/** | |
* Prepare the array of attributes. | |
* | |
* @return array | |
*/ | |
protected function properties(): array | |
{ | |
return [ | |
'slug' => $this->slug, | |
'title' => $this->title, | |
'status' => $this->status, | |
'statusLabel' => $this->status_label, | |
'summary' => $this->summary, | |
'content' => $this->content, | |
'date' => $this->date, | |
'closingDate' => $this->closing_date, | |
'sales' => Auth::guard()->user()->isAdmin() ? [ | |
'ticketsSold' => (int)$this->tickets_sold, | |
'totalSales' => (int)$this->total_sales, | |
'gatewayFee' => (int)$this->gateway_fee, | |
'organiserProfit' => (int)$this->organiser_profit, | |
'platformProfit' => (int)$this->platform_profit, | |
] : null, | |
'flags' => [ | |
'isPublished' => $this->isPublished(), | |
'isOpenToEntries' => $this->isOpenToEntries(), | |
'isViewableOnFrontPage' => $this->isViewableOnFrontPage(), | |
], | |
'metadata' => [ | |
'receiptNotes' => $this->metadata['receipt_notes'], | |
], | |
]; | |
} | |
/** | |
* @return array | |
*/ | |
protected function relationships(): array | |
{ | |
return [ | |
'logo' => new FileResource($this->getLogo()), | |
'banner' => new FileResource($this->getBanner()), | |
'sponsors' => new FileResourceCollection($this->getSponsors()), | |
'options' => new EventOptionResourceCollection($this->options), | |
'address' => new AddressResource($this->address), | |
'organisers' => new OrganiserResourceCollection($this->organisers), | |
]; | |
} | |
/** | |
* Prepare the array of links. | |
* | |
* @return ResourceLink | |
*/ | |
protected function links(): ResourceLink | |
{ | |
return ResourceLink::make() | |
->putIf($this->allows('view', $this->resource), 'self', route('backend.events.show', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'edit', route('backend.events.edit', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateBasicInformation', route('backend.events.update.basic-information', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateContent', route('backend.events.update.content', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateDates', route('backend.events.update.dates', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateImages', route('backend.events.update.images', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateAddress', route('backend.events.update.address', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updatePrices', route('backend.events.update.prices', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateSponsors', route('backend.events.update.sponsors', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'updateOthers', route('backend.events.update.others', $this->resource)) | |
->putIf($this->allows('preview', $this->resource), 'preview', route('backend.events.preview', $this->resource)) | |
->putIf($this->allows('export', $this->resource), 'exportSheet', route('backend.events.export.sheet', $this->resource)) | |
->putIf($this->allows('update', $this->resource), 'uploadMedia', handler(UploadMediaFile::class)) | |
->putIf($this->isViewableOnFrontPage(), 'frontpage', ['event.show', $this->resource->slug]); | |
} | |
/** | |
* Prepare the array of permissions. | |
* | |
* @return PolicyResource | |
*/ | |
protected function permissions(): PolicyResource | |
{ | |
return new PolicyResource(new EventPolicy, $this->resource); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources; | |
use App\Http\Resources\Support\ResourceLink; | |
use App\Models\Event; | |
use App\Policies\EventPolicy; | |
use Illuminate\Support\Facades\Gate; | |
class EventResourceCollection extends ItemResourceCollection | |
{ | |
/** | |
* Prepare the array of links. | |
* | |
* @return ResourceLink | |
*/ | |
protected function links(): ResourceLink | |
{ | |
return ResourceLink::make() | |
->putIf(Gate::allows('list', Event::class), 'self', route('backend.events.index')) | |
->putIf(Gate::allows('create', Event::class), 'create', route('backend.events.create')); | |
} | |
/** | |
* Prepare the array of permissions. | |
* | |
* @return PolicyResource | |
*/ | |
protected function permissions(): PolicyResource | |
{ | |
return new PolicyResource(new EventPolicy, Event::class); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources; | |
use App\Http\Resources\Support\ResourceLink; | |
use Illuminate\Http\Resources\Json\JsonResource; | |
use Illuminate\Support\Facades\Gate; | |
use Illuminate\Support\Str; | |
abstract class ItemResource extends JsonResource | |
{ | |
/** | |
* Transform the resource into an array. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @return array | |
* @throws \ReflectionException | |
*/ | |
public function toArray($request) | |
{ | |
return [ | |
'type' => $this->type(), | |
'id' => $this->id, | |
'attributes' => $this->properties(), | |
'links' => $this->links()->toArray(), | |
'permissions' => $this->permissions(), | |
'relationships' => $this->relationships(), | |
]; | |
} | |
/** | |
* Prepare the array of attributes. | |
* | |
* @return array | |
*/ | |
abstract protected function properties(): array; | |
/** | |
* Prepare the array of links. | |
* | |
* @return ResourceLink | |
*/ | |
abstract protected function links(): ResourceLink; | |
/** | |
* Prepare the array of permissions. | |
* | |
* @return PolicyResource | |
*/ | |
abstract protected function permissions(): PolicyResource; | |
/** | |
* Prepare the array of relationships. | |
* | |
* @return array | |
*/ | |
protected function relationships(): array | |
{ | |
return []; | |
} | |
/** | |
* Guess the type of the resource. | |
* | |
* @return string | |
* @throws \ReflectionException | |
*/ | |
protected function type(): string | |
{ | |
$name = Str::replaceLast('Resource', '', (new \ReflectionClass($this))->getShortName()); | |
return Str::snake(Str::plural($name)); | |
} | |
protected function allows(...$parameters): bool | |
{ | |
return Gate::allows(...$parameters); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources; | |
use App\Http\Resources\Support\ResourceLink; | |
use Illuminate\Http\Resources\Json\ResourceCollection; | |
use Illuminate\Support\Facades\Gate; | |
abstract class ItemResourceCollection extends ResourceCollection | |
{ | |
/** | |
* Transform the resource collection into an array. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @return array | |
*/ | |
public function toArray($request) | |
{ | |
return [ | |
'data' => $this->collection, | |
]; | |
} | |
public function with($request) | |
{ | |
return [ | |
'links' => $this->links()->toArray(), | |
'permissions' => $this->permissions(), | |
]; | |
} | |
/** | |
* Prepare the array of links. | |
* | |
* @return ResourceLink | |
*/ | |
abstract protected function links(): ResourceLink; | |
/** | |
* Prepare the array of permissions. | |
* | |
* @return PolicyResource | |
*/ | |
abstract protected function permissions(): PolicyResource; | |
protected function allows(...$parameters): bool | |
{ | |
return Gate::allows(...$parameters); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources; | |
use Illuminate\Database\Eloquent\Model; | |
use Illuminate\Http\Resources\Json\JsonResource; | |
use Illuminate\Support\Arr; | |
use Illuminate\Support\Collection; | |
class PolicyResource extends JsonResource | |
{ | |
protected $model; | |
protected $ignoreMethods = []; | |
protected $permissions = []; | |
/** | |
* Create a new resource instance. | |
* | |
* @param mixed $resource | |
* @param $model | |
*/ | |
public function __construct($resource = null, $model = null) | |
{ | |
$this->resource = $resource; | |
$this->model = $model; | |
} | |
/** | |
* Transform the resource into an array. | |
* | |
* @param \Illuminate\Http\Request $request | |
* @return array | |
* @throws \ReflectionException | |
*/ | |
public function toArray($request) | |
{ | |
if (is_null($this->resource)) { | |
return []; | |
} | |
$methods = (new \ReflectionClass($this->resource))->getMethods(\ReflectionMethod::IS_PUBLIC); | |
$policyPermissions = Collection::make($methods) | |
->except($this->ignoreMethods) | |
->filter(function (\ReflectionMethod $method) { | |
if ($this->model instanceof Model) { | |
return $method->getNumberOfParameters() > 1; | |
} | |
return $method->getNumberOfParameters() === 1; | |
}) | |
->mapWithKeys(function (\ReflectionMethod $method) use ($request) { | |
return [ | |
$method->name => $request->user('backend')->can($method->name, $this->model), | |
]; | |
}); | |
return $policyPermissions->merge($this->permissions)->toArray(); | |
} | |
public function push(string $key, bool $value) | |
{ | |
Arr::set($this->permissions, $key, $value); | |
return $this; | |
} | |
public function ignoreMethods(array $methods) | |
{ | |
$this->ignoreMethods = $methods; | |
return $this; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Resources\Support; | |
use Illuminate\Contracts\Support\Arrayable; | |
use Illuminate\Support\Arr; | |
class ResourceLink implements Arrayable | |
{ | |
/** @var array */ | |
protected $links; | |
public function __construct(array $links = []) | |
{ | |
$this->links = $links; | |
} | |
public static function make(...$parameters) | |
{ | |
return new self($parameters); | |
} | |
public function put(string $name, $route): self | |
{ | |
if (is_array($route)) { | |
$route = route($route[0], $route[1]); | |
} | |
Arr::set($this->links, $name, $route); | |
return $this; | |
} | |
public function remove(string $name): self | |
{ | |
Arr::pull($this->links, $name); | |
return $this; | |
} | |
public function putIf(bool $condition, string $name, $route): self | |
{ | |
if (true === $condition) { | |
$this->put($name, $route); | |
} | |
return $this; | |
} | |
public function removeIf(bool $condition, string $name): self | |
{ | |
if (true === $condition) { | |
$this->remove($name); | |
} | |
return $this; | |
} | |
/** | |
* Transform the resource into an array. | |
* | |
* @return array | |
*/ | |
public function toArray() | |
{ | |
return $this->links; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment