Files
2024-07-15 11:28:08 +02:00

496 lines
12 KiB
PHP

<?php
/**
* Module Name: Interface Builder
* Description: The module for the creation of interfaces in the WordPress admin panel
* Author: Cherry Team
* Author URI: http://www.cherryframework.com/
* License: GPLv3
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
*
* @package Cherry_Framework
* @subpackage Modules
* @author Cherry Team <cherryframework@gmail.com>
* @copyright Copyright (c) 2012 - 2017, Cherry Team
* @link http://www.cherryframework.com/
* @license http://www.gnu.org/licenses/gpl-3.0.html
*/
// If this file is called directly, abort.
if ( ! defined( 'WPINC' ) ) {
die;
}
if ( ! class_exists( 'Cherry5_Interface_Builder' ) ) {
/**
* Class Cherry Interface Builder.
*
* @since 1.0.0
*/
class Cherry5_Interface_Builder {
/**
* Core version.
*
* @since 1.5.0
* @access public
* @var string
*/
public $core_version = '';
/**
* Module directory path.
*
* @since 1.5.0
* @access protected
* @var srting.
*/
protected $module_path;
/**
* Module settings.
*
* @since 1.0.0
* @access private
* @var array
*/
private $args = array(
'views' => array(
'section' => 'inc/views/section.php',
'component-tab-vertical' => 'inc/views/component-tab-vertical.php',
'component-tab-horizontal' => 'inc/views/component-tab-horizontal.php',
'component-toggle' => 'inc/views/component-toggle.php',
'component-accordion' => 'inc/views/component-accordion.php',
'component-repeater' => 'inc/views/component-repeater.php',
'settings' => 'inc/views/settings.php',
'control' => 'inc/views/control.php',
'settings-children-title' => 'inc/views/settings-children-title.php',
'tab-children-title' => 'inc/views/tab-children-title.php',
'toggle-children-title' => 'inc/views/toggle-children-title.php',
'form' => 'inc/views/form.php',
'html' => 'inc/views/html.php',
),
'views_args' => array(
'parent' => '',
'type' => '',
'view' => '',
'view_wrapping' => true,
'html' => '',
'scroll' => false,
'master' => false,
'title' => '',
'description' => '',
),
);
/**
* A reference to an instance of this class.
*
* @since 1.0.0
* @access private
* @var object
*/
private static $instance = null;
/**
* UI element instance.
*
* @since 1.0.0
* @access public
* @var object
*/
public $ui_elements = null;
/**
* The structure of the interface elements.
*
* @since 1.0.0
* @access private
* @var array
*/
private $structure = array();
/**
* Cherry_Interface_Builder constructor.
*
* @since 1.0.0
* @access public
* @return void
*/
public function __construct( $core, array $args = array() ) {
$this->args = array_merge_recursive(
$args,
$this->args
);
$this->core_version = $core->get_core_version();
$this->module_path = $args['module_path'];
$this->ui_elements = $core->init_module( 'cherry-ui-elements' );
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
}
/**
* Register element type section.
*
* @since 1.0.0
* @access public
* @param array $args Options section.
* @return void
*/
public function register_section( array $args = array() ) {
$this->add_new_element( $args, 'section' );
}
/**
* Register element type component.
*
* @since 1.0.0
* @access public
* @param array $args Options component.
* @return void
*/
public function register_component( array $args = array() ) {
$this->add_new_element( $args, 'component' );
}
/**
* Register element type settings.
*
* @since 1.0.0
* @access public
* @param array $args Options settings.
* @return void
*/
public function register_settings( array $args = array() ) {
$this->add_new_element( $args, 'settings' );
}
/**
* Register element type control.
*
* @since 1.0.0
* @access public
* @param array $args Options control.
* @return void
*/
public function register_control( array $args = array() ) {
$this->add_new_element( $args, 'control' );
}
/**
* Register element type form.
*
* @since 1.0.0
* @access public
* @param array $args Options form.
* @return void
*/
public function register_form( array $args = array() ) {
$this->add_new_element( $args, 'form' );
}
/**
* Register element type html.
*
* @since 1.0.0
* @access public
* @param array $args Options control.
* @return void
*/
public function register_html( array $args = array() ) {
$this->add_new_element( $args, 'html' );
}
/**
* This function adds a new element to the structure.
*
* @since 1.0.0
* @access protected
* @param array $args Options new element.
* @param string $type Type new element.
* @return void
*/
protected function add_new_element( array $args = array(), $type = 'section' ) {
if ( ! isset( $args[0] ) && ! is_array( current( $args ) ) ) {
if ( 'control' !== $type && 'component' !== $type ) {
$args['type'] = $type;
}
$this->structure[ $args['id'] ] = $args;
} else {
foreach ( $args as $key => $value ) {
if ( 'control' !== $type && 'component' !== $type ) {
$value['type'] = $type;
}
$this->structure[ $key ] = $value;
}
}
}
/**
* Sorts the elements of the structure, adding child items to the parent.
*
* @since 1.0.0
* @access protected
* @param array $structure The original structure of the elements.
* @param string $parent_key The key of the parent element.
* @return array
*/
protected function sort_structure( array $structure = array(), $parent_key = null ) {
$new_array = array();
foreach ( $structure as $key => $value ) {
if (
( null === $parent_key && ! isset( $value['parent'] ) )
|| null === $parent_key && ! isset( $structure[ $value['parent'] ] )
|| ( isset( $value['parent'] ) && $value['parent'] === $parent_key )
) {
if ( ! isset( $value['id'] ) ) {
$value['id'] = $key;
}
if ( ! isset( $value['name'] ) ) {
$value['name'] = $key;
}
$new_array[ $key ] = $value;
$children = $this->sort_structure( $structure, $key );
if ( ! empty( $children ) ) {
$new_array[ $key ]['children'] = $children;
}
}
}
return $new_array;
}
/**
* Reset structure array.
* Call this method only after render.
*
* @since 1.0.1
* @return void
*/
public function reset_structure() {
$this->structure = array();
}
/**
* Get view for interface elements.
*
* @since 1.0.0
* @access protected
* @param string $type View type.
* @param array $args Input data.
* @return string
*/
protected function get_view( $type = 'control', array $args = array() ) {
if ( empty( $args['view'] ) ) {
$path = ( array_key_exists( $type, $this->args['views'] ) ) ? $this->args['views'][ $type ] : $this->args['views']['control'];
$path = is_array( $path ) ? $path[0] : $path;
$path = file_exists( $path ) ? $path : $this->module_path . $path;
} else {
$path = $args['view'];
}
return Cherry_Toolkit::render_view( $path, $args );
}
/**
* Render HTML elements.
*
* @since 1.0.0
* @access public
* @param bool $echo Input data.
* @param array $args The original structure of the elements.
* @return string
*/
public function render( $echo = true, array $args = array() ) {
if ( empty( $args ) ) {
$args = $this->structure;
}
if ( empty( $args ) ) {
return false;
}
$sorted_structure = $this->sort_structure( $args );
$output = $this->build( $sorted_structure );
$output = str_replace( array( "\r\n", "\r", "\n", "\t" ), '', $output );
$this->reset_structure();
return $this->output_method( $output, $echo );
}
/**
* Render HTML elements.
*
* @since 1.0.0
* @access protected
* @param array $args Input data.
* @return string
*/
protected function build( array $args = array() ) {
$output = '';
$views = $this->args['views'];
foreach ( $args as $key => $value ) {
$value = wp_parse_args(
$value,
$this->args['views_args']
);
$value['class'] = isset( $value['class'] ) ? $value['class'] . ' ' : '';
$value['class'] .= $value['id'] . ' ';
if ( $value['scroll'] ) {
$value['class'] .= 'cherry-scroll ';
}
if ( $value['master'] ) {
$value['class'] .= $value['master'] . ' ';
}
$type = array_key_exists( $value['type'], $views ) ? $value['type'] : 'field';
$has_child = isset( $value['children'] ) && is_array( $value['children'] ) && ! empty( $value['children'] );
switch ( $type ) {
case 'component-tab-vertical':
case 'component-tab-horizontal':
if ( $has_child ) {
$value['tabs'] = '';
foreach ( $value['children'] as $key_children => $value_children ) {
$value['tabs'] .= $this->get_view( 'tab-children-title', $value_children );
unset( $value['children'][ $key_children ]['title'] );
}
}
break;
case 'component-toggle':
case 'component-accordion':
if ( $has_child ) {
foreach ( $value['children'] as $key_children => $value_children ) {
$value['children'][ $key_children ]['title_in_view'] = $this->get_view( 'toggle-children-title', $value_children );
}
}
break;
case 'settings':
if ( isset( $value['title'] ) && $value['title'] ) {
$value['title'] = isset( $value['title_in_view'] ) ? $value['title_in_view'] : $this->get_view( 'settings-children-title', $value );
}
break;
case 'html':
$value['children'] = $value['html'];
break;
case 'form':
$value['accept-charset'] = isset( $value['accept-charset'] ) ? $value['accept-charset'] : 'utf-8';
$value['action'] = isset( $value['action'] ) ? $value['action'] : '' ;
$value['autocomplete'] = isset( $value['autocomplete'] ) ? $value['autocomplete'] : 'on';
$value['enctype'] = isset( $value['enctype'] ) ? $value['enctype'] : 'application/x-www-form-urlencoded';
$value['method'] = isset( $value['method'] ) ? $value['method'] : 'post';
$value['novalidate'] = ( isset( $value['novalidate'] ) && $value['novalidate'] ) ? 'novalidate' : '';
$value['target'] = isset( $value['target'] ) ? $value['target'] : '';
break;
case 'field':
$ui_args = $value;
$ui_args['class'] = isset( $ui_args['child_class'] ) ? $ui_args['child_class'] : '' ;
if ( isset( $ui_args['options_callback'] ) ) {
$ui_args['options'] = call_user_func( $ui_args['options_callback'] );
}
unset( $ui_args['master'] );
$value['children'] = $this->ui_elements->get_ui_element_instance( $ui_args['type'], $ui_args )->render();
break;
}
if ( $has_child ) {
$value['children'] = $this->build( $value['children'] );
}
$output .= ( $value['view_wrapping'] ) ? $this->get_view( $type, $value ) : $value['children'];
}
return $output;
}
/**
* Output HTML.
*
* @since 1.0.0
* @access protected
* @param string $output Output HTML.
* @param boolean $echo Output type.
* @return string
*/
protected function output_method( $output = '', $echo = true ) {
if ( ! filter_var( $echo, FILTER_VALIDATE_BOOLEAN ) ) {
return $output;
} else {
echo $output;
}
}
/**
* Enqueue javascript and stylesheet interface builder.
*
* @since 4.0.0
* @access public
* @return void
*/
public function enqueue_assets() {
wp_enqueue_script(
'cherry-interface-builder',
esc_url( Cherry_Core::base_url( 'inc/assets/min/cherry-interface-builder.min.js', $this->module_path ) ),
array( 'jquery' ),
$this->core_version,
true
);
wp_enqueue_style(
'cherry-interface-builder',
esc_url( Cherry_Core::base_url( 'inc/assets/min/cherry-interface-builder.min.css', $this->module_path ) ),
array(),
$this->core_version,
'all'
);
}
/**
* Returns the instance.
*
* @since 1.0.0
* @access public
* @return object
*/
public static function get_instance( $core, $args ) {
// If the single instance hasn't been set, set it now.
if ( null == self::$instance ) {
self::$instance = new self( $core, $args );
}
return self::$instance;
}
}
}