-
Christian Wach authoredChristian Wach authored
class-cfafa-form-action-base.php 14.43 KiB
<?php
/**
* ACFE Form Action Base Class.
*
* Holds methods common to ACFE Form Action classes.
*
* @package Conditional_Form_Actions_For_ACFE
*/
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
/**
* "Base" ACFE Form Action Class.
*
* A class that is extended by ACFE Form Action classes.
*
* @since 0.1
*/
class CFAFA_Form_Action_Base {
/**
* Form Action Name.
*
* @since 0.1
* @access public
* @var string
*/
public $action_name = '';
/**
* Form Action Label.
*
* @since 0.1
* @access public
* @var string
*/
public $action_label = '';
/**
* Form Action Alias Placeholder.
*
* @since 0.1
* @access public
* @var string
*/
public $alias_placeholder = '';
/**
* Field Key Prefix.
*
* @since 0.1
* @access public
* @var string
*/
public $field_key = '';
/**
* Field Name Prefix.
*
* @since 0.1
* @access public
* @var string
*/
public $field_name = '';
/**
* Constructor.
*
* @since 0.1
*/
public function __construct() {
// Callback for the "acfe/form/load/..." hook.
add_filter( 'acfe/form/load/' . $this->action_name, [ $this, 'load' ], 10, 3 );
// Callback for the "acfe/form/make/..." hook.
add_action( 'acfe/form/make/' . $this->action_name, [ $this, 'make' ], 10, 3 );
// Generic callback for ACFE Form Actions hook.
add_filter( 'acfe/form/actions', [ $this, 'action_add' ] );
}
/**
* Allow classes to configure themselves prior to the Layout being returned.
*
* @since 0.1
*/
protected function configure() {}
/**
* Performs tasks when the Form that the Action is attached to is loaded.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post in which the Form has been embedded.
* @param string $action The customised name of the action.
*/
public function load( $form, $current_post_id, $action ) {
return $form;
}
/**
* Saves the result of the Action for use by subsequent Actions.
*
* @since 0.1
*
* @param string $action The name of the Action.
* @param array $data The result of the Action.
*/
protected function load_action_save( $action, $data ) {
// Get the existing array of Action results.
$actions = get_query_var( 'acfe_form_actions', [] );
$actions[ $this->action_name ] = $data;
if ( ! empty( $action ) ) {
$actions[ $action ] = $data;
}
// Update array of Action results.
set_query_var( 'acfe_form_actions', $actions );
}
/**
* Performs the Action when the Form the Action is attached to is submitted.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the action.
*/
public function make( $form, $current_post_id, $action ) {}
/**
* Maybe skip the Action when the Form the Action is attached to is submitted.
*
* @since 0.1
*
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the Form Action.
* @return bool $prepare The net result of the set of filters.
*/
protected function make_skip( $form, $current_post_id, $action ) {
// Get some Form details.
$form_name = acf_maybe_get( $form, 'name' );
$form_id = acf_maybe_get( $form, 'ID' );
// Assume we're good to go.
$prepare = true;
/**
* Allow others to prevent Form Action.
*
* Returning false for any of these filters will skip the Action.
*
* @since 0.1
*
* @param bool $prepare True by default so that the Form Action goes ahead.
* @param array $form The array of Form data.
* @param integer $current_post_id The ID of the Post from which the Form has been submitted.
* @param string $action The customised name of the Form Action.
*/
$filter = 'acfe/form/prepare/' . $this->action_name;
$prepare = apply_filters( $filter, $prepare, $form, $current_post_id, $action );
$prepare = apply_filters( $filter . '/form=' . $form_name, $prepare, $form, $current_post_id, $action );
if ( ! empty( $action ) ) {
$prepare = apply_filters( $filter . '/action=' . $action, $prepare, $form, $current_post_id, $action );
}
// --<
return $prepare;
}
/**
* Saves the result of the Action for use by subsequent Actions.
*
* @since 0.1
*
* @param string $action The name of the Action.
* @param array $data The result of the Action.
*/
protected function make_action_save( $action, $data ) {
// Get the existing array of Action results.
$actions = get_query_var( 'acfe_form_actions', [] );
$actions[ $this->action_name ] = $data;
if ( ! empty( $action ) ) {
$actions[ $action ] = $data;
}
// Update array of Action results.
set_query_var( 'acfe_form_actions', $actions );
}
/**
* Defines the action by adding a layout.
*
* The "name" value of the layout determines the construction of the
* "acfe/form/load/..." and "acfe/form/make/..." actions.
*
* @since 0.1
*
* @param array $layouts The existing layouts.
* @return array $layouts The modified layouts.
*/
public function action_add( $layouts ) {
// Let the classes that extend this one configure themselves.
$this->configure();
// Init our layout.
$layout = [
'key' => 'layout_' . $this->action_name,
'name' => $this->action_name,
'label' => $this->action_label,
'display' => 'row',
'min' => '',
'max' => '',
];
// Build Action Tab.
$action_tab_fields = $this->tab_action_add();
// Build Mapping Tab.
$mapping_tab_fields = $this->tab_mapping_add();
// Build Attachments Tab.
$attachments_tab_fields = $this->tab_attachments_add();
// Combine Sub-Fields.
$sub_fields = array_merge(
$action_tab_fields,
$mapping_tab_fields,
$attachments_tab_fields
);
/**
* Let the classes that extend this one modify the Sub-Fields.
*
* @since 0.1
*
* @param array $sub_fields The array of Sub-Fields.
*/
$layout['sub_fields'] = apply_filters( 'cfafa/acfe/form/actions/sub_fields', $sub_fields );
// Add our completed layout to the layouts array.
$layouts[ 'layout_' . $this->action_name ] = $layout;
// --<
return $layouts;
}
/**
* Defines the "Action" Tab.
*
* These Fields are required to configure the Form Action.
*
* The ACFE "Action name" Field has a pre-defined format, e.g. it must be
* assigned the "acfe_slug" Field Type and have "acfe_form_custom_alias" as
* its "name". Only its "placeholder" attribute needs to be configured.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
protected function tab_action_add() {
// Init Fields array.
$fields = [];
// "Action" Tab wrapper.
$fields[] = [
'key' => $this->field_key . 'tab_action',
'label' => __( 'Action', 'conditional-form-actions-for-acfe' ),
'name' => '',
'type' => 'tab',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
'data-no-preference' => true,
],
'acfe_permissions' => '',
'placement' => 'top',
'endpoint' => 0,
];
// "Action name" Field.
$fields[] = [
'key' => $this->field_key . 'custom_alias',
'label' => __( 'Action name', 'conditional-form-actions-for-acfe' ),
'name' => 'acfe_form_custom_alias',
'type' => 'acfe_slug',
'instructions' => __( '(Required) Name this action so it can be referenced.', 'conditional-form-actions-for-acfe' ),
'required' => 1,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
'data-instruction-placement' => 'field',
],
'acfe_permissions' => '',
'default_value' => '',
'placeholder' => $this->alias_placeholder,
'prepend' => '',
'append' => '',
'maxlength' => '',
];
// Add any further Fields.
$action_extras = $this->tab_action_append();
if ( ! empty( $action_extras ) ) {
$fields = array_merge(
$fields,
$action_extras
);
}
// --<
return $fields;
}
/**
* Defines additional Fields for the "Action" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
protected function tab_action_append() {
$fields = [];
return $fields;
}
/**
* Defines the "Mapping" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
protected function tab_mapping_add() {
$fields = [];
return $fields;
}
/**
* Defines the "Mapping" Tab Header.
*
* @since 0.1
*
* @param string $label The label for this section.
* @return array $fields The array of Fields for this section.
*/
protected function tab_mapping_header( $label = '' ) {
// Set a default label.
if ( empty( $label ) ) {
$label = __( 'Mapping', 'conditional-form-actions-for-acfe' );
}
// "Mapping" Tab wrapper.
$mapping_tab = [
[
'key' => $this->field_key . 'tab_load',
'label' => $label,
'name' => '',
'type' => 'tab',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
'data-no-preference' => true,
],
'acfe_permissions' => '',
'placement' => 'top',
'endpoint' => 0,
],
];
// Combine Fields.
$fields = array_merge(
$mapping_tab
);
// --<
return $fields;
}
/**
* Defines the "Attachments" Tab.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
protected function tab_attachments_add() {
$fields = [];
return $fields;
}
/**
* Defines the "Attachments" Tab Header.
*
* @since 0.1
*
* @return array $fields The array of Fields for this section.
*/
protected function tab_attachments_header() {
// "Attachments" Tab wrapper.
$attachments_tab = [
[
'key' => $this->field_key . 'tab_attachments',
'label' => __( 'Attachments', 'conditional-form-actions-for-acfe' ),
'name' => '',
'type' => 'tab',
'instructions' => '',
'required' => 0,
'conditional_logic' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
'data-no-preference' => true,
],
'acfe_permissions' => '',
'placement' => 'top',
'endpoint' => 0,
],
];
// Combine Fields.
$fields = array_merge(
$attachments_tab
);
// --<
return $fields;
}
/**
* Gets the array that defines a "Map Field" for the "Mapping" Tab.
*
* @since 0.1
*
* @param string $code The unique code for the Field.
* @param string $label The label for the Field.
* @param array $conditional_logic The conditional logic for the Field.
* @return array $field The array of Field data.
*/
protected function mapping_field_get( $code, $label, $conditional_logic = [] ) {
// Build the Field array.
$field = [
'key' => $this->field_key . 'map_' . $code,
'label' => $label,
'name' => $this->field_name . 'map_' . $code,
'type' => 'select',
'instructions' => '',
'required' => 0,
'wrapper' => [
'width' => '',
'class' => '',
'id' => '',
],
'acfe_permissions' => '',
'choices' => [],
'default_value' => [],
'allow_null' => 1,
'multiple' => 0,
'ui' => 1,
'return_format' => 'value',
'placeholder' => __( 'Default', 'conditional-form-actions-for-acfe' ),
'ajax' => 0,
'search_placeholder' => __( 'Enter a custom value or template tag. (See "Cheatsheet" tab)', 'conditional-form-actions-for-acfe' ),
'allow_custom' => 1,
];
// Default conditional logic.
$field['conditional_logic'] = 0;
// Maybe replace with custom conditional logic.
if ( ! empty( $conditional_logic ) ) {
$field['conditional_logic'] = $conditional_logic;
}
// --<
return $field;
}
/**
* Adds filters that configure "Mapping Fields" when loaded.
*
* @since 0.1
*
* @param string $code The unique code for the Field.
*/
protected function mapping_field_filters_add( $code ) {
// Grab reference to ACFE Helper object.
$helpers = acf_get_instance( 'acfe_dynamic_forms_helpers' );
// Populate mapping Fields.
add_filter( 'acf/prepare_field/name=' . $this->field_name . 'map_' . $code, [ $helpers, 'map_fields_deep_no_custom' ] );
}
/**
* Adds filters that configure a named Field when loaded.
*
* @since 0.1
*
* @param string $name The unique name for the Field.
*/
protected function mapping_field_filter_deep( $name ) {
// Grab reference to ACFE Helper object.
$helpers = acf_get_instance( 'acfe_dynamic_forms_helpers' );
// Populate named Field.
add_filter( 'acf/prepare_field/name=' . $name, [ $helpers, 'map_fields_deep' ] );
}
/**
* Prepare the data from an ACFE Form.
*
* @since 0.1
*
* @param array $form_data The array of data from the ACFE Form.
* @return array $filtered_data The filtered data.
*/
protected function form_data_prepare( $form_data ) {
// Init filtered data.
$filtered_data = [];
// Bail if we have no Form data to save.
if ( empty( $form_data ) ) {
return $filtered_data;
}
// Populate return array from the Form data.
foreach ( $form_data as $param => $value ) {
// Skip if empty but allow (string) "0" as valid data.
if ( empty( $value ) && '0' !== $value ) {
continue;
}
// Maybe decode entities.
if ( is_string( $value ) && ! is_numeric( $value ) ) {
$value = html_entity_decode( $value );
}
// Maybe decode entities in arrays.
if ( is_array( $value ) ) {
array_walk_recursive(
$value,
function( &$item ) {
if ( is_string( $item ) && ! is_numeric( $item ) ) {
$item = html_entity_decode( $item );
}
}
);
}
// Finally add value to return array.
$filtered_data[ $param ] = $value;
}
// --<
return $filtered_data;
}
}