Last active
November 28, 2016 08:41
-
-
Save michaeluno/8f2ea5514925d60b7134f71783f25fb2 to your computer and use it in GitHub Desktop.
Demonstrates front-end forms using Admin Page Framework.
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 | |
/** | |
* Plugin Name: Admin Page Framework - Front-end Form (beta) | |
* Plugin URI: http://en.michaeluno.jp/admin-page-framework | |
* Description: Demonstrates front-end forms using Admin Page Framework. | |
* Author: Michael Uno | |
* Author URI: http://michaeluno.jp | |
* Version: 1.0.0 | |
* | |
*/ | |
final class AdminPageFramework_FrontEndFormBeta_Bootstrap { | |
public function __construct() { | |
add_action( 'plugins_loaded', array( $this, 'replyToLoadPlugin' ) ); | |
} | |
public function replyToLoadPlugin() { | |
$_sAPFPath = defined( 'WP_DEBUG' ) && WP_DEBUG | |
? dirname( dirname( __FILE__ ) ) . '/admin-page-framework/development/admin-page-framework.php' | |
: dirname( dirname( __FILE__ ) ) . '/admin-page-framework/library/apf/admin-page-framework.php'; | |
include( $_sAPFPath ); | |
if ( ! class_exists( 'AdminPageFramework' ) ) { | |
return; | |
} | |
include( dirname( __FILE__ ) . '/AdminPageFramework_FormBeta_frontend.php' ); | |
include( dirname( __FILE__ ) . '/AdminPageFramework_FrontendFormBeta_Base.php' ); | |
include( dirname( __FILE__ ) . '/AdminPageFramework_FrontendFormBeta.php' ); | |
} | |
} | |
new AdminPageFramework_FrontEndFormBeta_Bootstrap; |
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 | |
class AdminPageFramework_FormBeta_frontend extends AdminPageFramework_Form { | |
/** | |
* Stores sub-object class names. | |
* | |
* | |
* @since 3.8.11 | |
*/ | |
public $aSubClasses = array( | |
'submit_notice' => '', // disable it | |
'field_error' => '', // disable it | |
'last_input' => '', // disable it | |
'message' => 'AdminPageFramework_Message', | |
); | |
public function setFieldErrors( $aErrors ) {} | |
public function getFieldErrors() { | |
return $this->aArguments[ 'caller_object' ]->aFieldErrors; | |
} | |
} |
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 | |
/** | |
* Displays a form in the front-end. | |
* | |
*/ | |
class AdminPageFramework_FrontendFormBeta extends AdminPageFramework_FrontendFormBeta_Base { | |
/** | |
* The action/filter hook that the form output will be inserted. | |
*/ | |
public $sHookName = 'the_content'; | |
/** | |
* Set the callback priority passed to the `add_action()` or `add_filter()` function. | |
*/ | |
public $iPriority = 11; | |
/** | |
* Set the hook type either `filter` or `action`. | |
*/ | |
public $sHookType = 'filter'; // or action | |
/** | |
* Gets called when the page loads. Do some necessary set-ups here. | |
*/ | |
public function load() { | |
// Register field types | |
if ( class_exists( 'DateCustomFieldType' ) ) { | |
new DateCustomFieldType( get_class( $this ) ); | |
} | |
} | |
/** | |
* Determines whether the form should be loaded in the current page. | |
* @return boolean | |
*/ | |
public function isInThePage() { | |
if ( ! is_singular() ) { | |
return false; | |
} | |
if ( ! is_main_query() ) { | |
return false; | |
} | |
return true; | |
} | |
/** | |
* @return array | |
*/ | |
public function getStyles() { | |
return array( | |
'.form-table { | |
border: none; | |
} | |
.form-table th { | |
width: 30%; | |
} | |
.form-table tr > * { | |
vertical-align: top; | |
border: none; | |
} | |
.form-table tr label, | |
.form-table tr fieldset { | |
vertical-align: middle; | |
} | |
.form-table .admin-page-framework-input-label-container label { | |
vertical-align: top; | |
} | |
.form-table .admin-page-framework-field-radio input { | |
margin-right: 0.4em; | |
} | |
.form-table .admin-page-framework-field-submit { | |
text-align: right; | |
width: 100%; | |
} | |
.form-table .admin-page-framework-field-submit .admin-page-framework-input-button-container { | |
padding-right: 0; | |
} | |
.form-table .select_image.button, | |
.form-table .remove_image.button, | |
.form-table .remove_value.button { | |
text-decoration: none; | |
border: none; | |
} | |
.form-table .admin-page-framework-field { | |
margin: 0; | |
} | |
.form-table .admin-page-framework-checkbox-label { | |
margin-top: 0; | |
} | |
.form-table .admin-page-framework-field .admin-page-framework-input-label-container { | |
margin-bottom: 0; | |
} | |
@media only screen and (max-width: 600px) { | |
.form-table > tbody > tr > td, | |
.form-table > tbody > tr > th { | |
display: inline-block; | |
width: 100%; | |
} | |
.form-table > tbody > tr > td { | |
margin-bottom: 0.6em; | |
} | |
.form-table > tbody > tr { | |
} | |
} | |
/* Notification Containers */ | |
.submit-notice > p { | |
border-radius: 6px; | |
padding: 1em 2em; | |
} | |
.submit-notice.error > p { | |
border: solid 1px #8a2323; | |
background-color: #ffe0e0; | |
} | |
.submit-notice.update > p { | |
border: solid 1px #418a23; | |
background-color: #e9ffe0; | |
} | |
', | |
// or set a CSS file path | |
// dirname( __FILE__ ) . '/css/style.css', | |
); | |
} | |
/** | |
* Retrieves form section definition arrays. | |
* @return array | |
*/ | |
public function getSections() { | |
return array(); | |
} | |
/** | |
* Retrieves form field definition arrays. | |
*/ | |
public function getFields() { | |
return array( | |
array( | |
'title' => __( 'Text Input', 'admin-page-framework' ), | |
'show_debug_info' => false, | |
'field_id' => 'text', | |
'type' => 'text', | |
), | |
array( | |
'title' => __( 'Text Area', 'admin-page-framework' ), | |
'field_id' => 'textarea', | |
'type' => 'textarea', | |
'show_debug_info' => false, | |
), | |
array( | |
'title' => __( 'Radio Buttons', 'admin-page-framework' ), | |
'field_id' => 'radio', | |
'type' => 'radio', | |
'show_debug_info' => false, | |
'label' => array( | |
'on' => __( 'On', 'admin-page-framework' ), | |
'off' => __( 'Off', 'admin-page-framework' ), | |
), | |
'default' => 'on', | |
), | |
array( | |
'title' => __( 'Drop-dorn', 'admin-page-framework' ), | |
'field_id' => 'select', | |
'type' => 'select', | |
'show_debug_info' => false, | |
'label' => array( | |
0 => __( 'Sunday', 'admin-page-framework' ), | |
1 => __( 'Monday', 'admin-page-framework' ), | |
2 => __( 'Tuesday', 'admin-page-framework' ), | |
3 => __( 'Wednesday', 'admin-page-framework' ), | |
4 => __( 'Thursday', 'admin-page-framework' ), | |
5 => __( 'Friday', 'admin-page-framework' ), | |
6 => __( 'Saturday', 'admin-page-framework' ), | |
), | |
'default' => 4, | |
), | |
array( | |
'title' => __( 'Check Box', 'admin-page-framework' ), | |
'field_id' => 'checkbox', | |
'type' => 'checkbox', | |
'show_debug_info' => false, | |
'label' => __( 'This is a check box.', 'admin-page-framework' ), | |
), | |
array( | |
'title' => __( 'Image', 'admin-page-framework' ), | |
'field_id' => 'image', | |
'type' => 'image', | |
'show_debug_info' => false, | |
), | |
array( | |
'title' => __( 'Color', 'admin-page-framework' ), | |
'field_id' => 'color', | |
'type' => 'color', | |
'show_debug_info' => false, | |
), | |
array( | |
'field_id' => 'date', | |
'type' => 'date', | |
'title' => __( 'Date', 'admin-page-framework' ), | |
'date_format' => 'mm/dd', | |
'show_debug_info' => false, | |
), | |
array( | |
'field_id' => '_submit', | |
'type' => 'submit', | |
'value' => __( 'Submit', 'admin-page-framework' ), | |
'show_debug_info' => false, | |
), | |
); | |
} | |
/** | |
* Get the output. | |
* Here you can modify the output. | |
* @return string | |
*/ | |
public function content( $sFormOutput ) { | |
return "<h3>" . __( 'Form', 'admin-page-framework' ) . "</h3>" | |
. $sFormOutput; | |
} | |
/** | |
* Do form submission handling. | |
* @return void | |
*/ | |
public function validate( $aInputs ) { | |
$_bHasError = false; | |
$_aErrors = array(); | |
if ( ! is_numeric( $aInputs[ 'text' ] ) ) { | |
$_aErrors[ 'text' ] = 'Type a numeric value.'; | |
$_bHasError = true; | |
} | |
if ( empty( $aInputs[ 'textarea' ] ) ) { | |
$_aErrors[ 'textarea' ] = 'Please type something.'; | |
$_bHasError = true; | |
} | |
$this->setFieldErrors( $_aErrors ); | |
if ( $_bHasError ) { | |
$this->setSubmitNotice( 'Please correct some information you entered.', 'error' ); | |
$this->aFormData = $aInputs; | |
} else { | |
$this->setSubmitNotice( 'Form has been submitted', 'update' ); | |
} | |
} | |
} | |
new AdminPageFramework_FrontendFormBeta; |
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 | |
/** | |
* Provides an abstract base class for front-end forms. | |
* | |
* Usage | |
* | |
* 1. In your desired location, print an output of your custom WordPress filter. | |
* ``` | |
* echo apply_filters( 'your_custom_filter', '' ); | |
* ``` | |
* | |
* Or, do an action. | |
* ``` | |
* do_action( 'your_custom_action' ); | |
* ``` | |
* | |
* 2. Extend this class. | |
* ``` | |
* class YourFrontendFormClass extends AdminPageFramework_FrontendFormBeta_Base { | |
* | |
* } | |
* ``` | |
* | |
* 3. Set your filter or action in the `$sHookName` property. | |
* ``` | |
* public $sHookName = 'your_custom_filter'; | |
* public $sHookType = 'filter'; | |
* ``` | |
* Or | |
* ``` | |
* public $sHookName = 'your_custom_action'; | |
* public $sHookType = 'action'; | |
* ``` | |
* | |
* 4. In the `getFields()` method, define field definition arrays to return. | |
* ``` | |
* public function getFields() { | |
* return array( | |
* array( | |
* 'title' => __( 'Text Input', 'admin-page-framework' ), | |
* 'field_id' => 'text', | |
* 'type' => 'text', | |
* ), | |
* array( | |
* 'field_id' => '_submit', | |
* 'type' => 'submit', | |
* 'value' => __( 'Submit', 'admin-page-framework' ), | |
* ), | |
* ); | |
* } | |
* ``` | |
* Similarly, define section in the `getSections()` method. | |
* | |
* 5. In the `getStyles()` method, define your CSS rules or set paths for stylesheets. | |
* ``` | |
* public function getStyles() { | |
* return array( | |
* dirname( __FILE__ ) . '/css/style.css', | |
* ); | |
* } | |
* Similarly, set script paths in the `getScripts()` method. | |
* | |
* ``` | |
* 6. Instantiate the class. | |
* ``` | |
* new YourFrontendFormClass; | |
* ``` | |
* | |
* When you include this class with your generated framework files, | |
* make sure the used class names here with AdminPageFramework are all prefixed with the one you set in Generator. | |
* | |
* @remark Required Admin Page Framework 3.8.11 or above. | |
*/ | |
abstract class AdminPageFramework_FrontendFormBeta_Base { | |
/* Override these properties from here */ | |
public $sHookName = ''; // e.g `the_content` | |
public $iPriority = 11; | |
public $sHookType = 'filter'; // or action | |
/* to here */ | |
/** | |
* Stores the form field values. | |
*/ | |
public $aFormData = array(); | |
public $aFieldErrors = array(); | |
public $aSubmitNotices = array(); | |
public $oForm; | |
private $___sNonceActionName = 'admin-page-framework-frontend_form'; | |
/** | |
* Sets up hooks. | |
*/ | |
public function __construct() { | |
add_action( 'wp', array( $this, '_replyToDetermineWhetherToLoad' ) ); | |
$this->construct(); | |
} | |
/** | |
* Determines whether to load the form. | |
* @callback action wp | |
* @return void | |
*/ | |
public function _replyToDetermineWhetherToLoad() { | |
if ( ! class_exists( 'AdminPageFramework_Message' ) ) { | |
return; | |
} | |
if ( ! $this->isInThePage() ) { | |
return; | |
} | |
$this->___setHooks(); | |
$this->___setProperties(); | |
/** | |
* Let the user do necessary routines before setting up the form such as showing a notification message based on the form submission etc. | |
*/ | |
$this->load(); | |
$this->___setUp(); | |
if ( $this->___isFormSubmitted() ) { | |
$this->___handleFormSubmission(); | |
} | |
} | |
/** | |
* @return boolean | |
*/ | |
private function ___isFormSubmitted() { | |
if ( ! isset( $_REQUEST[ $this->___sNonceActionName ] ) ) { | |
return false; | |
} | |
if ( ! wp_verify_nonce( $_REQUEST[ $this->___sNonceActionName ], $this->___sNonceActionName ) ) { | |
return false; | |
} | |
return true; | |
} | |
private function ___handleFormSubmission() { | |
$aInputs = $_REQUEST; | |
unset( | |
$aInputs[ '_admin-page-framework_frontend_form' ], | |
$aInputs[ '_wp_http_referer' ], | |
$aInputs[ '__submit' ], | |
$aInputs[ '__repeatable_elements_' . $this->oForm->aArguments[ 'structure_type' ] ] | |
); | |
$this->validate( $aInputs ); | |
} | |
private function ___setProperties() { | |
$this->oForm = new AdminPageFramework_FormBeta_frontend( | |
array( // form object arguments | |
'caller_id' => get_class( $this ), | |
'structure_type' => 'frontend', | |
'action_hook_form_registration' => 'wp_enqueue_scripts', | |
// custom arguments | |
'caller_object' => $this, | |
), | |
array( // callbacks | |
'saved_data' => array( $this, 'replyToSetFormData' ), | |
) | |
); | |
} | |
private function ___setHooks() { | |
if ( ! $this->sHookName ) { | |
return; | |
} | |
$_aFunctionNames = array( | |
'filter' => 'add_filter', | |
'action' => 'add_action', | |
); | |
$_sFunctionName = isset( $_aFunctionNames[ $this->sHookType ] ) | |
? $_aFunctionNames[ $this->sHookType ] | |
: $_aFunctionNames[ 'filter' ]; | |
call_user_func_array( | |
$_sFunctionName, | |
array( | |
$this->sHookName, | |
array( $this, '_replyToGetForm' ), | |
$this->iPriority | |
) | |
); | |
} | |
/** | |
* @callback filter|action | |
*/ | |
public function _replyToGetForm( $sContent ) { | |
if ( 'filter' === $this->sHookType ) { | |
return $sContent . $this->___getFormWrapped(); | |
} | |
echo $this->___getFormWrapped(); | |
} | |
/** | |
* @return string | |
*/ | |
private function ___getFormWrapped() { | |
return $this->___getSubmitNotices() | |
. "<form class='admin-page-framework-frontend-form' method='post'>" | |
. $this->___getHiddenFields() | |
. $this->___getFormOutput() | |
. "</form>"; | |
} | |
/** | |
* @return string | |
*/ | |
private function ___getSubmitNotices() { | |
$_sOutput = ''; | |
if ( empty( $this->aSubmitNotices ) ) { | |
return $_sOutput; | |
} | |
foreach( $this->aSubmitNotices as $_aNotice ) { | |
$_sOutput .= "<div class='submit-notice " . esc_attr( $_aNotice[ 1 ] ) . "'>" | |
. "<p>" . $_aNotice[ 0 ] . "</p>" | |
. "</div>"; | |
} | |
return $_sOutput; | |
} | |
private function ___getFormOutput() { | |
return $this->content( $this->oForm->get() ); | |
} | |
private function ___getHiddenFields() { | |
return wp_nonce_field( | |
$this->___sNonceActionName, // nonce action name | |
$this->___sNonceActionName, // input name | |
true, // embed referrer | |
false // echo | |
); | |
} | |
/** | |
* Sets up form elements. | |
*/ | |
private function ___setUp() { | |
$this->___setResourcesByType( ( array ) $this->getStyles(), 'style' ); | |
$this->___setResourcesByType( ( array ) $this->getScripts(), 'script' ); | |
$_aSections = $this->getSections(); | |
$_aSections = is_array( $_aSections ) ? $_aSections : array(); | |
foreach( $_aSections as $_asSection ) { | |
$this->oForm->addSection( $_asSection ); | |
} | |
$_aFields = $this->getFields(); | |
$_aFields = is_array( $_aFields ) ? $_aFields : array(); | |
foreach( $_aFields as $_asField ) { | |
$this->oForm->addField( $_asField ); | |
} | |
} | |
private function ___setResourcesByType( array $aItems, $sType ) { | |
foreach( $aItems as $_iItem ) { | |
if ( ! $_iItem ) { | |
continue; | |
} | |
if ( $this->___isURL( $_iItem ) || file_exists( $_iItem ) ) { | |
$_sKey = 'style' === $sType ? 'src_styles' : 'src_scripts'; | |
$this->oForm->addResource( $_sKey, $_iItem ); | |
} | |
$_sKey = 'style' === $sType ? 'internal_styles' : 'internal_scripts'; | |
$this->oForm->addResource( $_sKey, $_iItem ); | |
} | |
} | |
/** | |
* @return boolean | |
*/ | |
private function ___isURL( $sItem ) { | |
return ( ! filter_var( $sItem, FILTER_VALIDATE_URL ) === false ); | |
} | |
/** | |
* @callback form_filter saved_data | |
* @return array | |
*/ | |
public function replyToSetFormData( $aData ) { | |
return $this->aFormData + $aData; | |
} | |
/** | |
* Sets a given field errors. | |
* @return void | |
*/ | |
public function setFieldErrors( $aErrors ) { | |
$this->aFieldErrors = $aErrors; | |
} | |
/** | |
* Sets the given message to be displayed in the next page load. | |
* | |
* This is used to inform users about the submitted input data, such as "Updated successfully." or "Problem occurred." etc. | |
* and normally used in validation callback methods. | |
* | |
* <h4>Example</h4> | |
* ` | |
* if ( ! $bVerified ) { | |
* $this->setFieldErrors( $aErrors ); | |
* $this->setSubmitNotice( 'There was an error in your input.' ); | |
* return $aOldPageOptions; | |
* } | |
* ` | |
* @access public | |
* @param string $sMessage the text message to be displayed. | |
* @param string $sType (optional) the type of the message, either "error" or "updated" is used. | |
* @param array $asAttributes (optional) the tag attribute array applied to the message container HTML element. If a string is given, it is used as the ID attribute value. | |
* @param boolean $bOverride (optional) If true, only one message will be shown in the next page load. false: do not override when there is a message of the same id. true: override the previous one. | |
* @return void | |
*/ | |
public function setSubmitNotice( $sMessage, $sType='error', $asAttributes=array(), $bOverride=true ) { | |
$_aNotice = func_get_args() + array( '', 'error', array(), false ); | |
// Has a message? | |
if ( ! $_aNotice[ 0 ] ) { | |
return; | |
} | |
// Override? | |
if ( $_aNotice[ 3 ] ) { | |
$this->aSubmitNotices = $_aNotice; | |
return; | |
} | |
$this->aSubmitNotices[] = $_aNotice; | |
} | |
/** ----------------------------------------------------------------------------------- | |
* Override the methods below. | |
*/ | |
/** | |
* User constructor. | |
* @remark Override this method to do necessary set-ups. | |
*/ | |
public function construct() {} | |
/** | |
* Gets called when the page loads. Do some necessary set-ups here. | |
*/ | |
public function load() {} | |
/** | |
* @remark Override this method in an extended class. | |
* @return boolean | |
*/ | |
public function isInThePage() { | |
return true; | |
} | |
/** | |
* Return the form output. | |
* @return string | |
*/ | |
public function content( $sFormOutput ) { | |
return $sFormOutput; | |
} | |
/** | |
* Retrieves form section definition arrays. | |
* @return array | |
*/ | |
public function getSections() { | |
return array(); | |
} | |
/** | |
* Retrieves form field definition arrays. | |
* @return array | |
*/ | |
public function getFields() { | |
return array(); | |
} | |
/** | |
* @return array | |
*/ | |
public function validate( $aInputs ) { | |
return array(); | |
} | |
/** | |
* Return internal CSS rules. | |
* @return array | |
* ``` | |
* return array( | |
* dirname( __FILE__ ) . '/css/style.css', | |
* dirname( __FILE__ ) . '/css/style2.css', // path | |
* plugins_url( '/asset/css/style.css' ), // url | |
* '.form-field { max-width: 100; }', // text rules | |
* ); | |
* ``` | |
*/ | |
public function getStyles() { | |
return array(); | |
} | |
/** | |
* Return internal JavaSript script. | |
* @return array | |
* ``` | |
* return array( | |
* dirname( __FILE__ ) . '/js/script.js', | |
* dirname( __FILE__ ) . '/js/script2.js', // path | |
* plugins_url( '/asset/js/script.js' ), // url | |
* 'jQuery( '.admin-page-framework-section-tabs-contents' ).createTabs(); ', // text script | |
* ); | |
* ``` | |
*/ | |
public function getScripts() { | |
return array(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment