Skip to content

Commit

Permalink
Add config to (re-)enable front end route binding
Browse files Browse the repository at this point in the history
  • Loading branch information
ryanmitchell committed Oct 16, 2023
1 parent bbf6c19 commit bf7b318
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 32 deletions.
12 changes: 12 additions & 0 deletions config/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,18 @@

'enabled' => true,

/*
|--------------------------------------------------------------------------
| Enable Route Binding
|--------------------------------------------------------------------------
|
| Do you want to enable route binding on Statamic Repositories
| (entry, taxonomy, collection etc) on front end routes?
|
*/

'binding_enabled' => true,

/*
|--------------------------------------------------------------------------
| Action Route Prefix
Expand Down
118 changes: 86 additions & 32 deletions src/Providers/RouteServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,17 @@ public function boot()
protected function bindCollections()
{
Route::bind('collection', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['collection'] ?? 'handle';
$collection = $field == 'handle' ? Collection::findByHandle($handle) : Collection::all()->firstWhere($field, $handle);

throw_unless(
$collection = Collection::findByHandle($handle),
$collection,
new NotFoundHttpException("Collection [$handle] not found.")
);

Expand All @@ -62,12 +67,17 @@ protected function bindCollections()
protected function bindEntries()
{
Route::bind('entry', function ($handle, $route = null) {
if ($this->isApiRoute($route) || ! $this->isCpRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if ($this->isApiRoute($route) || ! $this->isCpRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['entry'] ?? 'id';
$entry = $field == 'id' ? Entry::find($handle) : Entry::query()->where($field, $handle)->first();

throw_if(
! ($entry = Entry::find($handle)) || $entry->collection()->id() !== $route->parameter('collection')->id(),
! ($entry) || ($route->parameter('collection') && ($entry->collection()->id() !== $route->parameter('collection')->id())),
new NotFoundHttpException("Entry [$handle] not found.")
);

Expand All @@ -78,12 +88,17 @@ protected function bindEntries()
protected function bindTaxonomies()
{
Route::bind('taxonomy', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['taxonomy'] ?? 'handle';
$taxonomy = $field == 'handle' ? Taxonomy::findByHandle($handle) : Taxonomy::all()->firstWhere($field, $handle);

throw_unless(
$taxonomy = Taxonomy::findByHandle($handle),
$taxonomy,
new NotFoundHttpException("Taxonomy [$handle] not found.")
);

Expand All @@ -94,15 +109,21 @@ protected function bindTaxonomies()
protected function bindTerms()
{
Route::bind('term', function ($handle, $route = null) {
if ($this->isApiRoute($route) || ! $this->isCpRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if ($this->isApiRoute($route) || ! $this->isCpRoute($route)) {
return $handle;
}
}

$id = $route->parameter('taxonomy')->handle().'::'.$handle;
$field = $route->bindingFields()['term'] ?? 'id';

$handle = ($field == 'id' && $route->parameter('taxonomy') ? $route->parameter('taxonomy')->handle().'::' : '').$handle;
$site = $route->parameter('site') ?? Site::default()->handle();

$term = $field == 'id' ? Term::find($handle)->in($site) : Term::query()->where($field, $handle)->where('site', $site)->when($route->parameter('taxonomy'), fn ($query) => $query->where('taxonomy', $route->parameter('taxonomy')->handle()))->first();

throw_unless(
($term = Term::find($id)->in($site)) && $term->taxonomy()->id() === $route->parameter('taxonomy')->id(),
$term && ($route->parameter('taxonomy') && $term->taxonomy()->id() === $route->parameter('taxonomy')->id()),
new NotFoundHttpException("Taxonomy term [$handle] not found.")
);

Expand All @@ -113,12 +134,17 @@ protected function bindTerms()
protected function bindAssetContainers()
{
Route::bind('asset_container', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['asset_container'] ?? 'handle';
$container = $field == 'handle' ? AssetContainer::findByHandle($handle) : AssetContainer::all()->firstWhere($field, $handle);

throw_unless(
$container = AssetContainer::findByHandle($handle),
$container,
new NotFoundHttpException("Asset container [$handle] not found.")
);

Expand All @@ -129,14 +155,20 @@ protected function bindAssetContainers()
protected function bindAssets()
{
Route::bind('asset', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$id = $route->parameter('asset_container')->handle().'::'.$handle;
$field = $route->bindingFields()['asset'] ?? 'id';

$handle = ($field == 'id' && $route->parameter('asset_container') ? $route->parameter('asset_container')->handle().'::' : '').$handle;

$asset = $field == 'id' ? Asset::find($handle) : Asset::query()->where($field, $handle)->when($route->parameter('asset_container'), fn ($query) => $query->where('container', $route->parameter('container')->handle()))->first();

throw_unless(
$asset = Asset::find($id),
$asset,
new NotFoundHttpException("Asset [$handle] not found.")
);

Expand All @@ -147,14 +179,19 @@ protected function bindAssets()
protected function bindGlobalSets()
{
Route::bind('global', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['global'] ?? 'handle';
$global = $field == 'handle' ? GlobalSet::findByHandle($handle) : GlobalSet::all()->firstWhere($field, $handle);

$site = Site::default()->handle();

throw_unless(
$globalSet = GlobalSet::findByHandle($handle)->in($site),
$globalSet = $global->in($site),
new NotFoundHttpException("Global set [$handle] not found.")
);

Expand All @@ -165,12 +202,17 @@ protected function bindGlobalSets()
protected function bindSites()
{
Route::bind('site', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $handle;
}
}

$field = $route->bindingFields()['site'] ?? 'handle';
$site = $field == 'handle' ? Site::get($handle) : Site::all()->firstWhere($field, $handle);

throw_unless(
$site = Site::get($handle),
$site,
new NotFoundHttpException("Site [$handle] not found.")
);

Expand All @@ -181,8 +223,10 @@ protected function bindSites()
protected function bindRevisions()
{
Route::bind('revision', function ($reference, $route = null) {
if (! $this->isCpOrApiRoute($route)) {
return $reference;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)) {
return $reference;
}
}

if ($route->hasParameter('entry')) {
Expand All @@ -205,20 +249,30 @@ protected function bindRevisions()
protected function bindForms()
{
Route::bind('form', function ($handle, $route = null) {
if (! $this->isCpOrApiRoute($route)
&& ! Str::startsWith($route->uri(), config('statamic.routes.action').'/forms/')) {
return $handle;
if (! $this->isFrontendBindingEnabled()) {
if (! $this->isCpOrApiRoute($route)
&& ! Str::startsWith($route->uri(), config('statamic.routes.action').'/forms/')) {
return $handle;
}
}

$field = $route->bindingFields()['form'] ?? 'handle';
$form = $field == 'handle' ? Form::find($handle) : Form::all()->firstWhere($field, $handle);

throw_unless(
$form = Form::find($handle),
$form,
new NotFoundHttpException("Form [$handle] not found.")
);

return $form;
});
}

private function isFrontendBindingEnabled()
{
return config('statamic.routes.binding_enabled', false);
}

private function isApiRoute(\Illuminate\Routing\Route $route = null)
{
if (is_null($route)) {
Expand Down

0 comments on commit bf7b318

Please sign in to comment.