.. | ||
assets | ||
.gitignore | ||
add-page-by-form.php | ||
add-page-by-form.yaml | ||
blueprints.yaml | ||
CHANGELOG.md | ||
LICENSE | ||
README.md |
Add Page By Form Plugin
The Add Page By Form Plugin is for Grav CMS. It allows users to add a new page by filling in a form.
This plugin uses the possibilities of custom frontmatter. By setting your own variables in the form page frontmatter a priori and optionally letting users override these variable values by filling in corresponding form fields you can transport these data into the new page frontmatter.
The passing on of both the default settings and form field values entered by the end user to the new page frontmatter makes for an extremely configurable solution.
By mixing default settings and configuring the page form you can to a large extent control the appearence and behaviour of the newly added page by using the frontmatter variables present in the new page in a Twig template.
For example, a new page can act as a new blog post simply by setting the appropriate template variable in the form page definition (with the AntiMatter theme, this is template: item
). That template value is inserted in the new page frontmatter and, so, will be used by Grav to display the new page.
Security Warning
Allowing anonymous visitors to create pages is a potential website security risk. It is strongly advised to use the Grav Login Plugin or the Private Grav Plugin to restrict the page creation to logged in users only.
This plugin itself does not provide any security measures. Please take this in consideration before using this plugin.
Installation and Configuration
Typically the plugin should be installed via GPM (Grav Package Manager):
$ bin/gpm install add-page-by-form
Alternatively it can be installed via the Admin Plugin.
Another option is to manualy install the plugin by downloading the plugin as a zip file. Copy the zip file to your /user/plugins
directory, unzip it there and rename the folder to add-page-by-form
.
Configuration Defaults
Here is the default configuration in the configuration file add-page-by-form.yaml
plus an explanation of the settings:
enabled: true
date_display_format: 'd-m-Y g:ia'
default_title: 'My New Page'
default_content: 'No content.'
overwrite_mode: false
include_username: false
auto_taxonomy_types: false
use_editor_class: true
physical_template_name: true
-
enabled
determines whether the plugin is active or not; -
date_display_format
sets a default date and time format; -
default_title
will be used as a fallback for the new page title when no other value is set; -
default_content
will be used as the page content for the new page when no other value is set; -
include_username
sets whether or not the username of the currently logged in frontend user is included in the new page frontmatter; -
overwrite_mode
determines how to act when a page with the same name or slug already exists; -
auto_taxonomy_types
saves any new taxonomy types that were input by the user to the site configuration filesite.yaml
; -
use_editor_class
determines whether or not to change a textarea field into a Markdown editor when the texture field includes the class "editor" (classes: editor
); -
physical_template_name
should normally not be used. For more information see the description in the section 'pageconfig' block variables.
Customizing the default configuration
To keep your custom configuration when updating the plugin you need to use a configuration file which is stored in the user/config/plugins
folder.
Simply edit the plugin options in the Admin panel and the changes will be saved to the configuration file in that location. If you don't use the Admin panel, copy the add-page-by-form.yaml
default file to your user/config/plugins
folder and use that copy to change configuration settings.
Usage
Using this plugin requires:
- a normal page containing a Grav Form with a unique name that starts with "add_page";
- optionally, but required for usefulness, one or two blocks of extra page frontmatter variables in that page being:
- a 'pageconfig' block with variables that are used in the new page creation process;
- a 'pagefrontmatter' block with variables that are passed on to the new page frontmatter and can be processed by Twig along the way.
Modifying frontmatter variables
Every frontmatter variable value can be changed by the user when an input field with the same name as the variable is included in the form.
The basic method of modifying is overriding or replacing an initial value. An extreme case of overriding a variable which is quite uncommon but illustrates the process well:
overwrite_mode
is set inadd-page-by-form.yaml
- and can be changed in the Plugin configuration in the Admin Panel
- can be set in the
pageconfig
block - and finally may be changed again by the end user when the form contains an
overwrite_mode
field.
Page Headers / Frontmatter
This plugin makes extensive use of Custom Page Headers. Unfortunately the Grav documentation mixes the terms "frontmatter", "page headers" and simply "headers". This may be confusing at first. They all refer to the optional top part of a Grav page which contains data in YAML syntax.
Form page Frontmatter
The frontmatter in the form page and the way it is handled by the plugin is where the flexibility of this plugin originates.
The form page frontmatter is divided into three sections or blocks:
- So called 'root level' variables are intended to act upon the form page itself. They are not passed on to the new page;
- the
pageconfig
block contains variables that are used by the plugin in the new page creation process and do get passed on to the new page frontmatter; - the
pagefrontmatter
block holds all other variables that must be passed on to the new page frontmatter.
Root level variables
In the examples above the root level configuration options are:
title
sets the title of the page containing the form;template: form
activates the form on this page (not required when the form page is namedform.md
);form
defines the form.
From version 2, the use of parent
in the, what is now called, root level block is deprecated. It is however still supported for backwards compatibility.
'pageconfig' block variables
In the optional pageconfig block you can set these, and only these, variables (other variables will be ignored):
parent
sets the parent page for the new page. This variable may be an absolute route (for exampleparent: /user_contributions
) or a relative route (e.g.parent: articles
. In case of an absolute route this route starts from the pages root. A relative route is regarded to start from the form page, so the new page will be a child page of the form page. The form page is also used as the parent page when the set parent page does not exist;subroute
defines a route from the (initial) parent value. If one or more folders in the route do not exist they will be created;slug_field
tells the plugin what field to use as the new page's slug or folder name. Whenslug_field
is missing the plugin tries to use the value oftitle
;overwrite_mode: true|false|edit
(defaultfalse
) tells the plugin what to do when a page with the same name already exists. Withoverwrite_mode: true
the existing page is overwritten. Any additional (media) files besides the page itself which are stored in the existing page folder are deleted as well. Withoverwite_mode: false
the new page slug gets a sequential number attached at the end (for example "my-new-page-1" in case "my-new-page" exists).
Usingoverwite_mode: edit
allows for the page being saved to it's existing folder respecting any already present uploaded files;include_username: true|false
(defaultfalse
) determines whether or not to include the username of a logged in frontend user in the new page frontmatter;physical_template_name: true|false
(defaulttrue
) does or does not cause the plugin to use the template name of the new page as that new page's filesystem filename. Defaults to "default" when no template is set in the 'pagefrontmatter' block. When set totrue
to avoid future confusion the frontmatter variabletemplate
is removed from the new page frontmatter.
A note on parent and subroute
Together the variables parent
and subroute
define the new page's destination. Or, in other words, together they set the path or route of the new page filesystem folder in the page structure.
The difference between parent and subroute worded in another way:
- Parent: works on a page level; when there is no page at the parent route, the form page is used as the parent;
- Subroute: works on a folder level; a subroute may consist of empty folders and if a folder in the subroute does not exist it gets created.
'pagefrontmatter' block variables
The content of the optional pagefrontmatter
block will be included in the new page frontmatter.
Form usage
The form page needs to use a simple single form.
Two examples are included at the end of this ReadMe file.
Mandatory fields and values
Form Name
It is always a good thing to give each form a unique name, especially when multiple forms are used.
To pre fill form fields with default values the Form name must include the string "add_page". Valid names are for example add_page.blogpost
, add_page_profile
.
###Form Actions
Custom Form processing ( Important ! )
To let the plugin process the form after a Submit a custom process action must be set like so:
process:
-
add_page: true
Redirect to the new page
To show the new page to the user set the redirect
action to the custom value @self
or @self-admin
.
When using redirect: '@self'
the page will be shown as a regular web page, for example:
process:
-
add_page: true
-
redirect: '@self'
To open the new page in the Admin panel use redirect: '@self-admin'
.
Note that this plugin does not handle the admin user authentication. If the Admin plugin is not installed or is inactive redirection occurs as if @self
was used.
Tip: using
@self-admin
is a very convenient way to learn how to use this plugin as it is easy to view and examine the source of the resulting new page including it's frontmatter in the Admin panel.
Using a Markdown editor in textarea fields
When a textarea
field is given the class editor
it will use the SimpleMDE Markdown Editor.
Value overrides
The variables which are defined and given a value in the pageconfig
and pagefrontmatter
blocks may be 'overridden' or in other words replaced by form input fields. In that respect these variables can be seen to hold a set of default values.
There is only one exception to the default variable override behaviour and that is the handling of taxonomy
types. Extra taxonomy types and values (for example tags) which are entered via form fields are added to the new page taxonomy.
To override a default value by user input is simply a matter of including a form field by the same name in the page form.
For example in the example 2 - create a new blog post, the default title is set to "My new Blog post". The form contains a form field of type text with name: title
. Thus the user is prompted to enter a title for the new page in the form but does not need to do so because filling in the title field is not mandatory. If the user enters a title that value is used as the title for the new page. If he or she does not, the default title "My new Blog post" will be used.
Setting taxonomy categories and tags
The Add Blog Post example shows how to let the user add extra tags via the form. Extra categories may be added in the same way.
Handling extra taxonomy types
By default Grav 'knows' two taxonomy types, category
and tag
. Extra taxonomy types may be defined and added just like with any other variables you can include a form field. The new type is then added to the list of taxonomy types instead of replacing the existing types.
This can be done in the pagefrontmatter
block. For example, to define a new taxonomy type named 'department':
pagefrontmatter:
taxonomy:
- department
And/or in the form:
form:
name: my_form
fields:
-
name: taxonomy
label: Taxonomy type
type: text
This is a feature which calls for a solid look-before-you-leap approach because of it's side effects. Using a new taxonomy type requires it to be included in the list of known taxonomy types. This list is in the site configuration file site.yaml
.
By setting the plugin configuration option auto_taxonomy_types: true
new types get automatically saved and can then be used in a collection.
The side effect and possibly downside is that every modification of the site configuration file causes Grav to rebuild the cache, so this may not be desirable with larger sites.
Use with caution!
Examples
The least error prone way to test and play with the examples is to set up a fresh Grav site and using it's default theme Antimatter.
Form page example 1: create a normal page
The goal of this example is to show how to let a user create a new page where uploaded images and files are saved along the page (in the same folder). After the user clicked Submit he or she will be shown the new page.
Suppose this minimal Grav website structure in user/pages/
:
03.submit-assignment/
default.md
04.assignments/
cmpt363-e100/
default.md
drafts/
modular.md
reviewed/
modular.md
BTW both modular pages are not required but are mentioned as they could be used to display a collection of draft and reviewed assignments.
Then the 'Submit assignment for review' page (with slug submit-assignment
) full content (both frontmatter and content) could look like:
---
routable: true
title: 'Submit assignment for review'
template: form
visible: true
pageconfig:
parent: /submitted-assignments/cmpt363-e100/drafts
pagefrontmatter:
visible: true
status: draft
template: default
course:
assignment: 'CMPT363 E100'
instructor:
name: 'Jane Doe'
form:
name: addpage-assignment-cmpt363-e100
fields:
-
name: name
label: Name
type: text
validate:
required: true
-
name: title
label: Title
type: text
validate:
required: true
-
name: content
label: 'Assignment text'
type: textarea
size: long
classes: editor
validate:
required: true
-
name: attachments
label: 'Attachment (PDF only)'
type: file
multiple: true
accept:
- application/pdf
validate:
required: false
-
name: honeypot
type: honeypot
buttons:
-
type: submit
value: Submit
process:
-
addpage: null
-
redirect: '@self'
---
Please write your assignment and attach any images and/or files.
Supposing the user has not changed the pre filled title field, has entered his name "Paul Walker", has entered a simple "q.e.d." as the assignment content and uploaded one PDF document, then the full new page will be:
---
visible: true
status: draft
course:
assignment: 'CMPT363 E100'
instructor:
name: 'Jane Doe'
name: 'Paul Walker'
title: 'CMPT363 E100'
attachments:
/Users/rwgc/devroot/repos/grav-test/htdocs/user/pages/assignments/cmpt363-e100/drafts/cmpt363-e100-1/scrum-guide-sept-2013.pdf
name: scrum-guide-sept-2013.pdf
type: application/pdf
size: 273 KB
path: /Users/rwgc/devroot/repos/grav-test/htdocs/user/pages/assignments/cmpt363-e100/drafts/cmpt363-e100-1/scrum-guide-sept-2013.pdf
---
q.e.d.
On the file system level the file structure will be:
01.home/
default.md
02.add-new-article/
default.md
03.assignments/
cmpt363-e100/
default.md
drafts/
cmpt363-e100-1/
default.md
scrum-guide-sept-2013.pdf
modular.md
reviewed/
modular.md
Form page example 2: create a blog post
In this example the user can add a blog post. To ensure the new page will be treated as a blog post simply set the template
variable to be used by the new page to item
. BTW the active theme must include the corresponding template item.html.twig
. This is why it is best to start with Grav's default theme Antimatter.
---
title: 'Add Blog Post'
template: form
pageconfig:
parent: '/blog'
include_username: true
overwrite_mode: true
pagefrontmatter:
template: item
title: My new Blog post
taxonomy:
category: blog
tag: [journal, guest]
form:
name: add_page.blogpost
fields:
-
name: author
label: 'Author'
type: text
-
name: title
label: 'Post Title'
type: text
-
name: taxonomy.tag
label: 'Tags (comma separated)'
type: text
-
name: content
label: 'Post Content'
type: textarea
size: long
classes: editor
-
name: images
label: 'Images to upload'
type: file
multiple: true
accept:
- 'image/*'
-
name: honeypot
type: honeypot
buttons:
-
type: submit
value: Submit
process:
-
add_page: true
-
redirect: '/blog'
---
## New Blog Post
Write your blog post:
After the form has been submitted the user is taken to the blog main page where the new post should show up.
Issues
Grav Form issue
The form on the form page is a standard Grav form. Please note that the Grav Form Plugin currently (latest test using version 4.0.1) has an issue which prevents the form to be submitted when a form field of type file
is set to required: true
(see issue #106).
Credits
- Team Grav and everyone who contributes to Grav;
- Wes Cossick for SimpleMDE Markdown Editor;
- All contributors who've helped me out on things.