-
Notifications
You must be signed in to change notification settings - Fork 84
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
Unique pages #61
base: main
Are you sure you want to change the base?
Unique pages #61
Changes from 8 commits
c6b8314
c694b06
7c6cdc6
bbe7b26
15bbd58
4c43501
d3f4eb5
78faf3a
97e203c
ca7ded7
2dd65c1
edc5760
f9b9908
6914305
d6148e3
48aceeb
dde9313
cda31c1
2448c13
c0d6650
5c29894
c4a1e1f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,6 +52,27 @@ php artisan migrate | |
1. Go to **yourapp/admin/page** and see how it works. | ||
2. Define your own templates in app/PageTemplates.php using the Backpack\CRUD API. | ||
|
||
## Unique pages usage | ||
|
||
Unique pages are pages that exist only once. You can not create a second instance nor delete the current one. | ||
**Only editing** | ||
|
||
Each unique page is defined like a page template in app/UniquePages.php using the backpack\CRUD API. | ||
It will be available for editing in the backend at | ||
`< route_prefix >/unique/< page_function_slug >` | ||
|
||
For users to access the editing page for the page `about_us` you could add a menu item like so: | ||
(remember the url will use the slug of your function) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Colon at end. |
||
|
||
```html | ||
<li><a href="{{ url(config('backpack.base.route_prefix').'/unique/about-us') }}"><i class="fa fa-file-o"></i> <span>Pages</span></a></li> | ||
``` | ||
|
||
**Unique pages can easily use revisions** | ||
|
||
Be sure to subclass `Backpack\PageManager\app\Models\Page` and follow the docs on setting up revisions for your CRUD. | ||
After that just set the config value `unique_page_revisions` to `true`and you are ready to go. | ||
|
||
## Example front-end | ||
|
||
No front-end is provided (Backpack only takes care of the admin panel), but for most projects this front-end code will be all you need: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,20 +4,24 @@ | |
|
||
use App\PageTemplates; | ||
// VALIDATION: change the requests to match your own file names if you need form validation | ||
use Backpack\PageManager\app\TraitReflections; | ||
use Backpack\CRUD\app\Http\Controllers\CrudController; | ||
use Backpack\PageManager\app\Http\Requests\PageRequest as StoreRequest; | ||
use Backpack\PageManager\app\Http\Requests\PageRequest as UpdateRequest; | ||
|
||
class PageCrudController extends CrudController | ||
{ | ||
use PageTemplates; | ||
use TraitReflections; | ||
|
||
public function setup($template_name = false) | ||
{ | ||
parent::__construct(); | ||
|
||
$modelClass = config('backpack.pagemanager.page_model_class', 'Backpack\PageManager\app\Models\Page'); | ||
|
||
$this->checkForTemplatesAndUniquePagesNotDistinct(); | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| BASIC CRUD INFORMATION | ||
|
@@ -27,6 +31,8 @@ public function setup($template_name = false) | |
$this->crud->setRoute(config('backpack.base.route_prefix').'/page'); | ||
$this->crud->setEntityNameStrings(trans('backpack::pagemanager.page'), trans('backpack::pagemanager.pages')); | ||
|
||
$template_names = collect($this->getTemplates())->pluck('name'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suppose we're stuck with this It would read better as |
||
$this->crud->addClause('whereIn', 'template', $template_names); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NL after. |
||
/* | ||
|-------------------------------------------------------------------------- | ||
| COLUMNS | ||
|
@@ -179,23 +185,6 @@ public function useTemplate($template_name = false) | |
} | ||
} | ||
|
||
/** | ||
* Get all defined templates. | ||
*/ | ||
public function getTemplates($template_name = false) | ||
{ | ||
$templates_array = []; | ||
|
||
$templates_trait = new \ReflectionClass('App\PageTemplates'); | ||
$templates = $templates_trait->getMethods(\ReflectionMethod::IS_PRIVATE); | ||
|
||
if (! count($templates)) { | ||
abort(503, trans('backpack::pagemanager.template_not_found')); | ||
} | ||
|
||
return $templates; | ||
} | ||
|
||
/** | ||
* Get all defined template as an array. | ||
* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,190 @@ | ||
<?php | ||
|
||
namespace Backpack\PageManager\app\Http\Controllers\Admin; | ||
|
||
use App\UniquePages; | ||
use Backpack\PageManager\app\TraitReflections; | ||
use Backpack\CRUD\app\Http\Controllers\CrudController; | ||
use Backpack\CRUD\app\Http\Controllers\CrudFeatures\SaveActions; | ||
|
||
class UniquePageCrudController extends CrudController | ||
{ | ||
use SaveActions; | ||
use UniquePages; | ||
use TraitReflections; | ||
|
||
public function setup() | ||
{ | ||
parent::__construct(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is the constructor called from setup? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point... this was just a copy&paste from the original controller... |
||
|
||
$modelClass = config('backpack.pagemanager.unique_page_model_class', 'Backpack\PageManager\app\Models\Page'); | ||
|
||
$this->checkForTemplatesAndUniquePagesNotDistinct(); | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| BASIC CRUD INFORMATION | ||
|-------------------------------------------------------------------------- | ||
*/ | ||
$this->crud->setModel($modelClass); | ||
// don't set route or entity names here. these depend on the page you are editing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't set route or entity names here. These depend on the page you are editing. |
||
|
||
// unique pages can not be created nor deleted | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cannot is one word 😺 |
||
$this->crud->denyAccess('create'); | ||
$this->crud->denyAccess('delete'); | ||
|
||
if (config('backpack.pagemanager.unique_page_revisions')) { | ||
$this->crud->allowAccess('revisions'); | ||
} | ||
} | ||
|
||
/** | ||
* As we want to edit pages by slug we need a new edit function. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's not a good description - that's a comment. |
||
* | ||
* @param string $slug the page slug | ||
* @return Response | ||
*/ | ||
public function uniqueEdit($slug) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
$model = $this->crud->model; | ||
$entry = $model::findBySlug($slug); | ||
|
||
if (! $entry) { | ||
$entry = $this->createMissingPage($slug); | ||
} | ||
|
||
$this->uniqueSetup($entry); | ||
|
||
return parent::edit($entry->id); | ||
} | ||
|
||
public function update($slug, $id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might as well have PHP doc. |
||
{ | ||
$this->setRoute($slug); | ||
|
||
return parent::updateCrud(); | ||
} | ||
|
||
public function setRoute($slug) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And PHP Doc. |
||
{ | ||
$this->crud->setRoute(config('backpack.base.route_prefix').'/unique/'.$slug); | ||
} | ||
|
||
/** | ||
* Populate the update form with basic fields, that all pages need. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove the comma. |
||
* | ||
* @param Model $page the page entity | ||
*/ | ||
public function addDefaultPageFields($page) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
{ | ||
$this->crud->addField([ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Rather than a series of
|
||
'name' => 'template', | ||
'type' => 'hidden', | ||
]); | ||
$this->crud->addField([ | ||
'name' => 'name', | ||
'type' => 'hidden', | ||
]); | ||
$this->crud->addField([ | ||
'name' => 'title', | ||
'type' => 'hidden', | ||
]); | ||
$this->crud->addField([ | ||
'name' => 'slug', | ||
'type' => 'hidden', | ||
]); | ||
|
||
$this->crud->addField([ | ||
'name' => 'open', | ||
'type' => 'custom_html', | ||
'value' => $this->buttons($page), | ||
]); | ||
} | ||
|
||
public function buttons($page) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc. |
||
{ | ||
$openButton = $page->getOpenButton(); | ||
$revisionsButton = view('crud::buttons.revisions', ['crud' => $this->crud, 'entry' => $page]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Err, if there is no revision setting thingo? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As the revisions button checks itself for |
||
|
||
return $openButton.' '.$revisionsButton; | ||
} | ||
|
||
public function createMissingPage($slug) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc. |
||
{ | ||
$pages = collect($this->getUniquePages()); | ||
|
||
$slugs = $pages->mapWithKeys(function ($page) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return [str_slug($page->name) => $page->name]; | ||
}); | ||
|
||
if (! $page = $slugs->pull($slug)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Errk, the old assign and check trick. It works but :(. |
||
abort(404); | ||
} | ||
|
||
$model = $this->crud->model; | ||
|
||
return $model::create([ | ||
'template' => $page, | ||
'name' => camel_case($page), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And let's hard code the way to make names and titles ... the rest of the package probably does but what if I really want my names to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
'title' => camel_case($page), | ||
'slug' => $slug, | ||
]); | ||
} | ||
|
||
public function uniqueRevisions($slug, $id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc! |
||
{ | ||
$model = $this->crud->model; | ||
$entry = $model::findBySlugOrFail($slug); | ||
|
||
$this->uniqueSetup($entry); | ||
|
||
return parent::listRevisions($entry->id); | ||
} | ||
|
||
public function restoreUniqueRevision($slug, $id) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc. |
||
{ | ||
$model = $this->crud->model; | ||
$entry = $model::findBySlugOrFail($slug); | ||
|
||
$this->uniqueSetup($entry); | ||
|
||
return parent::restoreRevision($id); | ||
} | ||
|
||
protected function uniqueSetup($entry) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc. |
||
{ | ||
$this->setRoute($entry->slug); | ||
|
||
$this->addDefaultPageFields($entry); | ||
$this->crud->setEntityNameStrings($this->crud->makeLabel($entry->template), ''); | ||
|
||
$this->{$entry->template}(); | ||
} | ||
|
||
/* | ||
|-------------------------------------------------------------------------- | ||
| SaveActions overrides | ||
|-------------------------------------------------------------------------- | ||
*/ | ||
|
||
/** | ||
* Overrides trait version to remove. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...and has no @return in the PHP doc. This might cause some grief if someone has overridden these themselves. |
||
*/ | ||
public function getSaveAction() | ||
{ | ||
$saveCurrent = [ | ||
'value' => $this->getSaveActionButtonName('save_and_back'), | ||
'label' => $this->getSaveActionButtonName('save_and_back'), | ||
]; | ||
|
||
return [ | ||
'active' => $saveCurrent, | ||
'options' => [], | ||
]; | ||
} | ||
|
||
public function setSaveAction($forceSaveAction = null) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc. BTW what does this do if it's not there? |
||
{ | ||
// do nothing to preserve session value for other crud | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -58,14 +58,4 @@ private function services() | |
'placeholder' => trans('backpack::pagemanager.content_placeholder'), | ||
]); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this meant to be part of the PR? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I just moved As these traits get published and need to be edited by developers, this serves as an example how to define your templates/uniquePages. |
||
|
||
private function about_us() | ||
{ | ||
$this->crud->addField([ | ||
'name' => 'content', | ||
'label' => trans('backpack::pagemanager.content'), | ||
'type' => 'wysiwyg', | ||
'placeholder' => trans('backpack::pagemanager.content_placeholder'), | ||
]); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
namespace Backpack\PageManager\app; | ||
|
||
trait TraitReflections | ||
{ | ||
public function checkForTemplatesAndUniquePagesNotDistinct() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. PHP Doc! |
||
{ | ||
if (config('backpack.pagemanager.page_model_class') != config('backpack.pagemanager.unique_page_model_class')) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return; | ||
} | ||
|
||
$uniquePages = collect($this->getUniquePages())->pluck('name'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sigh. It looks like all these getUniquePages and getTemplates things should just return collections... |
||
$templates = collect($this->getTemplates())->pluck('name'); | ||
|
||
if ($uniquePages->intersect($templates)->isNotEmpty()) { | ||
throw new \Exception('Templates and unique pages should not have the same function names when same model class is used.'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Huh? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And it sounds like MUST not SHOULD 😈 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See the new PHPDoc for reasons :) |
||
} | ||
} | ||
|
||
/** | ||
* Get all defined unique pages. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ...without a @return. |
||
*/ | ||
public function getUniquePages() | ||
{ | ||
$pages_trait = new \ReflectionClass('App\UniquePages'); | ||
$pages = $pages_trait->getMethods(\ReflectionMethod::IS_PRIVATE); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All the private methods? That's odd. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well that's exactly how the current page templates work at the moment... All private methods in the Trait are defining one single template (or here on unique page) |
||
|
||
return $pages; | ||
} | ||
|
||
/** | ||
* Get all defined templates. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No @return. |
||
*/ | ||
public function getTemplates($template_name = false) | ||
{ | ||
$templates_array = []; | ||
|
||
$templates_trait = new \ReflectionClass('App\PageTemplates'); | ||
$templates = $templates_trait->getMethods(\ReflectionMethod::IS_PRIVATE); | ||
|
||
if (! count($templates)) { | ||
abort(503, trans('backpack::pagemanager.template_not_found')); | ||
} | ||
|
||
return $templates; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace App; | ||
|
||
trait UniquePages | ||
{ | ||
/* | ||
|-------------------------------------------------------------------------- | ||
| Unique pages for Backpack\PageManager | ||
|-------------------------------------------------------------------------- | ||
| | ||
| Each unique page has its own method, that define what fields should show up using the Backpack\CRUD API. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No comma here! |
||
| Use snake_case for naming and PageManager will generate the page on first edit | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eh? What if it's not snake_case? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is also a convention I just copied from default page templates behaviour. |
||
| | ||
| Any fields defined here will show up after the standard page fields: | ||
| - select template (hidden and fix) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does "(hidden and fix)" mean? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Improved the comment |
||
| - page name (only seen by admins) (hidden and fix) | ||
| - page title | ||
| - page slug (hidden and fix, slug of method name) | ||
*/ | ||
|
||
private function about_us() | ||
{ | ||
$this->crud->addField([ | ||
'name' => 'content', | ||
'label' => trans('backpack::pagemanager.content'), | ||
'type' => 'wysiwyg', | ||
'placeholder' => trans('backpack::pagemanager.content_placeholder'), | ||
]); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NL at end.