Hotel Raxa - Advanced Booking System Implementation
🏨 Hotel Booking Enhancements: - Implemented Eagle Booking Advanced Pricing add-on - Added Booking.com-style rate management system - Created professional calendar interface for pricing - Integrated deals and discounts functionality 💰 Advanced Pricing Features: - Dynamic pricing models (per room, per person, per adult) - Base rates, adult rates, and child rates management - Length of stay discounts and early bird deals - Mobile rates and secret deals implementation - Seasonal promotions and flash sales 📅 Availability Management: - Real-time availability tracking - Stop sell and restriction controls - Closed to arrival/departure functionality - Minimum/maximum stay requirements - Automatic sold-out management 💳 Payment Integration: - Maintained Redsys payment gateway integration - Seamless integration with existing Eagle Booking - No modifications to core Eagle Booking plugin 🛠️ Technical Implementation: - Custom database tables for advanced pricing - WordPress hooks and filters integration - AJAX-powered admin interface - Data migration from existing Eagle Booking - Professional calendar view for revenue management 📊 Admin Interface: - Booking.com-style management dashboard - Visual rate and availability calendar - Bulk operations for date ranges - Statistics and analytics dashboard - Modal dialogs for quick editing 🔧 Code Quality: - WordPress coding standards compliance - Secure database operations with prepared statements - Proper input validation and sanitization - Error handling and logging - Responsive admin interface 🤖 Generated with Claude Code (https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework Admin Notice Class
|
||||
* Makes instantiating a Redux object an absolute piece of cake.
|
||||
*
|
||||
* @package Redux_Framework
|
||||
* @author Kevin Provance & Dovy Paukstys
|
||||
* @subpackage Core
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Admin_Notices', false ) ) {
|
||||
|
||||
/**
|
||||
* Redux Admin Notices Class
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Redux_Admin_Notices extends Redux_Class {
|
||||
|
||||
/**
|
||||
* WordPress admin notice array.
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private static $notices = array();
|
||||
|
||||
/**
|
||||
* Redux_Admin_Notices constructor.
|
||||
*
|
||||
* @param array $redux ReduxFramework object.
|
||||
* @access public
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
add_action( 'wp_ajax_redux_hide_admin_notice', array( $this, 'ajax' ) );
|
||||
add_action( 'admin_notices', array( $this, 'notices' ), 99 );
|
||||
add_action( 'admin_init', array( $this, 'dismiss' ), 9 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display notices stored in a notice array.
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function notices() {
|
||||
$this->admin_notices( self::$notices );
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses admin notice
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function dismiss() {
|
||||
$this->dismiss_admin_notice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an admin notice for display.
|
||||
*
|
||||
* @param array $data Notice data.
|
||||
*/
|
||||
public static function set_notice( array $data ) {
|
||||
$type = null;
|
||||
$msg = null;
|
||||
$id = null;
|
||||
$dismiss = null;
|
||||
|
||||
// phpcs:ignore WordPress.PHP.DontExtract
|
||||
extract( $data );
|
||||
|
||||
self::$notices[ $parent->args['page_slug'] ][] = array(
|
||||
'type' => $type,
|
||||
'msg' => $msg,
|
||||
'id' => $id . '_' . $parent->args['opt_name'],
|
||||
'dismiss' => $dismiss,
|
||||
'color' => $color ?? '#00A2E3',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates a user-dismissed option for displaying admin notices.
|
||||
*
|
||||
* @param array $notices Array of stored notices to display.
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.0
|
||||
* @access public
|
||||
*/
|
||||
public function admin_notices( array $notices = array() ) {
|
||||
global $current_user;
|
||||
|
||||
$core = $this->core();
|
||||
if ( isset( $_GET['page'] ) && $core->args['page_slug'] === $_GET['page'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
do_action( 'redux_admin_notices_run', $core->args );
|
||||
|
||||
// Check for an active admin notice array.
|
||||
if ( ! empty( $notices ) ) {
|
||||
if ( isset( $notices[ $core->args['page_slug'] ] ) ) {
|
||||
// Enum admin notices.
|
||||
foreach ( $notices[ $core->args['page_slug'] ] as $notice ) {
|
||||
|
||||
$add_style = '';
|
||||
if ( strpos( $notice['type'], 'redux-message' ) !== false ) {
|
||||
$add_style = 'style="border-left: 4px solid ' . esc_attr( $notice['color'] ) . '!important;"';
|
||||
}
|
||||
|
||||
if ( true === $notice['dismiss'] ) {
|
||||
|
||||
// Get user ID.
|
||||
$userid = $current_user->ID;
|
||||
|
||||
if ( ! get_user_meta( $userid, 'ignore_' . $notice['id'] ) ) {
|
||||
global $wp_version;
|
||||
|
||||
$css_id = '';
|
||||
|
||||
// Print the notice with the dismiss link.
|
||||
if ( version_compare( $wp_version, '4.2', '>' ) ) {
|
||||
$css_id = esc_attr( $notice['id'] );
|
||||
$css_class = esc_attr( $notice['type'] ) . ' redux-notice notice is-dismissible redux-notice';
|
||||
|
||||
$nonce = wp_create_nonce( $notice['id'] . $userid . 'nonce' );
|
||||
|
||||
echo '<div ' . $add_style . ' id="' . esc_attr( $css_id ) . '" class="' . esc_attr( $css_class ) . '">'; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
echo '<input type="hidden" class="dismiss_data" id="' . esc_attr( $css_id ) . '" value="' . esc_attr( $nonce ) . '">';
|
||||
echo '<p>' . wp_kses_post( $notice['msg'] ) . '</p>';
|
||||
echo '</div>';
|
||||
} else {
|
||||
echo '<div ' . esc_html( $add_style ) . ' class="' . esc_attr( $notice['type'] ) . ' notice is-dismissable"><p>' . wp_kses_post( $notice['msg'] ) . ' <a href="?dismiss=true&id=' . esc_attr( $css_id ) . '">' . esc_html__( 'Dismiss', 'redux-framework' ) . '</a>.</p></div>';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Standard notice.
|
||||
echo '<div ' . esc_html( $add_style ) . ' class="' . esc_attr( $notice['type'] ) . ' notice"><p>' . wp_kses_post( $notice['msg'] ) . '</a>.</p></div>';
|
||||
}
|
||||
?>
|
||||
<script>
|
||||
jQuery( document ).ready( function( $ ) {
|
||||
$( document.body ).on(
|
||||
'click', '.redux-notice.is-dismissible .notice-dismiss', function( e ) {
|
||||
e.preventDefault();
|
||||
var $data = $( this ).parent().find( '.dismiss_data' );
|
||||
$.post(
|
||||
ajaxurl, {
|
||||
action: 'redux_hide_admin_notice',
|
||||
id: $data.attr( 'id' ),
|
||||
nonce: $data.val()
|
||||
}
|
||||
);
|
||||
} );
|
||||
} );
|
||||
</script>
|
||||
<?php
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clear the admin notice array.
|
||||
self::$notices[ $core->args['opt_name'] ] = array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user meta to store dismiss notice preference.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function dismiss_admin_notice() {
|
||||
global $current_user;
|
||||
|
||||
// Verify the dismissed notice and id parameters are present.
|
||||
if ( isset( $_GET['dismiss'] ) && isset( $_GET['id'] ) ) {
|
||||
if ( isset( $_GET['nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_GET['nonce'] ) ), 'redux_hint_toggle' ) ) {
|
||||
if ( 'true' === $_GET['dismiss'] || 'false' === $_GET['dismiss'] ) {
|
||||
|
||||
// Get the user id.
|
||||
$userid = $current_user->ID;
|
||||
|
||||
// Get the notice id.
|
||||
$id = sanitize_text_field( wp_unslash( $_GET['id'] ) );
|
||||
$val = sanitize_text_field( wp_unslash( $_GET['dismiss'] ) );
|
||||
|
||||
// Add the dismissed request to the user meta.
|
||||
update_user_meta( $userid, 'ignore_' . $id, $val );
|
||||
}
|
||||
} else {
|
||||
wp_nonce_ays( 'redux_hint_toggle' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user meta to store dismiss notice preference
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajax() {
|
||||
global $current_user;
|
||||
|
||||
if ( isset( $_POST['id'] ) ) {
|
||||
// Get the notice id.
|
||||
$id = explode( '&', sanitize_text_field( wp_unslash( $_POST['id'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$id = $id[0];
|
||||
|
||||
// Get the user id.
|
||||
$userid = $current_user->ID;
|
||||
|
||||
if ( ! isset( $_POST['nonce'] ) || ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), $id . $userid . 'nonce' ) ) ) {
|
||||
die( 0 );
|
||||
} else {
|
||||
// Add the dismissed request to the user meta.
|
||||
update_user_meta( $userid, 'ignore_' . $id, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux AJAX Save Class
|
||||
*
|
||||
* @class Redux_Core
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpConditionCheckedByNextConditionInspection
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_AJAX_Save', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_AJAX_Save
|
||||
*/
|
||||
class Redux_AJAX_Save extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_AJAX_Save constructor.
|
||||
* array_merge_recursive_distinct
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
add_action( 'wp_ajax_' . $this->args['opt_name'] . '_ajax_save', array( $this, 'save' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback to save the option panel values.
|
||||
*
|
||||
* @throws ReflectionException Exception.
|
||||
*/
|
||||
public function save() {
|
||||
$redux = null;
|
||||
|
||||
$core = $this->core();
|
||||
|
||||
if ( ! isset( $_REQUEST['nonce'] ) || ( ! wp_verify_nonce( sanitize_key( wp_unslash( $_REQUEST['nonce'] ) ), 'redux_ajax_nonce' . $this->args['opt_name'] ) ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'status' => esc_html__( 'Invalid security credential. Please reload the page and try again.', 'redux-framework' ),
|
||||
'action' => '',
|
||||
)
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! Redux_Helpers::current_user_can( $core->args['page_permissions'] ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'status' => esc_html__( 'Invalid user capability. Please reload the page and try again.', 'redux-framework' ),
|
||||
'action' => '',
|
||||
)
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
if ( isset( $_POST['opt_name'] ) && ! empty( $_POST['opt_name'] ) && isset( $_POST['data'] ) && ! empty( $_POST['data'] ) ) {
|
||||
$redux = Redux::instance( sanitize_text_field( wp_unslash( $_POST['opt_name'] ) ) );
|
||||
|
||||
if ( ! empty( $redux->args['opt_name'] ) ) {
|
||||
|
||||
$post_data = wp_unslash( $_POST['data'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
||||
|
||||
// New method to avoid input_var nonsense. Thanks, @harunbasic.
|
||||
$values = Redux_Functions_Ex::parse_str( $post_data );
|
||||
$values = $values[ $redux->args['opt_name'] ];
|
||||
|
||||
if ( ! empty( $values ) ) {
|
||||
try {
|
||||
if ( isset( $redux->validation_ran ) ) {
|
||||
unset( $redux->validation_ran );
|
||||
}
|
||||
|
||||
$redux->options_class->set( $redux->options_class->validate_options( $values ) );
|
||||
|
||||
$do_reload = false;
|
||||
if ( isset( $core->required_class->reload_fields ) && ! empty( $core->required_class->reload_fields ) ) {
|
||||
if ( ! empty( $core->transients['changed_values'] ) ) {
|
||||
foreach ( $core->required_class->reload_fields as $val ) {
|
||||
if ( array_key_exists( $val, $core->transients['changed_values'] ) ) {
|
||||
$do_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $do_reload || ( isset( $values['defaults'] ) && ! empty( $values['defaults'] ) ) || ( isset( $values['defaults-section'] ) && ! empty( $values['defaults-section'] ) ) || ( isset( $values['import_code'] ) && ! empty( $values['import_code'] ) ) || ( isset( $values['import_link'] ) && ! empty( $values['import_link'] ) ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'status' => 'success',
|
||||
'action' => 'reload',
|
||||
)
|
||||
);
|
||||
die();
|
||||
}
|
||||
|
||||
$redux->enqueue_class->get_warnings_and_errors_array();
|
||||
|
||||
$return_array = array(
|
||||
'status' => 'success',
|
||||
'options' => $redux->options,
|
||||
'errors' => $redux->enqueue_class->localize_data['errors'] ?? null,
|
||||
'warnings' => $redux->enqueue_class->localize_data['warnings'] ?? null,
|
||||
'sanitize' => $redux->enqueue_class->localize_data['sanitize'] ?? null,
|
||||
);
|
||||
} catch ( Exception $e ) {
|
||||
$return_array = array( 'status' => $e->getMessage() );
|
||||
}
|
||||
} else {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'status' => esc_html__( 'Your panel has no fields. Nothing to save.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $core->transients['run_compiler'] ) && $core->transients['run_compiler'] ) {
|
||||
$core->no_output = true;
|
||||
$temp = $core->args['output_variables_prefix'];
|
||||
|
||||
// Allow the override of variable's prefix for use by SCSS or LESS.
|
||||
if ( isset( $core->args['compiler_output_variables_prefix'] ) ) {
|
||||
$core->args['output_variables_prefix'] = $core->args['compiler_output_variables_prefix'];
|
||||
}
|
||||
|
||||
$core->output_class->enqueue();
|
||||
$core->args['output_variables_prefix'] = $temp;
|
||||
|
||||
try {
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
||||
$compiler_css = $core->compilerCSS; // Backward compatibility variable.
|
||||
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/compiler'
|
||||
*
|
||||
* @param array $options Global options.
|
||||
* @param string $css CSS that get sent to the compiler hook.
|
||||
* @param array $changed_values Changed option values.
|
||||
* @param array $output_variables Output variables.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/options/' . $core->args['opt_name'] . '/compiler', $core->options, $compiler_css, $core->transients['changed_values'], $core->output_variables );
|
||||
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/compiler/advanced'
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/options/' . $core->args['opt_name'] . '/compiler/advanced', $core );
|
||||
} catch ( Exception $e ) {
|
||||
$return_array = array( 'status' => $e->getMessage() );
|
||||
}
|
||||
|
||||
unset( $core->transients['run_compiler'] );
|
||||
$core->transient_class->set();
|
||||
}
|
||||
|
||||
if ( isset( $return_array ) ) {
|
||||
if ( 'success' === $return_array['status'] ) {
|
||||
$panel = new Redux_Panel( $redux );
|
||||
ob_start();
|
||||
$panel->notification_bar();
|
||||
$notification_bar = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$return_array['notification_bar'] = $notification_bar;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo wp_json_encode( apply_filters( 'redux/options/' . $core->args['opt_name'] . '/ajax_save/response', $return_array ) );
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Select2 AJAX Class
|
||||
*
|
||||
* @class Redux_AJAX_Select2
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpConditionCheckedByNextConditionInspection
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_AJAX_Select2', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_AJAX_Select2
|
||||
*/
|
||||
class Redux_AJAX_Select2 extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_AJAX_Select2 constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework object pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
add_action( "wp_ajax_redux_{$redux->args['opt_name']}_select2", array( $this, 'ajax' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback for select2 match search.
|
||||
*/
|
||||
public function ajax() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( isset( $_REQUEST['nonce'] ) && isset( $_REQUEST['action'] ) ) {
|
||||
if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ), sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ) ) ) {
|
||||
wp_send_json_error( esc_html__( 'Invalid security credential. Please reload the page and try again.', 'redux-framework' ) );
|
||||
}
|
||||
|
||||
if ( ! Redux_Helpers::current_user_can( $this->parent->args['page_permissions'] ) ) {
|
||||
wp_send_json_error( esc_html__( 'Invalid user capability. Please reload the page and try again.', 'redux-framework' ) );
|
||||
}
|
||||
|
||||
if ( isset( $_REQUEST['data'] ) ) {
|
||||
|
||||
$args = isset( $_REQUEST['data_args'] ) ? json_decode( sanitize_text_field( wp_unslash( $_REQUEST['data_args'] ) ), true ) : array();
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
's' => isset( $_REQUEST['q'] ) && ! empty( $_REQUEST['q'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['q'] ) ) : '',
|
||||
)
|
||||
);
|
||||
|
||||
if ( isset( $_REQUEST['q'] ) && ! empty( $_REQUEST['q'] ) ) {
|
||||
$criteria = sanitize_text_field( wp_unslash( $_REQUEST['q'] ) );
|
||||
$args['s'] = $criteria;
|
||||
}
|
||||
|
||||
$return = $core->wordpress_data->get( sanitize_text_field( wp_unslash( $_REQUEST['data'] ) ), $args );
|
||||
|
||||
if ( is_array( $return ) && ! empty( $_REQUEST['action'] ) ) {
|
||||
if ( ! empty( $args['s'] ) ) {
|
||||
$keys = array_keys( $return );
|
||||
$values = array_values( $return );
|
||||
|
||||
$to_json = array();
|
||||
|
||||
// Search all the values.
|
||||
$search_values = preg_grep( '~' . $args['s'] . '~i', $values );
|
||||
if ( ! empty( $search_values ) ) {
|
||||
foreach ( $search_values as $id => $val ) {
|
||||
$to_json[ $keys[ $id ] ] = array(
|
||||
'id' => $keys[ $id ],
|
||||
'text' => $val,
|
||||
);
|
||||
}
|
||||
}
|
||||
// Search all the keys.
|
||||
$search_keys = preg_grep( '~' . $args['s'] . '~i', $keys );
|
||||
if ( ! empty( $search_keys ) ) {
|
||||
foreach ( $search_keys as $id => $val ) {
|
||||
$to_json[ $val ] = array(
|
||||
'id' => $val,
|
||||
'text' => $values[ $id ],
|
||||
);
|
||||
}
|
||||
}
|
||||
wp_send_json_success( array_values( $to_json ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Typography AJAX Class
|
||||
*
|
||||
* @class Redux_Core
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_AJAX_Typography', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_AJAX_Typography
|
||||
*/
|
||||
class Redux_AJAX_Typography extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_AJAX_Typography constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
add_action( 'wp_ajax_redux_update_google_fonts', array( $this, 'google_fonts_update' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Google font AJAX callback
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function google_fonts_update() {
|
||||
$field_class = 'Redux_typography';
|
||||
|
||||
if ( ! class_exists( $field_class ) ) {
|
||||
$dir = str_replace( '/classes', '', Redux_Functions_Ex::wp_normalize_path( __DIR__ ) );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$class_file = apply_filters( 'redux-typeclass-load', $dir . '/fields/typography/class-redux-typography.php', $field_class );
|
||||
if ( $class_file ) {
|
||||
require_once $class_file;
|
||||
}
|
||||
}
|
||||
|
||||
if ( class_exists( $field_class ) && method_exists( $field_class, 'google_fonts_update_ajax' ) ) {
|
||||
$f = new $field_class( array(), '', $this->parent );
|
||||
|
||||
$f->google_fonts_update_ajax();
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,401 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework Args Class
|
||||
*
|
||||
* @package Redux_Framework/Classes
|
||||
* @noinspection PhpConditionCheckedByNextConditionInspection
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Args', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Args
|
||||
*/
|
||||
class Redux_Args {
|
||||
|
||||
/**
|
||||
* Returns entire arguments array.
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
public $get = array();
|
||||
|
||||
/**
|
||||
* ReduxFramework object.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $parent;
|
||||
|
||||
/**
|
||||
* Switch to omit social icons if dev_mode is set to true and Redux defaults are used.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $omit_icons = false;
|
||||
|
||||
/**
|
||||
* Switch to omit support menu items if dev_mode is set to true and redux defaults are used.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $omit_items = false;
|
||||
|
||||
/**
|
||||
* Flag to force dev_mod to true if in localhost or WP_DEBUG is set to true.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $dev_mode_forced = false;
|
||||
|
||||
/**
|
||||
* Redux_Args constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
* @param array $args Global arguments array.
|
||||
*/
|
||||
public function __construct( $redux, array $args ) {
|
||||
$this->parent = $redux;
|
||||
|
||||
$default = array(
|
||||
'opt_name' => '',
|
||||
'last_tab' => '',
|
||||
'menu_icon' => '',
|
||||
'menu_title' => '',
|
||||
'page_title' => '',
|
||||
'page_slug' => '',
|
||||
'page_permissions' => 'manage_options',
|
||||
'menu_type' => 'menu',
|
||||
'page_parent' => 'themes.php',
|
||||
'page_priority' => null,
|
||||
'allow_sub_menu' => true,
|
||||
'save_defaults' => true,
|
||||
'footer_credit' => '',
|
||||
'async_typography' => false,
|
||||
'disable_google_fonts_link' => false,
|
||||
'class' => '',
|
||||
'admin_bar' => true,
|
||||
'admin_bar_priority' => 999,
|
||||
'admin_bar_icon' => '',
|
||||
'help_tabs' => array(),
|
||||
'help_sidebar' => '',
|
||||
'database' => '',
|
||||
'customizer' => false,
|
||||
'global_variable' => '',
|
||||
'output' => true,
|
||||
'output_variables_prefix' => '--',
|
||||
'compiler_output_variables_prefix' => '$',
|
||||
'compiler' => true,
|
||||
'output_tag' => true,
|
||||
'output_location' => array( 'frontend' ),
|
||||
'transient_time' => '',
|
||||
'default_show' => false,
|
||||
'default_mark' => '',
|
||||
'disable_save_warn' => false,
|
||||
'open_expanded' => false,
|
||||
'hide_expand' => false,
|
||||
'network_admin' => false,
|
||||
'network_sites' => true,
|
||||
'hide_reset' => false,
|
||||
'hide_save' => false,
|
||||
'hints' => array(
|
||||
'icon' => 'el el-question-sign',
|
||||
'icon_position' => 'right',
|
||||
'icon_color' => 'lightgray',
|
||||
'icon_size' => 'normal',
|
||||
'tip_style' => array(
|
||||
'color' => 'light',
|
||||
'shadow' => true,
|
||||
'rounded' => false,
|
||||
'style' => '',
|
||||
),
|
||||
'tip_position' => array(
|
||||
'my' => 'top_left',
|
||||
'at' => 'bottom_right',
|
||||
),
|
||||
'tip_effect' => array(
|
||||
'show' => array(
|
||||
'effect' => 'slide',
|
||||
'duration' => '500',
|
||||
'event' => 'mouseover',
|
||||
),
|
||||
'hide' => array(
|
||||
'effect' => 'fade',
|
||||
'duration' => '500',
|
||||
'event' => 'click mouseleave',
|
||||
),
|
||||
),
|
||||
),
|
||||
'font_weights' => array(
|
||||
array(
|
||||
'id' => '400',
|
||||
'name' => __( 'Regular 400', 'redux-framework' ),
|
||||
),
|
||||
array(
|
||||
'id' => '400italic',
|
||||
'name' => __( 'Regular 400 Italic', 'redux-framework' ),
|
||||
),
|
||||
array(
|
||||
'id' => '700',
|
||||
'name' => __( 'Bold 700', 'redux-framework' ),
|
||||
),
|
||||
array(
|
||||
'id' => '700italic',
|
||||
'name' => __( 'Bold 700 Italic', 'redux-framework' ),
|
||||
),
|
||||
),
|
||||
'show_import_export' => true,
|
||||
'show_options_object' => true,
|
||||
'dev_mode' => true,
|
||||
'templates_path' => '',
|
||||
'ajax_save' => true,
|
||||
'use_cdn' => true,
|
||||
'cdn_check_time' => 1440,
|
||||
'options_api' => true,
|
||||
'allow_tracking' => true,
|
||||
'admin_theme' => 'wp',
|
||||
'elusive_frontend' => false,
|
||||
'fontawesome_frontend' => false,
|
||||
'flyout_submenus' => true,
|
||||
'font_display' => 'swap', // block|swap|fallback|optional.
|
||||
'load_on_cron' => false,
|
||||
'search' => false,
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$default = apply_filters( 'redux/pro/args/defaults', $default );
|
||||
|
||||
$args = Redux_Functions::parse_args( $args, $default );
|
||||
|
||||
$args = $this->args( $args );
|
||||
|
||||
$args = $this->default_cleanup( $args );
|
||||
|
||||
if ( ! in_array( $args['font_display'], array( 'block', 'swap', 'fallback', 'optional' ), true ) ) {
|
||||
$args['font_display'] = 'swap';
|
||||
}
|
||||
|
||||
if ( isset( $args['async_typography'] ) && $args['async_typography'] ) {
|
||||
$args['async_typography'] = false;
|
||||
}
|
||||
|
||||
$this->get = $args;
|
||||
|
||||
$this->parent->args = $args;
|
||||
|
||||
if ( 'redux_extensions_demo' !== $args['opt_name'] && 'redux_demo' !== $args['opt_name'] ) {
|
||||
$this->change_demo_defaults( $args );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds and sanitizes a global args array.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function args( array $args ): array {
|
||||
$args = $this->no_errors_please( $args );
|
||||
|
||||
$this->parent->old_opt_name = $args['opt_name'];
|
||||
|
||||
$args = $this->filters( $args );
|
||||
|
||||
if ( ! function_exists( 'wp_rand' ) ) {
|
||||
require_once ABSPATH . '/wp-includes/pluggable.php';
|
||||
}
|
||||
|
||||
if ( $args['opt_name'] === $this->parent->old_opt_name ) {
|
||||
$this->parent->old_opt_name = null;
|
||||
unset( $this->parent->old_opt_name );
|
||||
}
|
||||
|
||||
// Do not save the defaults if we're on a live preview!
|
||||
if ( 'customize' === $GLOBALS['pagenow'] && isset( $_GET['customize_theme'] ) && ! empty( $_GET['customize_theme'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$args['save_defaults'] = false;
|
||||
}
|
||||
|
||||
return $this->shim( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply filters to arg data.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*
|
||||
* @return mixed|void
|
||||
*/
|
||||
private function filters( array $args ) {
|
||||
/**
|
||||
* Filter 'redux/args/{opt_name}'
|
||||
*
|
||||
* @param array $args ReduxFramework configuration
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$args = apply_filters( "redux/args/{$args['opt_name']}", $args );
|
||||
|
||||
/**
|
||||
* Filter 'redux/options/{opt_name}/args'
|
||||
*
|
||||
* @param array $args ReduxFramework configuration
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
return apply_filters( "redux/options/{$args['opt_name']}/args", $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize args that should not be empty.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function no_errors_please( array $args ): array {
|
||||
if ( empty( $args['transient_time'] ) ) {
|
||||
$args['transient_time'] = 60 * MINUTE_IN_SECONDS;
|
||||
}
|
||||
|
||||
if ( empty( $args['footer_credit'] ) ) {
|
||||
|
||||
$footer_text = sprintf(
|
||||
/* translators: 1: Redux, 2: Link to plugin review */
|
||||
__( 'Enjoyed %1$s? Please leave us a %2$s rating. We really appreciate your support!', 'redux-framework' ),
|
||||
'<strong>' . __( 'Redux', 'redux-framework' ) . '</strong>',
|
||||
'<a href="https://wordpress.org/support/plugin/redux-framework/reviews/?filter=5/#new-post" target="_blank">★★★★★</a>'
|
||||
);
|
||||
$args['footer_credit'] = '<span id="footer-thankyou">' . $footer_text . '</span>';
|
||||
}
|
||||
|
||||
if ( empty( $args['menu_title'] ) ) {
|
||||
$args['menu_title'] = esc_html__( 'Options', 'redux-framework' );
|
||||
}
|
||||
|
||||
if ( empty( $args['page_title'] ) ) {
|
||||
$args['page_title'] = esc_html__( 'Options', 'redux-framework' );
|
||||
}
|
||||
|
||||
// Auto creates the page_slug appropriately.
|
||||
if ( empty( $args['page_slug'] ) ) {
|
||||
if ( ! empty( $args['display_name'] ) ) {
|
||||
$args['page_slug'] = sanitize_html_class( $args['display_name'] );
|
||||
} elseif ( ! empty( $args['page_title'] ) ) {
|
||||
$args['page_slug'] = sanitize_html_class( $args['page_title'] );
|
||||
} elseif ( ! empty( $args['menu_title'] ) ) {
|
||||
$args['page_slug'] = sanitize_html_class( $args['menu_title'] );
|
||||
} else {
|
||||
$args['page_slug'] = str_replace( '-', '_', $args['opt_name'] );
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shims for much older v3 configs.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function shim( array $args ): array {
|
||||
/**
|
||||
* SHIM SECTION
|
||||
* Old variables and ways of doing things that need correcting. ;)
|
||||
* */
|
||||
// Variable name change.
|
||||
if ( ! empty( $args['page_cap'] ) ) {
|
||||
$args['page_permissions'] = $args['page_cap'];
|
||||
unset( $args['page_cap'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['page_position'] ) ) {
|
||||
$args['page_priority'] = $args['page_position'];
|
||||
unset( $args['page_position'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $args['page_type'] ) ) {
|
||||
$args['menu_type'] = $args['page_type'];
|
||||
unset( $args['page_type'] );
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify to see if dev has bothered to change admin bar links and share icons from demo data to their own.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*/
|
||||
private function change_demo_defaults( array $args ) {
|
||||
if ( $args['dev_mode'] || true === Redux_Helpers::is_local_host() ) {
|
||||
if ( ! empty( $args['admin_bar_links'] ) ) {
|
||||
foreach ( $args['admin_bar_links'] as $arr ) {
|
||||
if ( is_array( $arr ) && ! empty( $arr ) ) {
|
||||
foreach ( $arr as $y ) {
|
||||
if ( strpos( Redux_Core::strtolower( $y ), 'redux' ) !== false ) {
|
||||
$this->omit_items = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $args['share_icons'] ) ) {
|
||||
foreach ( $args['share_icons'] as $arr ) {
|
||||
if ( is_array( $arr ) && ! empty( $arr ) ) {
|
||||
foreach ( $arr as $y ) {
|
||||
if ( strpos( Redux_Core::strtolower( $y ), 'redux' ) !== false ) {
|
||||
$this->omit_icons = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fix other arg criteria that sometimes gets hosed up.
|
||||
*
|
||||
* @param array $args Global args.
|
||||
*
|
||||
* @return array
|
||||
* @noinspection PhpStrictComparisonWithOperandsOfDifferentTypesInspection
|
||||
*/
|
||||
private function default_cleanup( array $args ): array {
|
||||
|
||||
// Fix the global variable name.
|
||||
if ( '' === $args['global_variable'] && false !== $args['global_variable'] ) {
|
||||
$args['global_variable'] = str_replace( '-', '_', $args['opt_name'] );
|
||||
}
|
||||
|
||||
if ( isset( $args['customizer_only'] ) && $args['customizer_only'] ) {
|
||||
$args['menu_type'] = 'hidden';
|
||||
$args['customizer'] = true;
|
||||
$args['admin_bar'] = false;
|
||||
$args['allow_sub_menu'] = false;
|
||||
}
|
||||
|
||||
// Check if the Airplane Mode plugin is installed.
|
||||
if ( class_exists( 'Airplane_Mode_Core' ) ) {
|
||||
$airplane = Airplane_Mode_Core::getInstance();
|
||||
if ( method_exists( $airplane, 'enabled' ) ) {
|
||||
if ( $airplane->enabled() ) {
|
||||
$args['use_cdn'] = false;
|
||||
}
|
||||
} elseif ( 'on' === $airplane->check_status() ) {
|
||||
$args['use_cdn'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Register an autoloader for custom mu-plugins.
|
||||
*
|
||||
* @package redux-framework
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class Autoloader
|
||||
*
|
||||
* @package altis/core
|
||||
*/
|
||||
class Redux_Autoloader {
|
||||
const NS_SEPARATOR = '\\';
|
||||
|
||||
/**
|
||||
* Prefix to validate against.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $prefix;
|
||||
|
||||
/**
|
||||
* String length of the prefix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $prefix_length;
|
||||
|
||||
/**
|
||||
* Path to validate.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $path;
|
||||
|
||||
/**
|
||||
* Autoloader constructor.
|
||||
*
|
||||
* @param string $prefix Prefix to validate against.
|
||||
* @param string $path Path to validate.
|
||||
*/
|
||||
public function __construct( string $prefix, string $path ) {
|
||||
$this->prefix = $prefix;
|
||||
$this->prefix_length = strlen( $prefix );
|
||||
$this->path = trailingslashit( $path );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a class file if it matches our criteria.
|
||||
*
|
||||
* @param string $classname Class to test and/or load.
|
||||
*/
|
||||
public function load( string $classname ) {
|
||||
if ( strpos( $classname, 'Redux' ) === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Strip prefix from the start (ala PSR-4).
|
||||
$classname = substr( $classname, $this->prefix_length + 1 );
|
||||
if ( function_exists( 'mb_strtolower' ) && function_exists( 'mb_detect_encoding' ) ) {
|
||||
$classname = mb_strtolower( $classname, mb_detect_encoding( $classname ) );
|
||||
} else {
|
||||
$classname = strtolower( $classname );
|
||||
}
|
||||
|
||||
$file = '';
|
||||
// Split on namespace separator.
|
||||
$last_ns_pos = strripos( $classname, self::NS_SEPARATOR );
|
||||
if ( false !== $last_ns_pos ) {
|
||||
$namespace = substr( $classname, 0, $last_ns_pos );
|
||||
$classname = substr( $classname, $last_ns_pos + 1 );
|
||||
$file = str_replace( self::NS_SEPARATOR, DIRECTORY_SEPARATOR, $namespace ) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
$file_prefix = $file;
|
||||
$file = $file_prefix . 'class-' . str_replace( '_', '-', $classname ) . '.php';
|
||||
|
||||
$path = $this->path . $file;
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
require_once $path;
|
||||
} else {
|
||||
$file = $file_prefix . 'class-redux-' . str_replace( '_', '-', $classname ) . '.php';
|
||||
$path = $this->path . $file;
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
require_once $path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework CDN Container Class
|
||||
*
|
||||
* @author Kevin Provance (kprovance)
|
||||
* @package Redux_Framework/Classes
|
||||
* @noinspection PhpIgnoredClassAliasDeclaration
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_CDN', false ) ) {
|
||||
/**
|
||||
* Class Redux_CDN
|
||||
*/
|
||||
class Redux_CDN {
|
||||
|
||||
/**
|
||||
* Pointer to ReduxFramework object.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public static $parent;
|
||||
|
||||
/**
|
||||
* Flag to check for set status.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private static $set;
|
||||
|
||||
/**
|
||||
* Check for enqueued status of style/script.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $mode Mode to check.
|
||||
* @param bool $is_script Flag for scrip/style.
|
||||
*
|
||||
* @return bool
|
||||
* @noinspection PhpSameParameterValueInspection
|
||||
*/
|
||||
private static function is_enqueued( string $handle, string $mode = 'enqueued', bool $is_script = true ): bool {
|
||||
if ( $is_script ) {
|
||||
return wp_script_is( $handle, $mode );
|
||||
} else {
|
||||
return wp_style_is( $handle, $mode );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register script/style.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param mixed $footer_or_media True or 'all'.
|
||||
* @param bool $is_script Script or style.
|
||||
*/
|
||||
private static function register( string $handle, string $src_cdn, array $deps, string $ver, $footer_or_media, bool $is_script = true ) {
|
||||
if ( $is_script ) {
|
||||
wp_register_script( $handle, $src_cdn, $deps, $ver, $footer_or_media );
|
||||
} else {
|
||||
wp_register_style( $handle, $src_cdn, $deps, $ver, $footer_or_media );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue script or style.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string|null $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param mixed $footer_or_media True or 'all'.
|
||||
* @param bool $is_script Script or style.
|
||||
*/
|
||||
private static function enqueue( string $handle, ?string $src_cdn, array $deps, string $ver, $footer_or_media, bool $is_script = true ) {
|
||||
if ( $is_script ) {
|
||||
wp_enqueue_script( $handle, $src_cdn, $deps, $ver, $footer_or_media );
|
||||
} else {
|
||||
wp_enqueue_style( $handle, $src_cdn, $deps, $ver, $footer_or_media );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue/Register CDN
|
||||
*
|
||||
* @param bool $register Register or enqueue.
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param mixed $footer_or_media True or 'all'.
|
||||
* @param bool $is_script Script or style.
|
||||
*/
|
||||
private static function cdn( bool $register, string $handle, string $src_cdn, array $deps, string $ver, $footer_or_media, bool $is_script ) {
|
||||
$tran_key = '_style_cdn_is_up';
|
||||
if ( $is_script ) {
|
||||
$tran_key = '_script_cdn_is_up';
|
||||
}
|
||||
|
||||
$cdn_is_up = get_transient( $handle . $tran_key );
|
||||
if ( $cdn_is_up ) {
|
||||
if ( $register ) {
|
||||
self::register( $handle, $src_cdn, $deps, $ver, $footer_or_media, $is_script );
|
||||
} else {
|
||||
self::enqueue( $handle, $src_cdn, $deps, $ver, $footer_or_media, $is_script );
|
||||
}
|
||||
} else {
|
||||
|
||||
$prefix = '/' === $src_cdn[1] ? 'http:' : '';
|
||||
|
||||
// phpcs:ignore WordPress.PHP.NoSilencedErrors
|
||||
$cdn_response = @wp_remote_get( $prefix . $src_cdn );
|
||||
|
||||
if ( is_wp_error( $cdn_response ) || 200 !== wp_remote_retrieve_response_code( $cdn_response ) ) {
|
||||
if ( class_exists( 'Redux_Vendor_URL' ) || class_exists( 'Redux_VendorURL' ) ) {
|
||||
if ( class_exists( 'Redux_Vendor_URL' ) ) {
|
||||
$src = Redux_Vendor_URL::get_url( $handle );
|
||||
} else {
|
||||
$src = Redux_VendorURL::get_url( $handle );
|
||||
}
|
||||
|
||||
if ( $register ) {
|
||||
self::register( $handle, $src, $deps, $ver, $footer_or_media, $is_script );
|
||||
} else {
|
||||
self::enqueue( $handle, $src, $deps, $ver, $footer_or_media, $is_script );
|
||||
}
|
||||
} elseif ( ! self::is_enqueued( $handle, 'enqueued', $is_script ) ) {
|
||||
$msg = esc_html__( 'Please wait a few minutes, then try refreshing the page. Unable to load some remotely hosted scripts.', 'redux-framework' );
|
||||
if ( self::$parent->args['dev_mode'] ) {
|
||||
// translators: %s: URL.
|
||||
$msg = sprintf( esc_html__( 'If you are developing offline, please download and install the %s plugin/extension to bypass our CDN and avoid this warning', 'redux-framework' ), '<a href="https://github.com/reduxframework/redux-vendor-support" target="_blank">Redux Vendor Support</a>' );
|
||||
}
|
||||
|
||||
// translators: %s: CDN handle.
|
||||
$msg = '<strong>' . esc_html__( 'Redux Framework Warning', 'redux-framework' ) . '</strong><br/>' . sprintf( esc_html__( '%s CDN unavailable. Some controls may not render properly.', 'redux-framework' ), $handle ) . ' ' . $msg;
|
||||
|
||||
$data = array(
|
||||
'parent' => self::$parent,
|
||||
'type' => 'error',
|
||||
'msg' => $msg,
|
||||
'id' => $handle . $tran_key,
|
||||
'dismiss' => false,
|
||||
);
|
||||
|
||||
Redux_Admin_Notices::set_notice( $data );
|
||||
}
|
||||
} else {
|
||||
set_transient( $handle . $tran_key, true, MINUTE_IN_SECONDS * self::$parent->args['cdn_check_time'] );
|
||||
|
||||
if ( $register ) {
|
||||
self::register( $handle, $src_cdn, $deps, $ver, $footer_or_media, $is_script );
|
||||
} else {
|
||||
self::enqueue( $handle, $src_cdn, $deps, $ver, $footer_or_media, $is_script );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register/enqueue file from vendor library.
|
||||
*
|
||||
* @param bool $register Register or enqueue.
|
||||
* @param string $handle File handle.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param mixed $footer_or_media True or 'all'.
|
||||
* @param bool $is_script Script or style.
|
||||
*/
|
||||
private static function vendor_plugin( bool $register, string $handle, array $deps, string $ver, $footer_or_media, bool $is_script ) {
|
||||
if ( class_exists( 'Redux_Vendor_URL' ) || class_exists( 'Redux_VendorURL' ) ) {
|
||||
if ( class_exists( 'Redux_Vendor_URL' ) ) {
|
||||
$src = Redux_Vendor_URL::get_url( $handle );
|
||||
} else {
|
||||
$src = Redux_VendorURL::get_url( $handle );
|
||||
}
|
||||
|
||||
if ( $register ) {
|
||||
self::register( $handle, $src, $deps, $ver, $footer_or_media, $is_script );
|
||||
} else {
|
||||
self::enqueue( $handle, $src, $deps, $ver, $footer_or_media, $is_script );
|
||||
}
|
||||
} elseif ( ! self::$set ) {
|
||||
// translators: %s: Vendor support URL. %s: Admin plugins page.
|
||||
$msg = sprintf( esc_html__( 'The %1$s (or extension) is either not installed or not activated and thus, some controls may not render properly. Please ensure that it is installed and %2$s', 'redux-framework' ), '<a href="https://github.com/reduxframework/redux-vendor-support">Vendor Support plugin</a>', '<a href="' . admin_url( 'plugins.php' ) . '">' . esc_html__( 'activated.', 'redux-framework' ) . '</a>' );
|
||||
|
||||
$data = array(
|
||||
'parent' => self::$parent,
|
||||
'type' => 'error',
|
||||
'msg' => $msg,
|
||||
'id' => $handle,
|
||||
'dismiss' => false,
|
||||
);
|
||||
|
||||
Redux_Admin_Notices::set_notice( $data );
|
||||
|
||||
self::$set = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register style CDN or local.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param string $media True or 'all'.
|
||||
*/
|
||||
public static function register_style( string $handle, string $src_cdn, array $deps = array(), string $ver = '', string $media = 'all' ) {
|
||||
if ( empty( self::$parent ) || self::$parent->args['use_cdn'] ) {
|
||||
self::cdn( true, $handle, $src_cdn, $deps, $ver, $media, false );
|
||||
} else {
|
||||
self::vendor_plugin( true, $handle, $deps, $ver, $media, false );
|
||||
}
|
||||
}
|
||||
|
||||
/** Register script CDN or local.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param bool $in_footer Script in footer.
|
||||
*/
|
||||
public static function register_script( string $handle, string $src_cdn, array $deps = array(), string $ver = '', bool $in_footer = false ) {
|
||||
if ( empty( self::$parent ) || self::$parent->args['use_cdn'] ) {
|
||||
self::cdn( true, $handle, $src_cdn, $deps, $ver, $in_footer, true );
|
||||
} else {
|
||||
self::vendor_plugin( true, $handle, $deps, $ver, $in_footer, true );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue style CDN or local.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File deps.
|
||||
* @param string $ver File version.
|
||||
* @param string $media Media type.
|
||||
*/
|
||||
public static function enqueue_style( string $handle, string $src_cdn, array $deps = array(), string $ver = '', string $media = 'all' ) {
|
||||
if ( self::$parent->args['use_cdn'] ) {
|
||||
self::cdn( false, $handle, $src_cdn, $deps, $ver, $media, false );
|
||||
} else {
|
||||
self::vendor_plugin( false, $handle, $deps, $ver, $media, false );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue script CDN or local.
|
||||
*
|
||||
* @param string $handle File handle.
|
||||
* @param string $src_cdn CDN source.
|
||||
* @param array $deps File seps.
|
||||
* @param string $ver File version.
|
||||
* @param bool $in_footer Script in footer.
|
||||
*/
|
||||
public static function enqueue_script( string $handle, string $src_cdn, array $deps = array(), string $ver = '', bool $in_footer = false ) {
|
||||
if ( self::$parent->args['use_cdn'] ) {
|
||||
self::cdn( false, $handle, $src_cdn, $deps, $ver, $in_footer, true );
|
||||
} else {
|
||||
self::vendor_plugin( false, $handle, $deps, $ver, $in_footer, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Redux_Vendor_URL' ) && class_exists( 'Redux_Extension_Vendor_Support' ) ) {
|
||||
class_alias( 'Redux_VendorURL', 'Redux_Vendor_URL' );
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Class
|
||||
*
|
||||
* @class Redux_Class
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Class', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Class
|
||||
*/
|
||||
class Redux_Class {
|
||||
|
||||
/**
|
||||
* Pointer to ReduxFramework object.
|
||||
*
|
||||
* @var null|ReduxFramework
|
||||
*/
|
||||
public $parent = null;
|
||||
|
||||
/**
|
||||
* Global arguments array.
|
||||
*
|
||||
* @var array|mixed|void
|
||||
*/
|
||||
public $args = array();
|
||||
|
||||
/**
|
||||
* Project opt_name
|
||||
*
|
||||
* @var mixed|string
|
||||
*/
|
||||
public $opt_name = '';
|
||||
|
||||
/**
|
||||
* Redux_Class constructor.
|
||||
*
|
||||
* @param null|object $redux Pointer to ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $redux = null ) {
|
||||
if ( is_object( $redux ) ) {
|
||||
$this->parent = $redux;
|
||||
$this->args = $redux->args;
|
||||
$this->opt_name = $this->args['opt_name'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pointer to a project-specific ReduxFramework object.
|
||||
*
|
||||
* @return null|object|ReduxFramework
|
||||
*/
|
||||
public function core() {
|
||||
if ( isset( $this->opt_name ) && '' !== $this->opt_name ) {
|
||||
return Redux::instance( $this->opt_name );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,334 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Color Manipulator Class
|
||||
*
|
||||
* @class Redux_Core
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Colors', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Colors
|
||||
*/
|
||||
class Redux_Colors extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Sanitizes a HEX value.
|
||||
* The way this works is by splitting the string in 6 substrings.
|
||||
* Each sub-string is individually sanitized, and the result is then returned.
|
||||
*
|
||||
* @param string $color The hex value of a color.
|
||||
* @param boolean $hash Whether we want to include a hash (#) at the beginning or not.
|
||||
*
|
||||
* @return string The sanitized hex color.
|
||||
*/
|
||||
public static function sanitize_hex( string $color = '#FFFFFF', bool $hash = true ): string {
|
||||
$word_colors = array(
|
||||
'aliceblue' => 'F0F8FF',
|
||||
'antiquewhite' => 'FAEBD7',
|
||||
'aqua' => '00FFFF',
|
||||
'aquamarine' => '7FFFD4',
|
||||
'azure' => 'F0FFFF',
|
||||
'beige' => 'F5F5DC',
|
||||
'bisque' => 'FFE4C4',
|
||||
'black' => '000000',
|
||||
'blanchedalmond' => 'FFEBCD',
|
||||
'blue' => '0000FF',
|
||||
'blueviolet' => '8A2BE2',
|
||||
'brown' => 'A52A2A',
|
||||
'burlywood' => 'DEB887',
|
||||
'cadetblue' => '5F9EA0',
|
||||
'chartreuse' => '7FFF00',
|
||||
'chocolate' => 'D2691E',
|
||||
'coral' => 'FF7F50',
|
||||
'cornflowerblue' => '6495ED',
|
||||
'cornsilk' => 'FFF8DC',
|
||||
'crimson' => 'DC143C',
|
||||
'cyan' => '00FFFF',
|
||||
'darkblue' => '00008B',
|
||||
'darkcyan' => '008B8B',
|
||||
'darkgoldenrod' => 'B8860B',
|
||||
'darkgray' => 'A9A9A9',
|
||||
'darkgreen' => '006400',
|
||||
'darkgrey' => 'A9A9A9',
|
||||
'darkkhaki' => 'BDB76B',
|
||||
'darkmagenta' => '8B008B',
|
||||
'darkolivegreen' => '556B2F',
|
||||
'darkorange' => 'FF8C00',
|
||||
'darkorchid' => '9932CC',
|
||||
'darkred' => '8B0000',
|
||||
'darksalmon' => 'E9967A',
|
||||
'darkseagreen' => '8FBC8F',
|
||||
'darkslateblue' => '483D8B',
|
||||
'darkslategray' => '2F4F4F',
|
||||
'darkslategrey' => '2F4F4F',
|
||||
'darkturquoise' => '00CED1',
|
||||
'darkviolet' => '9400D3',
|
||||
'deeppink' => 'FF1493',
|
||||
'deepskyblue' => '00BFFF',
|
||||
'dimgray' => '696969',
|
||||
'dimgrey' => '696969',
|
||||
'dodgerblue' => '1E90FF',
|
||||
'firebrick' => 'B22222',
|
||||
'floralwhite' => 'FFFAF0',
|
||||
'forestgreen' => '228B22',
|
||||
'fuchsia' => 'FF00FF',
|
||||
'gainsboro' => 'DCDCDC',
|
||||
'ghostwhite' => 'F8F8FF',
|
||||
'gold' => 'FFD700',
|
||||
'goldenrod' => 'DAA520',
|
||||
'gray' => '808080',
|
||||
'green' => '008000',
|
||||
'greenyellow' => 'ADFF2F',
|
||||
'grey' => '808080',
|
||||
'honeydew' => 'F0FFF0',
|
||||
'hotpink' => 'FF69B4',
|
||||
'indianred' => 'CD5C5C',
|
||||
'indigo' => '4B0082',
|
||||
'ivory' => 'FFFFF0',
|
||||
'khaki' => 'F0E68C',
|
||||
'lavender' => 'E6E6FA',
|
||||
'lavenderblush' => 'FFF0F5',
|
||||
'lawngreen' => '7CFC00',
|
||||
'lemonchiffon' => 'FFFACD',
|
||||
'lightblue' => 'ADD8E6',
|
||||
'lightcoral' => 'F08080',
|
||||
'lightcyan' => 'E0FFFF',
|
||||
'lightgoldenrodyellow' => 'FAFAD2',
|
||||
'lightgray' => 'D3D3D3',
|
||||
'lightgreen' => '90EE90',
|
||||
'lightgrey' => 'D3D3D3',
|
||||
'lightpink' => 'FFB6C1',
|
||||
'lightsalmon' => 'FFA07A',
|
||||
'lightseagreen' => '20B2AA',
|
||||
'lightskyblue' => '87CEFA',
|
||||
'lightslategray' => '778899',
|
||||
'lightslategrey' => '778899',
|
||||
'lightsteelblue' => 'B0C4DE',
|
||||
'lightyellow' => 'FFFFE0',
|
||||
'lime' => '00FF00',
|
||||
'limegreen' => '32CD32',
|
||||
'linen' => 'FAF0E6',
|
||||
'magenta' => 'FF00FF',
|
||||
'maroon' => '800000',
|
||||
'mediumaquamarine' => '66CDAA',
|
||||
'mediumblue' => '0000CD',
|
||||
'mediumorchid' => 'BA55D3',
|
||||
'mediumpurple' => '9370D0',
|
||||
'mediumseagreen' => '3CB371',
|
||||
'mediumslateblue' => '7B68EE',
|
||||
'mediumspringgreen' => '00FA9A',
|
||||
'mediumturquoise' => '48D1CC',
|
||||
'mediumvioletred' => 'C71585',
|
||||
'midnightblue' => '191970',
|
||||
'mintcream' => 'F5FFFA',
|
||||
'mistyrose' => 'FFE4E1',
|
||||
'moccasin' => 'FFE4B5',
|
||||
'navajowhite' => 'FFDEAD',
|
||||
'navy' => '000080',
|
||||
'oldlace' => 'FDF5E6',
|
||||
'olive' => '808000',
|
||||
'olivedrab' => '6B8E23',
|
||||
'orange' => 'FFA500',
|
||||
'orangered' => 'FF4500',
|
||||
'orchid' => 'DA70D6',
|
||||
'palegoldenrod' => 'EEE8AA',
|
||||
'palegreen' => '98FB98',
|
||||
'paleturquoise' => 'AFEEEE',
|
||||
'palevioletred' => 'DB7093',
|
||||
'papayawhip' => 'FFEFD5',
|
||||
'peachpuff' => 'FFDAB9',
|
||||
'peru' => 'CD853F',
|
||||
'pink' => 'FFC0CB',
|
||||
'plum' => 'DDA0DD',
|
||||
'powderblue' => 'B0E0E6',
|
||||
'purple' => '800080',
|
||||
'red' => 'FF0000',
|
||||
'rosybrown' => 'BC8F8F',
|
||||
'royalblue' => '4169E1',
|
||||
'saddlebrown' => '8B4513',
|
||||
'salmon' => 'FA8072',
|
||||
'sandybrown' => 'F4A460',
|
||||
'seagreen' => '2E8B57',
|
||||
'seashell' => 'FFF5EE',
|
||||
'sienna' => 'A0522D',
|
||||
'silver' => 'C0C0C0',
|
||||
'skyblue' => '87CEEB',
|
||||
'slateblue' => '6A5ACD',
|
||||
'slategray' => '708090',
|
||||
'slategrey' => '708090',
|
||||
'snow' => 'FFFAFA',
|
||||
'springgreen' => '00FF7F',
|
||||
'steelblue' => '4682B4',
|
||||
'tan' => 'D2B48C',
|
||||
'teal' => '008080',
|
||||
'thistle' => 'D8BFD8',
|
||||
'tomato' => 'FF6347',
|
||||
'turquoise' => '40E0D0',
|
||||
'violet' => 'EE82EE',
|
||||
'wheat' => 'F5DEB3',
|
||||
'white' => 'FFFFFF',
|
||||
'whitesmoke' => 'F5F5F5',
|
||||
'yellow' => 'FFFF00',
|
||||
'yellowgreen' => '9ACD32',
|
||||
);
|
||||
|
||||
if ( is_array( $color ) ) {
|
||||
$color = $color[0];
|
||||
}
|
||||
|
||||
// Remove any spaces and special characters before and after the string.
|
||||
$color = trim( $color );
|
||||
|
||||
// Check if the color is a standard word-color.
|
||||
// If it is, then convert to hex.
|
||||
if ( array_key_exists( $color, $word_colors ) ) {
|
||||
$color = $word_colors[ $color ];
|
||||
}
|
||||
|
||||
// Remove any trailing '#' symbols from the color value.
|
||||
$color = str_replace( '#', '', $color );
|
||||
|
||||
// If the string is six characters long, then use it in pairs.
|
||||
if ( 3 === strlen( $color ) ) {
|
||||
$color = substr( $color, 0, 1 ) . substr( $color, 0, 1 ) . substr( $color, 1, 1 ) . substr( $color, 1, 1 ) . substr( $color, 2, 1 ) . substr( $color, 2, 1 );
|
||||
}
|
||||
|
||||
$substr = array();
|
||||
for ( $i = 0; $i <= 5; $i++ ) {
|
||||
$default = ( 0 === $i ) ? 'F' : ( $substr[ $i - 1 ] );
|
||||
$substr[ $i ] = substr( $color, $i, 1 );
|
||||
$substr[ $i ] = ( false === $substr[ $i ] || ! ctype_xdigit( $substr[ $i ] ) ) ? $default : $substr[ $i ];
|
||||
}
|
||||
|
||||
$hex = implode( '', $substr );
|
||||
|
||||
return ( ! $hash ) ? $hex : '#' . $hex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes RGBA color.
|
||||
*
|
||||
* @param string $value RGBA value.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitize_rgba( string $value ): string {
|
||||
// If empty or an array return transparent.
|
||||
if ( empty( $value ) ) {
|
||||
return 'rgba(0,0,0,0)';
|
||||
}
|
||||
|
||||
// If string does not start with 'rgba', then treat as hex
|
||||
// sanitize the hex color and finally convert hex to rgba.
|
||||
if ( false === strpos( $value, 'rgba' ) ) {
|
||||
return self::get_rgba( self::sanitize_hex( $value ) );
|
||||
}
|
||||
|
||||
// By now we know the string is formatted as a rgba color, so we can just return it.
|
||||
$value = str_replace( array( ' ', 'rgba', '(', ')' ), '', $value );
|
||||
$value = explode( ',', $value );
|
||||
$red = ( isset( $value[0] ) ) ? intval( $value[0] ) : 255;
|
||||
$green = ( isset( $value[1] ) ) ? intval( $value[1] ) : 255;
|
||||
$blue = ( isset( $value[2] ) ) ? intval( $value[2] ) : 255;
|
||||
$alpha = ( isset( $value[3] ) ) ? filter_var( $value[3], FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION ) : 1;
|
||||
|
||||
return 'rgba(' . $red . ',' . $green . ',' . $blue . ',' . $alpha . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize colors.
|
||||
* Determine if the current value is a hex or a rgba color and call the appropriate method.
|
||||
*
|
||||
* @param string|array $value hex or rgba color.
|
||||
*
|
||||
* @return string
|
||||
* @since 0.8.5
|
||||
*/
|
||||
public static function sanitize_color( $value ): string {
|
||||
if ( is_array( $value ) ) {
|
||||
if ( isset( $value['rgba'] ) ) {
|
||||
$value = $value['rgba'];
|
||||
} elseif ( isset( $value['color'] ) ) {
|
||||
$opacity = ( isset( $value['opacity'] ) ) ? $value['opacity'] : null;
|
||||
$opacity = ( ! is_null( $opacity ) && isset( $value['alpha'] ) ) ? $value['alpha'] : null;
|
||||
$opacity = ( is_null( $opacity ) ) ? 1 : floatval( $opacity );
|
||||
|
||||
$value = self::get_rgba( $value['color'], $opacity );
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'transparent' === $value ) {
|
||||
return 'transparent';
|
||||
}
|
||||
|
||||
// Is this a rgba color or a hex?
|
||||
$mode = ( false === strpos( $value, 'rgba' ) ) ? 'rgba' : 'hex';
|
||||
|
||||
if ( 'rgba' === $mode ) {
|
||||
return self::sanitize_hex( $value );
|
||||
} else {
|
||||
return self::sanitize_rgba( $value );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rgb value of the $hex color.
|
||||
*
|
||||
* @param string $hex The hex value of a color.
|
||||
* @param boolean $implode Whether we want to implode the values or not.
|
||||
*
|
||||
* @return array|string array|string
|
||||
*/
|
||||
public static function get_rgb( string $hex, bool $implode = false ) {
|
||||
// Remove any trailing '#' symbols from the color value.
|
||||
$hex = self::sanitize_hex( $hex, false );
|
||||
|
||||
// rgb is an array.
|
||||
$rgb = array(
|
||||
hexdec( substr( $hex, 0, 2 ) ),
|
||||
hexdec( substr( $hex, 2, 2 ) ),
|
||||
hexdec( substr( $hex, 4, 2 ) ),
|
||||
);
|
||||
|
||||
return ( $implode ) ? implode( ',', $rgb ) : $rgb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rgb value of the $hex color.
|
||||
*
|
||||
* @param string $hex The hex value of a color.
|
||||
* @param int $opacity Opacity level (1-100).
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_rgba( string $hex = '#fff', int $opacity = 100 ): string {
|
||||
$hex = self::sanitize_hex( $hex, false );
|
||||
|
||||
/**
|
||||
* Make sure that opacity is properly formatted:
|
||||
* Set the opacity to 100 if a larger value has been entered by mistake.
|
||||
* If a negative value is used, then set to 0.
|
||||
* If an opacity value is entered in a decimal form (for example, 0.25), then multiply by 100.
|
||||
*/
|
||||
if ( $opacity >= 100 ) {
|
||||
$opacity = 100;
|
||||
} elseif ( $opacity < 0 ) {
|
||||
$opacity = 0;
|
||||
} elseif ( $opacity <= 1 && 0 !== $opacity ) {
|
||||
$opacity = ( $opacity * 100 );
|
||||
}
|
||||
|
||||
// Divide the opacity by 100 to end-up with a CSS value for the opacity.
|
||||
$opacity = ( $opacity / 100 );
|
||||
|
||||
return 'rgba(' . self::get_rgb( $hex, true ) . ', ' . $opacity . ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,412 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Connection Banner Class
|
||||
*
|
||||
* @class Redux_Core
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
// @codingStandardsIgnoreStart
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Connection_Banner', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Connection_Banner
|
||||
*/
|
||||
class Redux_Connection_Banner {
|
||||
/**
|
||||
* Plugin version, used for cache-busting of style and script file references.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var string
|
||||
*/
|
||||
protected $version = '1.0.0';
|
||||
|
||||
/**
|
||||
* Singleton instance.
|
||||
*
|
||||
* @var Redux_Connection_Banner
|
||||
**/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Register option.
|
||||
*
|
||||
* @var string $register_option
|
||||
*/
|
||||
private $register_option = 'redux-connection-register';
|
||||
/**
|
||||
* Dismiss option.
|
||||
*
|
||||
* @var string $dismiss_option
|
||||
*/
|
||||
private $dismiss_option = 'redux-connection-dismiss';
|
||||
|
||||
/**
|
||||
* Nonce slug.
|
||||
*
|
||||
* @var string $dismiss_options
|
||||
*/
|
||||
private $nonce = 'redux-connection-nonce';
|
||||
|
||||
/**
|
||||
* URLs.
|
||||
*
|
||||
* @var array $urls
|
||||
*/
|
||||
private $urls = array();
|
||||
|
||||
/**
|
||||
* Init function.
|
||||
*
|
||||
* @return Redux_Connection_Banner
|
||||
*/
|
||||
public static function init(): ?Redux_Connection_Banner {
|
||||
if ( is_null( self::$instance ) ) {
|
||||
self::$instance = new Redux_Connection_Banner();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redux_Connection_Banner constructor.
|
||||
*
|
||||
* Since we call the Redux_Connection_Banner:init() method from the `Redux` class, and after
|
||||
* the admin_init action fires, we know that the admin is initialized at this point.
|
||||
*/
|
||||
private function __construct() {
|
||||
$clean_get = $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
if ( isset( $clean_get['_wpnonce'] ) && wp_verify_nonce( $clean_get['_wpnonce'], $this->nonce ) ) {
|
||||
if ( isset( $clean_get[ $this->dismiss_option ] ) ) {
|
||||
update_option( 'redux-framework_extendify_plugin_notice', 'hide' );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_redux_activation', array( $this, 'admin_ajax' ) ); // Executed when logged in.
|
||||
add_action( 'current_screen', array( $this, 'maybe_initialize_hooks' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the URL for the current page to fall back if JS is broken.
|
||||
*
|
||||
* @param bool|string $location Used to determine the location of the banner for account creation.
|
||||
* @since 4.1.21
|
||||
* @return array
|
||||
*/
|
||||
private function get_urls( $location = true ): array {
|
||||
if ( ! empty( $this->urls ) ) {
|
||||
return $this->urls;
|
||||
}
|
||||
|
||||
global $pagenow;
|
||||
|
||||
$clean_get = $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
if ( isset( $clean_get[ $this->register_option ] ) ) {
|
||||
unset( $clean_get[ $this->register_option ] );
|
||||
}
|
||||
if ( isset( $clean_get[ $this->dismiss_option ] ) ) {
|
||||
unset( $clean_get[ $this->dismiss_option ] );
|
||||
}
|
||||
$base_url = admin_url( add_query_arg( $clean_get, $pagenow ) );
|
||||
|
||||
return array(
|
||||
'dismiss' => wp_nonce_url( add_query_arg( $this->dismiss_option, true, $base_url ), $this->nonce ),
|
||||
'register' => wp_nonce_url( add_query_arg( $this->register_option, $location, $base_url ), $this->nonce ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback for dismissing the notice.
|
||||
*/
|
||||
public function admin_ajax() {
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
$nonce = isset( $_REQUEST['nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['nonce'] ) ) : '';
|
||||
|
||||
if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, $this->nonce ) ) {
|
||||
die( __( 'Security check failed.', 'redux-framework' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
}
|
||||
|
||||
if ( 'false' === $_REQUEST['activate'] ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'close',
|
||||
'msg' => '',
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'redux-framework_extendify_plugin_notice', 'hide' );
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
$res = $this->install_extendify();
|
||||
|
||||
if ( true === $res ) {
|
||||
update_option( 'redux-framework_extendify_plugin_notice', 'hide' );
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install and activate Extendify Plugin.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function install_extendify(): bool {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/misc.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
|
||||
|
||||
$api = plugins_api(
|
||||
'plugin_information',
|
||||
array(
|
||||
'slug' => 'extendify',
|
||||
'fields' => array(
|
||||
'short_description' => false,
|
||||
'sections' => false,
|
||||
'requires' => false,
|
||||
'rating' => false,
|
||||
'ratings' => false,
|
||||
'downloaded' => false,
|
||||
'last_updated' => false,
|
||||
'added' => false,
|
||||
'tags' => false,
|
||||
'compatibility' => false,
|
||||
'homepage' => false,
|
||||
'donate_link' => false,
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
$download_link = $api->download_link;
|
||||
|
||||
if ( empty( $download_link ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'Error: Install URL for Extendify could not be located.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
$skin = new Redux_Installer_Muter( array( 'api' => $api ) );
|
||||
$upgrader = new Plugin_Upgrader( $skin );
|
||||
$install = $upgrader->install( $download_link );
|
||||
|
||||
if ( ob_get_contents() ) {
|
||||
ob_end_clean();
|
||||
}
|
||||
|
||||
if ( true !== $install ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'Install process for Extendify failed.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$plugin_dir = WP_PLUGIN_DIR . '/extendify/extendify.php';
|
||||
|
||||
$activate = activate_plugin( $plugin_dir );
|
||||
|
||||
if ( is_wp_error( $activate ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'Extendify activation failed.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'success',
|
||||
'msg' => esc_html__( 'Extendify installed and activated.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback for dismissing the notice.
|
||||
*
|
||||
* @param string|null $admin_body_class Class string.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function admin_body_class( ?string $admin_body_class = '' ): string {
|
||||
$classes = explode( ' ', trim( $admin_body_class ) );
|
||||
|
||||
$classes[] = false ? 'redux-connected' : 'redux-disconnected';
|
||||
|
||||
$admin_body_class = implode( ' ', array_unique( $classes ) );
|
||||
return " $admin_body_class ";
|
||||
}
|
||||
|
||||
/**
|
||||
* Will initialize hooks to display the new (as of 4.4) connection banner if the current user can
|
||||
* connect Redux if Redux has not been deactivated, and if the current page is the plugin page.
|
||||
*
|
||||
* This method should not be called if the site is connected to WordPress.com or if the site is in development mode.
|
||||
*
|
||||
* @since 4.4.0
|
||||
* @since 4.5.0 Made the new (as of 4.4) connection banner display to everyone by default.
|
||||
* @since 5.3.0 Running another split test between 4.4 banner and a new one in 5.3.
|
||||
* @since 7.2 B test was removed.
|
||||
*
|
||||
* @param $current_screen
|
||||
*/
|
||||
public function maybe_initialize_hooks( $current_screen ) {
|
||||
if ( Redux_Functions_Ex::is_plugin_installed( 'extendify' ) || 'hide' === get_option( 'redux-framework_extendify_plugin_notice', null ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'install_plugins' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't show the connection notice anywhere but the plugins.php after activating
|
||||
if ( 'plugins' !== $current_screen->base && 'dashboard' !== $current_screen->base ) {
|
||||
add_action( 'admin_head', array( $this, 'admin_head' ) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Only show this notice when the plugin is installed.
|
||||
if ( class_exists( 'Redux_Framework_Plugin' ) && false === Redux_Framework_Plugin::$crash ) {
|
||||
add_action( 'admin_notices', array( $this, 'render_banner' ) );
|
||||
add_action( 'network_admin_notices', array( $this, 'network_connect_notice' ) );
|
||||
add_action( 'admin_head', array( $this, 'admin_head' ) );
|
||||
add_filter( 'admin_body_class', array( $this, 'admin_body_class' ), 20 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide Individual Dashboard Pages
|
||||
*
|
||||
* @access public
|
||||
* @since 4.0.0
|
||||
* @return void
|
||||
*/
|
||||
public function admin_head() {
|
||||
?>
|
||||
|
||||
<link
|
||||
rel='stylesheet' id='redux-banner' <?php // phpcs:ignore WordPress.WP.EnqueuedResources ?>
|
||||
href='<?php echo esc_url( Redux_Core::$url ); ?>inc/welcome/css/redux-banner.min.css'
|
||||
type='text/css' media='all'/>
|
||||
<script
|
||||
id="redux-banner-admin"
|
||||
src='<?php echo esc_url( Redux_Core::$url ); ?>inc/welcome/js/redux-banner-admin.min.js'>
|
||||
</script>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the new connection banner as of 4.4.0.
|
||||
*
|
||||
* @since 7.2 Copy and visual elements reduced to show the new focus of Redux on Security and Performance.
|
||||
* @since 4.4.0
|
||||
*/
|
||||
public function render_banner() {
|
||||
|
||||
$urls = $this->get_urls( 'main_banner' );
|
||||
|
||||
?>
|
||||
<div id="redux-connect-message" class="updated redux-banner-container" data-nonce="<?php echo wp_create_nonce( $this->nonce ); ?>">
|
||||
<div class="redux-banner-inner-container">
|
||||
<a href="<?php echo esc_url( $urls['dismiss'] ); ?>" data-url="<?php echo admin_url( 'admin-ajax.php' ); ?>"
|
||||
class="notice-dismiss redux-banner-svg-dismiss redux-connection-banner-action"
|
||||
title="<?php esc_attr_e( 'Dismiss this notice', 'redux-framework' ); ?>" data-activate="false">
|
||||
</a>
|
||||
|
||||
<div class="redux-banner-content-container">
|
||||
|
||||
<!-- slide 1: intro -->
|
||||
<div class="redux-banner-slide redux-banner-slide-one redux-slide-is-active">
|
||||
|
||||
<div class="redux-banner-content-icon redux-illo">
|
||||
<a href="<?php echo esc_url( 'https://redux.io/?utm_source=plugin&utm_medium=extendify-plugin&utm_campaign=redux_banner_logo' ); ?>" target="_blank"><img
|
||||
src="<?php echo esc_url( Redux_Core::$url ); ?>assets/img/logo-color.svg"
|
||||
class="redux-banner-content-logo"
|
||||
alt="
|
||||
<?php
|
||||
esc_attr_e(
|
||||
'Visit our website to learn more!',
|
||||
'redux-framework'
|
||||
);
|
||||
?>
|
||||
" height="auto"
|
||||
/></a>
|
||||
</div>
|
||||
|
||||
<div class="redux-banner-slide-text">
|
||||
<h2><?php esc_html_e( 'Action needed to continue using the template library.', 'redux-framework' ); ?></h2>
|
||||
<p>
|
||||
<?php
|
||||
esc_html_e(
|
||||
"The Extendify Library of Patterns and Templates has been unbundled from the Redux Options Framework to give our users more control over their WordPress experience. To continue using the Extendify Library click Install & Activate below.",
|
||||
'redux_framework'
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<div class="redux-banner-button-container">
|
||||
<span class="redux-banner-tos-blurb"></span>
|
||||
<a href="<?php echo esc_url( $urls['register'] ); ?>" data-url="<?php echo admin_url( 'admin-ajax.php' ); ?>" data-activate="main_banner"
|
||||
class="button button-primary button-large redux-alt-connect-button redux-connection-banner-action">
|
||||
<?php esc_html_e( 'Install and Activate Extendify', 'redux-framework' ); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div> <!-- end slide 1 -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<noscript><style>#redux-connect-message{display:none;}</style></noscript>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the legacy network connection banner.
|
||||
*/
|
||||
public function network_connect_notice() {
|
||||
?>
|
||||
<div id="message" class="updated Redux-message">
|
||||
<div class="squeezer">
|
||||
<h2>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
__(
|
||||
'<strong>Redux is activated!</strong> Each site on your network must be connected individually by an admin on that site.',
|
||||
'Redux'
|
||||
),
|
||||
array( 'strong' => array() )
|
||||
);
|
||||
?>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<noscript><style>#message{display:none;}</style></noscript>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// @codingStandardsIgnoreEnd
|
||||
@@ -0,0 +1,737 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Primary Enqueue Class
|
||||
*
|
||||
* @class Redux_Core
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpIgnoredClassAliasDeclaration
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Enqueue', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Enqueue
|
||||
*/
|
||||
class Redux_Enqueue extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Data to localize.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $localize_data = array();
|
||||
|
||||
/**
|
||||
* Min string for .min files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $min = '';
|
||||
|
||||
/**
|
||||
* Timestamp for file versions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $timestamp = '';
|
||||
|
||||
/**
|
||||
* Localize data required for the repeater extension.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $repeater_data = array();
|
||||
|
||||
/**
|
||||
* Redux_Enqueue constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
// Enqueue the admin page CSS and JS.
|
||||
if ( isset( $_GET['page'] ) && $_GET['page'] === $redux->args['page_slug'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'init' ), 1 );
|
||||
}
|
||||
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'frontend_init' ), 10 );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/{$redux->args['opt_name']}/enqueue/construct", $this );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/enqueue/construct', $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Scripts to enqueue on the frontend
|
||||
*/
|
||||
public function frontend_init() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( $core->args['elusive_frontend'] ) {
|
||||
Redux_Functions_Ex::enqueue_elusive_font();
|
||||
}
|
||||
|
||||
if ( $core->args['fontawesome_frontend'] ) {
|
||||
Redux_Functions_Ex::enqueue_font_awesome();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class init functions.
|
||||
*/
|
||||
public function init() {
|
||||
$core = $this->core();
|
||||
|
||||
Redux_Functions::$parent = $core;
|
||||
Redux_CDN::$parent = $core;
|
||||
|
||||
$this->min = Redux_Functions::is_min();
|
||||
|
||||
$this->timestamp = Redux_Core::$version;
|
||||
if ( $core->args['dev_mode'] ) {
|
||||
$this->timestamp .= '.' . time();
|
||||
}
|
||||
|
||||
$this->register_styles( $core );
|
||||
$this->register_scripts();
|
||||
|
||||
add_thickbox();
|
||||
|
||||
$this->enqueue_fields( $core );
|
||||
|
||||
add_filter( "redux/{$core->args['opt_name']}/localize", array( 'Redux_Helpers', 'localize' ) );
|
||||
|
||||
$this->set_localized_data( $core );
|
||||
|
||||
/**
|
||||
* Action 'redux/page/{opt_name}/enqueue'
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/page/{$core->args['opt_name']}/enqueue" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all core framework styles.
|
||||
*
|
||||
* @param object $core ReduxFramework object.
|
||||
*/
|
||||
private function register_styles( $core ) {
|
||||
|
||||
/**
|
||||
* Redux Admin CSS
|
||||
*/
|
||||
if ( 'wordpress' === $core->args['admin_theme'] || 'wp' === $core->args['admin_theme'] ) { // phpcs:ignore WordPress.WP.CapitalPDangit
|
||||
$color_scheme = get_user_option( 'admin_color' );
|
||||
} elseif ( 'classic' === $core->args['admin_theme'] || '' === $core->args['admin_theme'] ) {
|
||||
$color_scheme = 'classic';
|
||||
} else {
|
||||
$color_scheme = $core->args['admin_theme'];
|
||||
}
|
||||
|
||||
if ( ! file_exists( Redux_Core::$dir . "assets/css/colors/$color_scheme/colors$this->min.css" ) ) {
|
||||
$color_scheme = 'fresh';
|
||||
}
|
||||
|
||||
$css = Redux_Core::$url . "assets/css/colors/$color_scheme/colors$this->min.css";
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$css = apply_filters( 'redux/enqueue/' . $core->args['opt_name'] . '/args/admin_theme/css_url', $css );
|
||||
|
||||
wp_register_style(
|
||||
'redux-admin-theme',
|
||||
$css,
|
||||
array(),
|
||||
$this->timestamp
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'redux-admin-css',
|
||||
Redux_Core::$url . "assets/css/redux-admin$this->min.css",
|
||||
array( 'redux-admin-theme' ),
|
||||
$this->timestamp
|
||||
);
|
||||
|
||||
/**
|
||||
* Redux Fields CSS
|
||||
*/
|
||||
if ( ! $core->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-fields',
|
||||
Redux_Core::$url . 'assets/css/redux-fields.min.css',
|
||||
array(),
|
||||
$this->timestamp
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select2 CSS
|
||||
*/
|
||||
wp_enqueue_style(
|
||||
'select2-css',
|
||||
Redux_Core::$url . 'assets/css/vendor/select2.min.css',
|
||||
array(),
|
||||
'4.1.0'
|
||||
);
|
||||
|
||||
/**
|
||||
* Spectrum CSS
|
||||
*/
|
||||
wp_register_style(
|
||||
'redux-spectrum-css',
|
||||
Redux_Core::$url . "assets/css/vendor/spectrum$this->min.css",
|
||||
array(),
|
||||
'1.3.3'
|
||||
);
|
||||
|
||||
/**
|
||||
* Elusive Icon CSS
|
||||
*/
|
||||
Redux_Functions_Ex::enqueue_elusive_font();
|
||||
|
||||
/**
|
||||
* Font Awesome for Social Profiles and Icon Select
|
||||
*/
|
||||
Redux_Functions_Ex::enqueue_font_awesome();
|
||||
|
||||
/**
|
||||
* QTip CSS
|
||||
*/
|
||||
wp_enqueue_style(
|
||||
'qtip',
|
||||
Redux_Core::$url . "assets/css/vendor/qtip$this->min.css",
|
||||
array(),
|
||||
'3.0.3'
|
||||
);
|
||||
|
||||
/**
|
||||
* JQuery UI CSS
|
||||
*/
|
||||
wp_enqueue_style(
|
||||
'jquery-ui',
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/page/{$core->args['opt_name']}/enqueue/jquery-ui-css",
|
||||
Redux_Core::$url . 'assets/css/vendor/jquery-ui-1.10.0.custom.css'
|
||||
),
|
||||
array(),
|
||||
$this->timestamp
|
||||
);
|
||||
|
||||
/**
|
||||
* Iris CSS
|
||||
*/
|
||||
wp_enqueue_style( 'wp-color-picker' );
|
||||
|
||||
if ( $core->args['dev_mode'] ) {
|
||||
|
||||
/**
|
||||
* Media CSS
|
||||
*/
|
||||
wp_enqueue_style(
|
||||
'redux-field-media',
|
||||
Redux_Core::$url . 'assets/css/media.css',
|
||||
array(),
|
||||
$this->timestamp
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* RTL CSS
|
||||
*/
|
||||
if ( is_rtl() ) {
|
||||
wp_enqueue_style(
|
||||
'redux-rtl',
|
||||
Redux_Core::$url . 'assets/css/rtl.css',
|
||||
array(),
|
||||
$this->timestamp
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register all core framework scripts.
|
||||
*/
|
||||
private function register_scripts() {
|
||||
// *****************************************************************
|
||||
// JQuery / JQuery UI JS
|
||||
// *****************************************************************
|
||||
wp_enqueue_script( 'jquery' );
|
||||
wp_enqueue_script( 'jquery-ui-core' );
|
||||
wp_enqueue_script( 'jquery-ui-dialog' );
|
||||
|
||||
/**
|
||||
* Select2 Sortable JS
|
||||
*/
|
||||
wp_register_script(
|
||||
'redux-select2-sortable',
|
||||
Redux_Core::$url . 'assets/js/vendor/select2-sortable/redux.select2.sortable' . $this->min . '.js',
|
||||
array( 'jquery', 'jquery-ui-sortable' ),
|
||||
$this->timestamp,
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Select2
|
||||
*/
|
||||
wp_enqueue_script(
|
||||
'select2-js',
|
||||
Redux_Core::$url . 'assets/js/vendor/select2/select2' . $this->min . '.js`',
|
||||
array( 'jquery', 'redux-select2-sortable' ),
|
||||
'4.1.0',
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* QTip JS
|
||||
*/
|
||||
wp_enqueue_script(
|
||||
'qtip',
|
||||
Redux_Core::$url . 'assets/js/vendor/qtip/qtip' . $this->min . '.js',
|
||||
array( 'jquery' ),
|
||||
'3.0.3',
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Iris alpha color picker
|
||||
*/
|
||||
if ( ! wp_script_is( 'redux-wp-color-picker-alpha' ) ) {
|
||||
wp_enqueue_style( 'wp-color-picker' );
|
||||
|
||||
wp_register_script(
|
||||
'redux-wp-color-picker-alpha',
|
||||
Redux_Core::$url . 'assets/js/vendor/wp-color-picker-alpha/wp-color-picker-alpha' . $this->min . '.js',
|
||||
array( 'jquery', 'wp-color-picker' ),
|
||||
'3.0.0',
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block UI (used by Custom Fonts and Color Schemes).
|
||||
*/
|
||||
wp_register_script(
|
||||
'redux-block-ui',
|
||||
Redux_Core::$url . 'assets/js/vendor/block-ui/jquery.blockUI' . $this->min . '.js',
|
||||
array( 'jquery' ),
|
||||
'2.70.0',
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Spectrum JS
|
||||
*/
|
||||
wp_register_script(
|
||||
'redux-spectrum-js',
|
||||
Redux_Core::$url . 'assets/js/vendor/spectrum/redux-spectrum' . $this->min . '.js',
|
||||
array( 'jquery' ),
|
||||
'1.3.3',
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Vendor JS
|
||||
*/
|
||||
wp_register_script(
|
||||
'redux-vendor',
|
||||
Redux_Core::$url . 'assets/js/redux-vendors' . $this->min . '.js',
|
||||
array( 'jquery' ),
|
||||
$this->timestamp,
|
||||
true
|
||||
);
|
||||
|
||||
/**
|
||||
* Redux JS
|
||||
*/
|
||||
wp_register_script(
|
||||
'redux-js',
|
||||
Redux_Core::$url . 'assets/js/redux' . $this->min . '.js',
|
||||
array( 'jquery', 'redux-vendor' ),
|
||||
$this->timestamp,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue fields that are in use.
|
||||
*
|
||||
* @param object $core ReduxFramework object.
|
||||
* @param array $field Field array.
|
||||
*/
|
||||
public function enqueue_field( $core, array $field ) {
|
||||
if ( isset( $field['type'] ) && 'callback' !== $field['type'] ) {
|
||||
$field_type = str_replace( '_', '-', $field['type'] );
|
||||
$core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/class-redux-$field_type.php";
|
||||
|
||||
// Shim for v3 extension class names.
|
||||
if ( ! file_exists( $core_path ) ) {
|
||||
$core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/field_{$field['type']}.php";
|
||||
}
|
||||
|
||||
$filter_path = $core_path;
|
||||
|
||||
/**
|
||||
* Field class file
|
||||
* filter 'redux/{opt_name}/field/class/{field.type}
|
||||
*
|
||||
* @param string $filter_path Field class file path
|
||||
* @param array $field Field config data
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$class_file = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/field/class/{$field['type']}",
|
||||
$filter_path,
|
||||
$field
|
||||
);
|
||||
|
||||
$field_classes = array( 'Redux_' . $field['type'], 'ReduxFramework_' . $field['type'] );
|
||||
|
||||
if ( $class_file ) {
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
if ( false === $field_class ) {
|
||||
if ( file_exists( $class_file ) ) {
|
||||
require_once $class_file;
|
||||
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( false !== $field_class && ( ( method_exists( $field_class, 'enqueue' ) ) || method_exists( $field_class, 'localize' ) ) ) {
|
||||
if ( ! isset( $core->options[ $field['id'] ] ) ) {
|
||||
$core->options[ $field['id'] ] = '';
|
||||
}
|
||||
|
||||
$the_field = new $field_class( $field, $core->options[ $field['id'] ], $core );
|
||||
|
||||
// Move dev_mode check to a new if/then block.
|
||||
if ( ! wp_script_is( 'redux-field-' . $field_type ) && ( class_exists( $field_class ) && method_exists( $field_class, 'enqueue' ) ) ) {
|
||||
$the_field->enqueue();
|
||||
}
|
||||
|
||||
if ( class_exists( $field_class ) && method_exists( $field_class, 'always_enqueue' ) ) {
|
||||
$the_field->always_enqueue();
|
||||
}
|
||||
|
||||
if ( method_exists( $field_class, 'localize' ) ) {
|
||||
$the_field->localize( $field );
|
||||
|
||||
if ( ! isset( $this->localize_data[ $field['type'] ] ) ) {
|
||||
$this->localize_data[ $field['type'] ] = array();
|
||||
}
|
||||
|
||||
$localize_data = $the_field->localize( $field );
|
||||
|
||||
$shims = array( 'repeater' );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$shims = apply_filters( 'redux/' . $core->args['opt_name'] . '/localize/shims', $shims );
|
||||
|
||||
if ( is_array( $shims ) && in_array( $field['type'], $shims, true ) ) {
|
||||
$this->repeater_data[ $field['type'] ][ $field['id'] ] = $localize_data;
|
||||
}
|
||||
|
||||
$this->localize_data[ $field['type'] ][ $field['id'] ] = $localize_data;
|
||||
}
|
||||
|
||||
unset( $the_field );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue field files.
|
||||
*
|
||||
* @param object $core ReduxFramework object.
|
||||
*/
|
||||
private function enqueue_fields( $core ) {
|
||||
foreach ( $core->sections as $section ) {
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $field ) {
|
||||
$this->enqueue_field( $core, $field );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a localized array from field functions, if any.
|
||||
*
|
||||
* @param object $core ReduxFramework object.
|
||||
* @param string $type Field type.
|
||||
*/
|
||||
private function build_local_array( $core, string $type ) {
|
||||
if ( isset( $core->transients['last_save_mode'] ) && ! empty( $core->transients['notices'][ $type ] ) ) {
|
||||
$the_total = 0;
|
||||
$messages = array();
|
||||
|
||||
foreach ( $core->transients['notices'][ $type ] as $msg ) {
|
||||
if ( is_array( $msg ) && ! empty( $msg ) ) {
|
||||
$messages[ $msg['section_id'] ][ $type ][] = $msg;
|
||||
|
||||
if ( ! isset( $messages[ $msg['section_id'] ]['total'] ) ) {
|
||||
$messages[ $msg['section_id'] ]['total'] = 0;
|
||||
}
|
||||
|
||||
++$messages[ $msg['section_id'] ]['total'];
|
||||
++$the_total;
|
||||
}
|
||||
}
|
||||
|
||||
$this->localize_data[ $type ] = array(
|
||||
'total' => $the_total,
|
||||
"$type" => $messages,
|
||||
);
|
||||
|
||||
unset( $core->transients['notices'][ $type ] );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile panel errors and wearings for a localized array.
|
||||
*/
|
||||
public function get_warnings_and_errors_array() {
|
||||
$core = $this->core();
|
||||
|
||||
$this->build_local_array( $core, 'errors' );
|
||||
$this->build_local_array( $core, 'warnings' );
|
||||
$this->build_local_array( $core, 'sanitize' );
|
||||
|
||||
if ( empty( $core->transients['notices'] ) ) {
|
||||
if ( isset( $core->transients['notices'] ) ) {
|
||||
unset( $core->transients['notices'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commit localized data to global array.
|
||||
*
|
||||
* @param object $core ReduxFramework object.
|
||||
*/
|
||||
private function set_localized_data( $core ) {
|
||||
if ( ! empty( $core->args['last_tab'] ) ) {
|
||||
$this->localize_data['last_tab'] = $core->args['last_tab'];
|
||||
}
|
||||
|
||||
$this->localize_data['font_weights'] = $this->args['font_weights'];
|
||||
|
||||
$this->localize_data['required'] = $core->required;
|
||||
$this->repeater_data['fonts'] = $core->fonts;
|
||||
|
||||
if ( ! isset( $this->repeater_data['opt_names'] ) ) {
|
||||
$this->repeater_data['opt_names'] = array();
|
||||
}
|
||||
|
||||
$this->repeater_data['opt_names'][] = $core->args['opt_name'];
|
||||
$this->repeater_data['folds'] = array();
|
||||
$this->localize_data['required_child'] = $core->required_child;
|
||||
$this->localize_data['fields'] = $core->fields;
|
||||
|
||||
if ( isset( $core->font_groups['google'] ) ) {
|
||||
$this->repeater_data['googlefonts'] = $core->font_groups['google'];
|
||||
}
|
||||
|
||||
if ( isset( $core->font_groups['std'] ) ) {
|
||||
$this->repeater_data['stdfonts'] = $core->font_groups['std'];
|
||||
}
|
||||
|
||||
if ( isset( $core->font_groups['customfonts'] ) ) {
|
||||
$this->repeater_data['customfonts'] = $core->font_groups['customfonts'];
|
||||
}
|
||||
|
||||
if ( isset( $core->font_groups['typekitfonts'] ) ) {
|
||||
$this->repeater_data['typekitfonts'] = $core->font_groups['typekitfonts'];
|
||||
}
|
||||
|
||||
$this->localize_data['folds'] = $core->folds;
|
||||
|
||||
// Make sure the children are all hidden properly.
|
||||
foreach ( $core->fields as $key => $value ) {
|
||||
if ( in_array( $key, $core->fields_hidden, true ) ) {
|
||||
foreach ( $value as $k => $v ) {
|
||||
if ( ! in_array( $k, $core->fields_hidden, true ) ) {
|
||||
$core->fields_hidden[] = $k;
|
||||
$core->folds[ $k ] = 'hide';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->localize_data['fields_hidden'] = $core->fields_hidden;
|
||||
$this->localize_data['options'] = $core->options;
|
||||
$this->localize_data['defaults'] = $core->options_defaults;
|
||||
|
||||
/**
|
||||
* Save pending string
|
||||
* filter 'redux/{opt_name}/localize/save_pending
|
||||
*
|
||||
* @param string $msg Save_pending string
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$save_pending = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/localize/save_pending",
|
||||
esc_html__(
|
||||
'You have changes that are not saved. Would you like to save them now?',
|
||||
'redux-framework'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Reset all string
|
||||
* filter 'redux/{opt_name}/localize/reset
|
||||
*
|
||||
* @param string $msg Reset all string.
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$reset_all = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/localize/reset",
|
||||
esc_html__(
|
||||
'Are you sure? Resetting will lose all custom values.',
|
||||
'redux-framework'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Reset section string
|
||||
* filter 'redux/{opt_name}/localize/reset_section
|
||||
*
|
||||
* @param string $msg Reset section string.
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$reset_section = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/localize/reset_section",
|
||||
esc_html__(
|
||||
'Are you sure? Resetting will lose all custom values in this section.',
|
||||
'redux-framework'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Preset confirm string
|
||||
* filter 'redux/{opt_name}/localize/preset
|
||||
*
|
||||
* @param string $msg Preset confirm string.
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$preset_confirm = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/localize/preset",
|
||||
esc_html__(
|
||||
'Your current options will be replaced with the values of this preset. Would you like to proceed?',
|
||||
'redux-framework'
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* Import confirm string
|
||||
* filter 'redux/{opt_name}/localize/import
|
||||
*
|
||||
* @param string $msg Import confirm string.
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$import_confirm = apply_filters(
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
"redux/{$core->args['opt_name']}/localize/import",
|
||||
esc_html__(
|
||||
'Your current options will be replaced with the values of this import. Would you like to proceed?',
|
||||
'redux-framework'
|
||||
)
|
||||
);
|
||||
|
||||
global $pagenow;
|
||||
|
||||
$this->localize_data['args'] = array(
|
||||
'dev_mode' => $core->args['dev_mode'],
|
||||
'save_pending' => $save_pending,
|
||||
'reset_confirm' => $reset_all,
|
||||
'reset_section_confirm' => $reset_section,
|
||||
'preset_confirm' => $preset_confirm,
|
||||
'import_section_confirm' => $import_confirm,
|
||||
'please_wait' => esc_html__( 'Please Wait', 'redux-framework' ),
|
||||
'opt_name' => $core->args['opt_name'],
|
||||
'flyout_submenus' => $core->args['flyout_submenus'] ?? false,
|
||||
'slug' => $core->args['page_slug'],
|
||||
'hints' => $core->args['hints'],
|
||||
'disable_save_warn' => $core->args['disable_save_warn'],
|
||||
'class' => $core->args['class'],
|
||||
'ajax_save' => $core->args['ajax_save'],
|
||||
'menu_search' => $pagenow . '?page=' . $core->args['page_slug'] . '&tab=',
|
||||
);
|
||||
|
||||
$this->localize_data['ajax'] = array(
|
||||
'console' => esc_html__(
|
||||
'There was an error saving. Here is the result of your action:',
|
||||
'redux-framework'
|
||||
),
|
||||
'alert' => esc_html__(
|
||||
'There was a problem with your action. Please try again or reload the page.',
|
||||
'redux-framework'
|
||||
),
|
||||
);
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$this->localize_data = apply_filters( "redux/{$core->args['opt_name']}/localize", $this->localize_data );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$this->repeater_data = apply_filters( "redux/{$core->args['opt_name']}/repeater", $this->repeater_data );
|
||||
|
||||
$this->get_warnings_and_errors_array();
|
||||
|
||||
if ( ! isset( $core->repeater_data ) ) {
|
||||
$core->repeater_data = array();
|
||||
}
|
||||
$core->repeater_data = Redux_Functions_Ex::nested_wp_parse_args(
|
||||
$this->repeater_data,
|
||||
$core->repeater_data
|
||||
);
|
||||
|
||||
if ( ! isset( $core->localize_data ) ) {
|
||||
$core->localize_data = array();
|
||||
}
|
||||
$core->localize_data = Redux_Functions_Ex::nested_wp_parse_args(
|
||||
$this->localize_data,
|
||||
$core->localize_data
|
||||
);
|
||||
|
||||
// Shim for extension compatibility.
|
||||
if ( Redux::$extension_compatibility ) {
|
||||
$this->repeater_data = Redux_Functions_Ex::nested_wp_parse_args(
|
||||
$this->repeater_data,
|
||||
$core->localize_data
|
||||
);
|
||||
}
|
||||
|
||||
wp_localize_script(
|
||||
'redux-js',
|
||||
'redux',
|
||||
$this->repeater_data
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'redux-js',
|
||||
'redux_' . str_replace( '-', '_', $core->args['opt_name'] ),
|
||||
$this->localize_data
|
||||
);
|
||||
|
||||
wp_enqueue_script( 'redux-js' ); // Enqueue the JS now.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'reduxCoreEnqueue' ) ) {
|
||||
class_alias( 'Redux_Enqueue', 'reduxCoreEnqueue' );
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Extension Abstract
|
||||
*
|
||||
* @class Redux_Extension_Abstract
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Class Redux_Extension_Abstract
|
||||
* An abstract class to make the writing of redux extensions easier by allowing users to extend this class
|
||||
*
|
||||
* @see the samples directory to find a usage example
|
||||
*/
|
||||
abstract class Redux_Extension_Abstract {
|
||||
/**
|
||||
* The version of the extension (This is a default value you may want to override it)
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '1.0.0';
|
||||
|
||||
/**
|
||||
* The extension URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $extension_url;
|
||||
|
||||
/**
|
||||
* The extension dir.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $extension_dir;
|
||||
|
||||
/**
|
||||
* The instance of the extension
|
||||
*
|
||||
* @var static
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* The extension's file
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $file;
|
||||
|
||||
/**
|
||||
* The redux framework instance that spawned the extension.
|
||||
*
|
||||
* @var ReduxFramework
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* The ReflectionClass of the extension
|
||||
*
|
||||
* @var ReflectionClass
|
||||
*/
|
||||
protected $reflection_class;
|
||||
|
||||
/**
|
||||
* Redux_Extension_Abstract constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
* @param string $file Extension file.
|
||||
*/
|
||||
public function __construct( $redux, string $file = '' ) {
|
||||
$this->parent = $redux;
|
||||
|
||||
// If the file is not given, make sure we have one.
|
||||
if ( empty( $file ) ) {
|
||||
$file = $this->get_reflection()->getFileName();
|
||||
}
|
||||
|
||||
$this->file = $file;
|
||||
|
||||
$this->extension_dir = trailingslashit( str_replace( '\\', '/', dirname( $file ) ) );
|
||||
|
||||
$plugin_info = Redux_Functions_Ex::is_inside_plugin( $this->file );
|
||||
|
||||
if ( false !== $plugin_info ) {
|
||||
$this->extension_url = trailingslashit( dirname( $plugin_info['url'] ) );
|
||||
} else {
|
||||
$theme_info = Redux_Functions_Ex::is_inside_theme( $this->file );
|
||||
if ( false !== $theme_info ) {
|
||||
$this->extension_url = trailingslashit( dirname( $theme_info['url'] ) );
|
||||
}
|
||||
}
|
||||
|
||||
static::$instance = $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the reflection class of the extension.
|
||||
*
|
||||
* @return ReflectionClass
|
||||
*/
|
||||
protected function get_reflection(): ReflectionClass {
|
||||
if ( ! isset( $this->reflection_class ) ) {
|
||||
$this->reflection_class = new ReflectionClass( $this );
|
||||
}
|
||||
|
||||
return $this->reflection_class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extension version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_version(): string {
|
||||
return static::$version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns extension instance.
|
||||
*
|
||||
* @return Redux_Extension_Abstract
|
||||
*/
|
||||
public static function get_instance(): Redux_Extension_Abstract {
|
||||
return static::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return extension dir.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_dir(): string {
|
||||
return $this->extension_dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns extension URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_url(): string {
|
||||
return $this->extension_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the local field. (The use of add_field is recommended).
|
||||
*
|
||||
* @param string $field_name Name of field.
|
||||
*/
|
||||
protected function add_overload_field_filter( string $field_name ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
add_filter( 'redux/' . $this->parent->args['opt_name'] . '/field/class/' . $field_name, array( &$this, 'overload_field_path' ), 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the local field to the extension and register it in the builder.
|
||||
*
|
||||
* @param string $field_name Name of field.
|
||||
*/
|
||||
protected function add_field( string $field_name ) {
|
||||
$class = $this->get_reflection()->getName();
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
add_filter(
|
||||
'redux/fields',
|
||||
function ( $classes ) use ( $field_name, $class ) {
|
||||
$classes[ $field_name ] = $class;
|
||||
|
||||
return $classes;
|
||||
}
|
||||
);
|
||||
|
||||
$this->add_overload_field_filter( $field_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Overload a field path.
|
||||
*
|
||||
* @param string $file Extension file.
|
||||
* @param array $field Field array.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function overload_field_path( string $file, array $field ): string {
|
||||
$filename_fix = str_replace( '_', '-', $field['type'] );
|
||||
|
||||
$files = array(
|
||||
trailingslashit( dirname( $this->file ) ) . $field['type'] . DIRECTORY_SEPARATOR . 'field_' . $field['type'] . '.php',
|
||||
trailingslashit( dirname( $this->file ) ) . $field['type'] . DIRECTORY_SEPARATOR . 'class-redux-' . $filename_fix . '.php',
|
||||
);
|
||||
|
||||
return Redux_Functions::file_exists_ex( $files );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum version of Redux to use. Displays a notice if requirements are not met.
|
||||
*
|
||||
* @param string $min_version Minimum version to evaluate.
|
||||
* @param string $extension_version Extension version number.
|
||||
* @param string $friendly_name Friend extension name for notice display.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_minimum_version( string $min_version = '', string $extension_version = '', string $friendly_name = '' ): bool {
|
||||
$redux_ver = Redux_Core::$version;
|
||||
|
||||
if ( '' !== $min_version ) {
|
||||
if ( version_compare( $redux_ver, $min_version ) < 0 ) {
|
||||
// translators: %1$s Extension friendly name. %2$s: minimum Redux version.
|
||||
$msg = '<strong>' . sprintf( esc_html__( 'The %1$s extension requires Redux Framework version %2$s or higher.', 'redux-framework' ), $friendly_name, $min_version ) . '</strong> ' . esc_html__( 'You are currently running Redux Framework version ', 'redux-framework' ) . ' ' . $redux_ver . '.<br/><br/>' . esc_html__( 'This field will not render in your option panel, and features of this extension will not be available until the latest version of Redux Framework has been installed.', 'redux-framework' );
|
||||
|
||||
$data = array(
|
||||
'parent' => $this->parent,
|
||||
'type' => 'error',
|
||||
'msg' => $msg,
|
||||
'id' => $this->ext_name . '_notice_' . $extension_version,
|
||||
'dismiss' => false,
|
||||
);
|
||||
|
||||
if ( method_exists( 'Redux_Admin_Notices', 'set_notice' ) ) {
|
||||
Redux_Admin_Notices::set_notice( $data );
|
||||
} else {
|
||||
echo '<div class="error">';
|
||||
echo '<p>';
|
||||
echo $msg; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
echo '</p>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Redux_Abstract_Extension' ) ) {
|
||||
class_alias( 'Redux_Extension_Abstract', 'Redux_Abstract_Extension' );
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
/**
|
||||
* Register Extensions for use
|
||||
*
|
||||
* @package Redux Framework/Classes
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Extensions', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Extensions
|
||||
*/
|
||||
class Redux_Extensions extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_Extensions constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework object pointer.
|
||||
*
|
||||
* @throws ReflectionException Exception.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class load functions.
|
||||
*
|
||||
* @throws ReflectionException For fallback.
|
||||
*/
|
||||
private function load() {
|
||||
$core = $this->core();
|
||||
|
||||
$max = 1;
|
||||
|
||||
for ( $i = 1; $i <= $max; $i++ ) {
|
||||
$path = Redux_Core::$dir . 'inc/extensions/';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$path = apply_filters( 'redux/' . $core->args['opt_name'] . '/extensions/dir', $path );
|
||||
|
||||
/**
|
||||
* Action 'redux/extensions/before'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/extensions/before', $core );
|
||||
|
||||
/**
|
||||
* Action 'redux/extensions/{opt_name}/before'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/extensions/{$core->args['opt_name']}/before", $core );
|
||||
|
||||
if ( isset( $core->old_opt_name ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/extensions/' . $core->old_opt_name . '/before', $core );
|
||||
}
|
||||
|
||||
require_once Redux_Core::$dir . 'inc/classes/class-redux-extension-abstract.php';
|
||||
|
||||
$path = untrailingslashit( $path );
|
||||
|
||||
Redux::set_extensions( $core->args['opt_name'], $path, true );
|
||||
|
||||
/**
|
||||
* Action 'redux/extensions/{opt_name}'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/extensions/{$core->args['opt_name']}", $core );
|
||||
|
||||
if ( isset( $core->old_opt_name ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/extensions/' . $core->old_opt_name, $core );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Field Class
|
||||
*
|
||||
* @class Redux_Field
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Field', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Field
|
||||
*/
|
||||
abstract class Redux_Field {
|
||||
|
||||
/**
|
||||
* CSS styling per field output/compiler.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $style = null;
|
||||
|
||||
/**
|
||||
* Class dir.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $dir = null;
|
||||
|
||||
/**
|
||||
* Class URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $url = null;
|
||||
|
||||
/**
|
||||
* Timestamp for ver append in dev_mode
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $timestamp = null;
|
||||
|
||||
/**
|
||||
* ReduxFramework object pointer.
|
||||
*
|
||||
* @var ReduxFramework
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* Field values.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
public $field;
|
||||
|
||||
/**
|
||||
* Value values.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* Select2 options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $select2_config = array();
|
||||
|
||||
/**
|
||||
* Redux_Field constructor.
|
||||
*
|
||||
* @param array|string|null $field Field array.
|
||||
* @param string|array|null $value Field values.
|
||||
* @param null $redux ReduxFramework object pointer.
|
||||
*
|
||||
* @throws ReflectionException Comment.
|
||||
*/
|
||||
public function __construct( $field = array(), $value = null, $redux = null ) {
|
||||
$this->parent = $redux;
|
||||
$this->field = $field;
|
||||
$this->value = $value;
|
||||
|
||||
$this->select2_config = array(
|
||||
'width' => 'resolve',
|
||||
'allowClear' => false,
|
||||
'theme' => 'default',
|
||||
);
|
||||
|
||||
$this->set_defaults();
|
||||
|
||||
$class_name = get_class( $this );
|
||||
$reflector = new ReflectionClass( $class_name );
|
||||
$path = $reflector->getFilename();
|
||||
$path_info = Redux_Helpers::path_info( $path );
|
||||
$this->dir = trailingslashit( dirname( $path_info['real_path'] ) );
|
||||
$this->url = trailingslashit( dirname( $path_info['url'] ) );
|
||||
|
||||
$this->timestamp = Redux_Core::$version;
|
||||
if ( $redux->args['dev_mode'] ) {
|
||||
$this->timestamp .= '.' . time();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Media query compiler for Redux Pro,
|
||||
*
|
||||
* @param string $style_data CSS string.
|
||||
*/
|
||||
public function media_query( string $style_data = '' ) {
|
||||
$query_arr = $this->field['media_query'];
|
||||
$css = '';
|
||||
|
||||
if ( isset( $query_arr['queries'] ) ) {
|
||||
foreach ( $query_arr['queries'] as $query ) {
|
||||
$rule = $query['rule'] ?? '';
|
||||
$selectors = $query['selectors'] ?? array();
|
||||
|
||||
if ( ! is_array( $selectors ) && '' !== $selectors ) {
|
||||
$selectors = array( $selectors );
|
||||
}
|
||||
|
||||
if ( '' !== $rule && ! empty( $selectors ) ) {
|
||||
$selectors = implode( ',', $selectors );
|
||||
|
||||
$css .= '@media ' . $rule . '{';
|
||||
$css .= $selectors . '{' . $style_data . '}';
|
||||
$css .= '}';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $query_arr['output'] ) && $query_arr['output'] ) {
|
||||
$this->parent->outputCSS .= $css;
|
||||
}
|
||||
|
||||
if ( isset( $query_arr['compiler'] ) && $query_arr['compiler'] ) {
|
||||
$this->parent->compilerCSS .= $css;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* CSS for field output, if set (Remove the noinpection line and fix this function when we drop support for PHP 7.1).
|
||||
*
|
||||
* @param string $style CSS string.
|
||||
*
|
||||
* @noinspection PhpMissingParamTypeInspection
|
||||
*/
|
||||
public function output( $style = '' ) {
|
||||
if ( '' !== $style ) {
|
||||
|
||||
// Force output value into an array.
|
||||
if ( isset( $this->field['output'] ) && ! is_array( $this->field['output'] ) ) {
|
||||
$this->field['output'] = array( $this->field['output'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->field['output'] ) && is_array( $this->field['output'] ) ) {
|
||||
if ( isset( $this->field['output']['important'] ) ) {
|
||||
if ( $this->field['output']['important'] ) {
|
||||
$style = str_replace( ';', ' !important;', $style );
|
||||
}
|
||||
unset( $this->field['output']['important'] );
|
||||
}
|
||||
|
||||
$keys = implode( ',', $this->field['output'] );
|
||||
$this->parent->outputCSS .= $keys . '{' . $style . '}';
|
||||
}
|
||||
|
||||
// Force compiler value into an array.
|
||||
if ( isset( $this->field['compiler'] ) && ! is_array( $this->field['compiler'] ) ) {
|
||||
$this->field['compiler'] = array( $this->field['compiler'] );
|
||||
}
|
||||
|
||||
if ( isset( $this->field['compiler']['important'] ) ) {
|
||||
if ( $this->field['compiler']['important'] ) {
|
||||
$style = str_replace( ';', ' !important;', $style );
|
||||
}
|
||||
unset( $this->field['compiler']['important'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $this->field['compiler'] ) && is_array( $this->field['compiler'] ) ) {
|
||||
$keys = implode( ',', $this->field['compiler'] );
|
||||
$this->parent->compilerCSS .= $keys . '{' . $style . '}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*
|
||||
* @param mixed $data CSS data.
|
||||
*/
|
||||
public function css_style( $data ) {}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*/
|
||||
public function set_defaults() {}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*/
|
||||
public function render() {}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*/
|
||||
public function enqueue() {}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*/
|
||||
public function always_enqueue() {}
|
||||
|
||||
/**
|
||||
* Unused for now.
|
||||
*
|
||||
* @param array $field Field array.
|
||||
* @param string $value Value array.
|
||||
*/
|
||||
public function localize( array $field, string $value = '' ) {}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,605 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework Private Extended Functions Container Class
|
||||
*
|
||||
* @class Redux_Functions_Ex
|
||||
* @since 3.0.0
|
||||
* @package Redux_Framework/Classes
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Functions_Ex', false ) ) {
|
||||
|
||||
/**
|
||||
* Redux Functions Class
|
||||
* A Class of useful functions that can/should be shared among all Redux files.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Redux_Functions_Ex {
|
||||
|
||||
/**
|
||||
* What is this for?
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $args;
|
||||
|
||||
/**
|
||||
* Enqueue Font Awesome.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function enqueue_font_awesome() {
|
||||
wp_enqueue_style(
|
||||
'font-awesome',
|
||||
Redux_Core::$url . 'assets/font-awesome/css/all' . Redux_Functions::is_min() . '.css',
|
||||
array(),
|
||||
'6.5.1'
|
||||
);
|
||||
|
||||
wp_enqueue_style(
|
||||
'font-awesome-4-shims',
|
||||
Redux_Core::$url . 'assets/font-awesome/css/v4-shims' . Redux_Functions::is_min() . '.css',
|
||||
array(),
|
||||
'6.5.1'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Elusive Font.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function enqueue_elusive_font() {
|
||||
wp_enqueue_style(
|
||||
'redux-elusive-icon',
|
||||
Redux_Core::$url . 'assets/css/vendor/elusive-icons' . Redux_Functions::is_min() . '.css',
|
||||
array(),
|
||||
'2.0.0'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shim to load Extendify for backward compatibility.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function load_extendify_css() {
|
||||
add_action( 'enqueue_block_editor_assets', array( __CLASS__, 'block_editor_styles' ), 99 );
|
||||
add_action( 'wp_enqueue_scripts', array( __CLASS__, 'frontend_init' ), 10 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Shim to enqueue Extendify CSS in the block editor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function block_editor_styles() {
|
||||
wp_enqueue_style(
|
||||
'redux-editor-styles',
|
||||
Redux_Core::$url . 'assets/css/extendify-utilities.css',
|
||||
array(),
|
||||
Redux_Core::$version
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scripts to enqueue on the frontend
|
||||
*/
|
||||
public static function frontend_init() {
|
||||
wp_enqueue_style(
|
||||
'redux-extendify-styles',
|
||||
Redux_Core::$url . 'assets/css/extendify-utilities.css',
|
||||
array(),
|
||||
Redux_Core::$version
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Output alpha data tag for Iris alpha color picker, if enabled.
|
||||
*
|
||||
* @param array $data Data array.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function output_alpha_data( array $data ): string {
|
||||
$index = null;
|
||||
|
||||
extract( $data ); // phpcs:ignore WordPress.PHP.DontExtract
|
||||
|
||||
$value = false;
|
||||
|
||||
if ( isset( $field['color_alpha'] ) && $field['color_alpha'] ) {
|
||||
if ( is_array( $field['color_alpha'] ) ) {
|
||||
$value = $field['color_alpha'][ $index ] ?? false;
|
||||
} else {
|
||||
$value = $field['color_alpha'];
|
||||
}
|
||||
}
|
||||
|
||||
return 'data-alpha-enabled="' . (bool) esc_attr( $value ) . '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the string into variables without the max_input_vars limitation.
|
||||
*
|
||||
* @param string $str String of data.
|
||||
*
|
||||
* @return array|false $result
|
||||
* @since 3.5.7.11
|
||||
* @author harunbasic
|
||||
* @access private
|
||||
*/
|
||||
public static function parse_str( string $str ) {
|
||||
if ( '' === $str ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$pairs = explode( '&', $str );
|
||||
|
||||
foreach ( $pairs as $pair ) {
|
||||
// use the original parse_str() on each element.
|
||||
parse_str( $pair, $params );
|
||||
|
||||
$k = key( $params );
|
||||
|
||||
if ( ! isset( $result[ $k ] ) ) {
|
||||
$result += $params;
|
||||
} elseif ( is_array( $result[ $k ] ) && is_array( $params[ $k ] ) ) {
|
||||
$result[ $k ] = self::array_merge_recursive_distinct( $result[ $k ], $params[ $k ] );
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge arrays without converting values with duplicate keys to arrays as array_merge_recursive does.
|
||||
* As seen here http://php.net/manual/en/function.array-merge-recursive.php#92195
|
||||
*
|
||||
* @param array $array1 array one.
|
||||
* @param array $array2 array two.
|
||||
*
|
||||
* @return array $merged
|
||||
* @since 3.5.7.11
|
||||
* @author harunbasic
|
||||
* @access private
|
||||
*/
|
||||
public static function array_merge_recursive_distinct( array $array1, array $array2 ): array {
|
||||
$merged = $array1;
|
||||
|
||||
foreach ( $array2 as $key => $value ) {
|
||||
|
||||
if ( is_array( $value ) && isset( $merged[ $key ] ) && is_array( $merged[ $key ] ) ) {
|
||||
$merged[ $key ] = self::array_merge_recursive_distinct( $merged[ $key ], $value );
|
||||
} elseif ( is_numeric( $key ) && isset( $merged[ $key ] ) ) {
|
||||
$merged[] = $value;
|
||||
} else {
|
||||
$merged[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Records calling function.
|
||||
*
|
||||
* @param string $opt_name Panel opt_name.
|
||||
*/
|
||||
public static function record_caller( string $opt_name = '' ) {
|
||||
global $pagenow;
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
if ( ! ( 'options-general.php' === $pagenow && isset( $_GET['page'] ) && ( 'redux-framework' === $_GET['page'] || 'health-check' === $_GET['page'] ) ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions
|
||||
$caller = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1]['file'];
|
||||
|
||||
if ( ! empty( $caller ) && ! empty( $opt_name ) && class_exists( 'Redux_Core' ) ) {
|
||||
if ( ! isset( Redux_Core::$callers[ $opt_name ] ) ) {
|
||||
Redux_Core::$callers[ $opt_name ] = array();
|
||||
}
|
||||
|
||||
if ( strpos( $caller, 'class-redux-' ) !== false || strpos( $caller, 'redux-core/framework.php' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! in_array( $caller, Redux_Core::$callers[ $opt_name ], true ) ) {
|
||||
Redux_Core::$callers[ $opt_name ][] = $caller;
|
||||
}
|
||||
|
||||
if ( ! empty( self::$args[ $opt_name ]['callers'] ) && ! in_array( $caller, self::$args[ $opt_name ]['callers'], true ) ) {
|
||||
self::$args[ $opt_name ]['callers'][] = $caller;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize path.
|
||||
*
|
||||
* @param string $path Path to normalize.
|
||||
*
|
||||
* @return string|string[]|null
|
||||
*/
|
||||
public static function wp_normalize_path( string $path = '' ) {
|
||||
if ( function_exists( 'wp_normalize_path' ) ) {
|
||||
$path = wp_normalize_path( $path );
|
||||
} else {
|
||||
// Shim for pre WP 3.9.
|
||||
$path = str_replace( '\\', '/', $path );
|
||||
$path = preg_replace( '|(?<=.)/+|', '/', $path );
|
||||
|
||||
if ( ':' === substr( $path, 1, 1 ) ) {
|
||||
$path = ucfirst( $path );
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action to add generator tag to page HEAD.
|
||||
*/
|
||||
public static function generator() {
|
||||
add_action( 'wp_head', array( 'Redux_Functions_Ex', 'meta_tag' ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Callback for wp_head hook to add meta tag.
|
||||
*/
|
||||
public static function meta_tag() {
|
||||
echo '<meta name="generator" content="Redux ' . esc_html( Redux_Core::$version ) . '" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Run URL through a ssl check.
|
||||
*
|
||||
* @param string $url URL to check.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function verify_url_protocol( string $url ): string {
|
||||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
|
||||
$protocol = ! empty( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] || ( ! empty( $_SERVER['SERVER_PORT'] ) && 443 === $_SERVER['SERVER_PORT'] ) ? 'https://' : 'http://';
|
||||
|
||||
if ( ! empty( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
|
||||
$new_protocol = sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) ) . '://'; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated
|
||||
if ( 'http://' === $protocol && $new_protocol !== $protocol && false === strpos( $url, $new_protocol ) ) {
|
||||
$url = str_replace( $protocol, $new_protocol, $url );
|
||||
}
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check s.
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public static function s(): bool {
|
||||
if ( ! get_option( 'redux_p' . 'ro_lic' . 'ense_key', false ) ) { // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
|
||||
$s = get_option( 'redux_p' . 'ro_l' . 'icense_status', false ); // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
|
||||
|
||||
if ( in_array( $s, array( 'valid', 'site_inactive' ), true ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is file in theme.
|
||||
*
|
||||
* @param string $file File to check.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function file_in_theme( string $file ): bool {
|
||||
$file_path = self::wp_normalize_path( dirname( $file ) );
|
||||
|
||||
if ( strpos( $file_path, self::wp_normalize_path( get_template_directory() ) ) !== false ) {
|
||||
return true;
|
||||
} elseif ( strpos( $file_path, self::wp_normalize_path( get_stylesheet_directory() ) ) !== false ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Redux embedded inside a plugin?
|
||||
*
|
||||
* @param string $file File to check.
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public static function is_inside_plugin( string $file ) {
|
||||
$file = self::wp_normalize_path( $file );
|
||||
$plugin_basename = self::wp_normalize_path( plugin_basename( $file ) );
|
||||
|
||||
if ( self::file_in_theme( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $plugin_basename !== $file ) {
|
||||
$slug = explode( '/', $plugin_basename );
|
||||
$slug = $slug[0];
|
||||
|
||||
return array(
|
||||
'slug' => $slug,
|
||||
'basename' => $plugin_basename,
|
||||
'path' => $file,
|
||||
'url' => self::verify_url_protocol( plugins_url( $plugin_basename ) ),
|
||||
'real_path' => self::wp_normalize_path( dirname( realpath( $file ) ) ),
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is Redux embedded in a theme?
|
||||
*
|
||||
* @param string $file File to check.
|
||||
*
|
||||
* @return array|bool
|
||||
*/
|
||||
public static function is_inside_theme( string $file = '' ) {
|
||||
|
||||
if ( ! self::file_in_theme( $file ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$theme_paths = array(
|
||||
self::wp_normalize_path( get_template_directory() ) => get_template_directory_uri(),
|
||||
// parent.
|
||||
self::wp_normalize_path( get_stylesheet_directory() ) => get_stylesheet_directory_uri(),
|
||||
// child.
|
||||
);
|
||||
|
||||
$theme_paths = array_unique( $theme_paths );
|
||||
$file_path = self::wp_normalize_path( $file );
|
||||
|
||||
$filename = explode( DIRECTORY_SEPARATOR, $file );
|
||||
|
||||
end( $filename );
|
||||
|
||||
$filename = prev( $filename );
|
||||
|
||||
foreach ( $theme_paths as $theme_path => $url ) {
|
||||
$real_path = self::wp_normalize_path( realpath( $theme_path ) );
|
||||
|
||||
if ( empty( $real_path ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( strpos( $file_path, $real_path ) !== false ) {
|
||||
$slug = explode( '/', $theme_path );
|
||||
$slug = end( $slug );
|
||||
$relative_path = explode( $slug . '/', dirname( $file_path ) );
|
||||
$relative_path = $relative_path[1];
|
||||
$data = array(
|
||||
'slug' => $slug,
|
||||
'path' => trailingslashit( trailingslashit( $theme_path ) . $relative_path ) . $filename,
|
||||
'real_path' => trailingslashit( trailingslashit( $real_path ) . $relative_path ) . $filename,
|
||||
'url' => self::verify_url_protocol( trailingslashit( trailingslashit( $url ) . $relative_path ) . $filename ),
|
||||
'basename' => trailingslashit( $slug ) . trailingslashit( $relative_path ) . $filename,
|
||||
);
|
||||
$data['realpath'] = $data['real_path']; // Shim for old extensions.
|
||||
|
||||
if ( count( $theme_paths ) > 1 ) {
|
||||
$key = array_search( $theme_path, $theme_paths, true );
|
||||
|
||||
if ( false !== $key ) {
|
||||
unset( $theme_paths[ $key ] );
|
||||
}
|
||||
|
||||
$theme_paths_end = end( $theme_paths );
|
||||
$parent_slug_end = explode( '/', $theme_paths_end );
|
||||
$parent_slug_end = end( $parent_slug_end );
|
||||
|
||||
$data['parent_slug'] = $parent_slug_end;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to fix 3.x and 4 compatibility for extensions
|
||||
*
|
||||
* @param object $extension The extension parent object.
|
||||
* @param string $path - Path of the file.
|
||||
* @param string $ext_class - Extension class name.
|
||||
* @param string $new_class_name - New dynamic class name.
|
||||
* @param string $name extension name.
|
||||
*
|
||||
* @return object - Extended field class.
|
||||
*/
|
||||
public static function extension_compatibility( $extension, string $path, string $ext_class, string $new_class_name, string $name ) {
|
||||
if ( empty( $new_class_name ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$upload_dir = ReduxFramework::$_upload_dir . '/extension_compatibility/';
|
||||
|
||||
if ( ! file_exists( $upload_dir . $ext_class . '.php' ) ) {
|
||||
if ( ! is_dir( $upload_dir ) ) {
|
||||
$extension->filesystem->mkdir( $upload_dir );
|
||||
$extension->filesystem->put_contents( $upload_dir . 'index.php', '<?php // Silence is golden.' );
|
||||
}
|
||||
if ( ! class_exists( $ext_class ) ) {
|
||||
require_once $path;
|
||||
}
|
||||
if ( ! file_exists( $upload_dir . $new_class_name . '.php' ) ) {
|
||||
$class_file = '<?php' . PHP_EOL . PHP_EOL .
|
||||
'class {{ext_class}} extends Redux_Extension_Abstract {' . PHP_EOL .
|
||||
' private $c;' . PHP_EOL .
|
||||
' public function __construct( $parent, $path, $ext_class ) {' . PHP_EOL .
|
||||
' $this->c = $parent->extensions[\'' . $name . '\'];' . PHP_EOL .
|
||||
' // Add all the params of the Abstract to this instance.' . PHP_EOL .
|
||||
' foreach( get_object_vars( $this->c ) as $key => $value ) {' . PHP_EOL .
|
||||
' $this->$key = $value;' . PHP_EOL .
|
||||
' }' . PHP_EOL .
|
||||
' parent::__construct( $parent, $path );' . PHP_EOL .
|
||||
' }' . PHP_EOL .
|
||||
' // fake "extends Redux_Extension_Abstract\" using magic function' . PHP_EOL .
|
||||
' public function __call( $method, $args ) {' . PHP_EOL .
|
||||
' return call_user_func_array( array( $this->c, $method ), $args );' . PHP_EOL .
|
||||
' }' . PHP_EOL .
|
||||
'}' . PHP_EOL;
|
||||
$template = str_replace( '{{ext_class}}', $new_class_name, $class_file );
|
||||
// phpcs:ignore Squiz.PHP.CommentedOutCode.Found
|
||||
// $parent->filesystem->put_contents( $upload_dir . $new_class_name . '.php', $template );
|
||||
}
|
||||
|
||||
if ( file_exists( $upload_dir . $new_class_name . '.php' ) ) {
|
||||
if ( ! class_exists( $new_class_name ) ) {
|
||||
require_once $upload_dir . $new_class_name . '.php';
|
||||
}
|
||||
if ( class_exists( $new_class_name ) ) {
|
||||
return new $new_class_name( $extension, $path, $ext_class );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to merge two deep arrays.
|
||||
*
|
||||
* @param array $a First array to deeply merge.
|
||||
* @param array $b Second array to deeply merge.
|
||||
*
|
||||
* @return array - Deep merge of the two arrays.
|
||||
*/
|
||||
public static function nested_wp_parse_args( array &$a, array $b ): array {
|
||||
$result = $b;
|
||||
|
||||
foreach ( $a as $k => &$v ) {
|
||||
if ( is_array( $v ) && isset( $result[ $k ] ) ) {
|
||||
$result[ $k ] = self::nested_wp_parse_args( $v, $result[ $k ] );
|
||||
} else {
|
||||
$result[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback key
|
||||
*/
|
||||
public static function hash_key(): string {
|
||||
$key = defined( 'AUTH_KEY' ) ? AUTH_KEY : get_site_url();
|
||||
$key .= defined( 'SECURE_AUTH_KEY' ) ? SECURE_AUTH_KEY : '';
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a class path to be autoloaded.
|
||||
* Registers a namespace to be autoloaded from a given path, using the
|
||||
* WordPress/HM-style filenames (`class-{name}.php`).
|
||||
*
|
||||
* @link https://engineering.hmn.md/standards/style/php/#file-naming
|
||||
*
|
||||
* @param string $prefix Prefix to autoload from.
|
||||
* @param string $path Path to validate.
|
||||
*/
|
||||
public static function register_class_path( string $prefix = '', string $path = '' ) {
|
||||
if ( ! class_exists( 'Redux_Autoloader' ) ) {
|
||||
require_once Redux_Path::get_path( '/inc/classes/class-redux-autoloader.php' );
|
||||
}
|
||||
|
||||
$loader = new Redux_Autoloader( $prefix, $path );
|
||||
|
||||
spl_autoload_register( array( $loader, 'load' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string starts with a string.
|
||||
*
|
||||
* @param string $haystack Full string.
|
||||
* @param string $needle String to check if it starts with.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function string_starts_with( string $haystack, string $needle ): bool {
|
||||
$length = strlen( $needle );
|
||||
|
||||
return substr( $haystack, 0, $length ) === $needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string ends with a string.
|
||||
*
|
||||
* @param string $haystack Full string.
|
||||
* @param string $needle String to check if it starts with.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function string_ends_with( string $haystack, string $needle ): bool {
|
||||
$length = strlen( $needle );
|
||||
|
||||
if ( ! $length ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return substr( $haystack, - $length ) === $needle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if Extendify plugin is installed.
|
||||
*
|
||||
* @param string $name Plugin name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_plugin_installed( string $name ): bool {
|
||||
if ( ! function_exists( 'get_plugins' ) ) {
|
||||
include_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
foreach ( get_plugins() as $plugin => $data ) {
|
||||
if ( $data['TextDomain'] === $name ) {
|
||||
return $plugin;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is plugin active.
|
||||
*
|
||||
* @param string $name Plugin name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function is_plugin_active( string $name ): bool {
|
||||
if ( in_array( $name . '/' . $name . '.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,373 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework Private Functions Container Class
|
||||
*
|
||||
* @class Redux_Functions
|
||||
* @package Redux_Framework/Classes
|
||||
* @since 3.0.0
|
||||
*/
|
||||
|
||||
// Exit if accessed directly.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Functions', false ) ) {
|
||||
|
||||
/**
|
||||
* Redux Functions Class
|
||||
* A Class of useful functions that can/should be shared among all Redux files.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
class Redux_Functions {
|
||||
|
||||
/**
|
||||
* ReduxFramework object pointer.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public static $parent;
|
||||
|
||||
/**
|
||||
* ReduxFramework shim object pointer.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public static $_parent; // phpcs:ignore PSR2.Classes.PropertyDeclaration.Underscore
|
||||
|
||||
/**
|
||||
* Check for the existence of class name via an array of class names.
|
||||
*
|
||||
* @param array $class_names Array of class names.
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function class_exists_ex( array $class_names = array() ) {
|
||||
foreach ( $class_names as $class_name ) {
|
||||
if ( class_exists( $class_name ) ) {
|
||||
return $class_name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the existence of file name via an array of file names.
|
||||
*
|
||||
* @param array $file_names Array of file names.
|
||||
*
|
||||
* @return string|bool
|
||||
*/
|
||||
public static function file_exists_ex( array $file_names = array() ) {
|
||||
foreach ( $file_names as $file_name ) {
|
||||
if ( file_exists( $file_name ) ) {
|
||||
return $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Extract data:
|
||||
* $field = field_array
|
||||
* $value = field values
|
||||
* $core = Redux instance
|
||||
* $mode = pro field init mode */
|
||||
|
||||
/**
|
||||
* Parse args to handle deep arrays. The WP one does not.
|
||||
*
|
||||
* @param array|string $args Array of args.
|
||||
* @param array $defaults Defaults array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function parse_args( $args, array $defaults ): array {
|
||||
$arr = array();
|
||||
|
||||
if ( ! is_array( $args ) ) {
|
||||
$arr[] = $args;
|
||||
} else {
|
||||
$arr = $args;
|
||||
}
|
||||
|
||||
$result = $defaults;
|
||||
|
||||
foreach ( $arr as $k => $v ) {
|
||||
if ( is_array( $v ) && isset( $result[ $k ] ) ) {
|
||||
$result[ $k ] = self::parse_args( $v, $result[ $k ] );
|
||||
} else {
|
||||
$result[ $k ] = $v;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated: Return min tag for JS and CSS files in dev_mode.
|
||||
*
|
||||
* @deprecated No longer using camelCase naming conventions.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function isMin(): string { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
|
||||
return self::is_min();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return min tag for JS and CSS files in dev_mode.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function is_min(): string {
|
||||
$min = '.min';
|
||||
$dev_mode = false;
|
||||
|
||||
$instances = Redux::all_instances();
|
||||
|
||||
if ( ! empty( $instances ) ) {
|
||||
foreach ( $instances as $instance ) {
|
||||
|
||||
if ( empty( self::$parent ) ) {
|
||||
self::$parent = $instance;
|
||||
self::$_parent = self::$parent;
|
||||
}
|
||||
if ( ! empty( $instance->args['dev_mode'] ) ) {
|
||||
$dev_mode = true;
|
||||
self::$parent = $instance;
|
||||
self::$_parent = self::$parent;
|
||||
}
|
||||
}
|
||||
if ( $dev_mode ) {
|
||||
$min = '';
|
||||
}
|
||||
}
|
||||
|
||||
return $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CSS from an output/compiler array
|
||||
*
|
||||
* @param array $css_array CSS data.
|
||||
* @param string $style CSS style.
|
||||
* @param string $value CSS values.
|
||||
*
|
||||
* @return string CSS string
|
||||
* @since 3.2.8
|
||||
* @access private
|
||||
*/
|
||||
public static function parse_css( array $css_array = array(), string $style = '', string $value = '' ): string {
|
||||
|
||||
// Something wrong happened.
|
||||
if ( 0 === count( $css_array ) ) {
|
||||
return '';
|
||||
} else {
|
||||
$css = '';
|
||||
$important = false;
|
||||
|
||||
if ( isset( $css_array['important'] ) && true === $css_array['important'] ) {
|
||||
$important = '!important';
|
||||
|
||||
unset( $css_array['important'] );
|
||||
}
|
||||
|
||||
foreach ( $css_array as $element => $selector ) {
|
||||
|
||||
// The old way.
|
||||
if ( 0 === $element ) {
|
||||
return self::the_old_way( $css_array, $style );
|
||||
}
|
||||
|
||||
// New way continued.
|
||||
$css_style = $element . ':' . $value . $important . ';';
|
||||
|
||||
$css .= $selector . '{' . $css_style . '}';
|
||||
}
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CSS shim.
|
||||
*
|
||||
* @param array $css_array CSS data.
|
||||
* @param string $style CSS style.
|
||||
* @param string $value CSS values.
|
||||
*
|
||||
* @deprecated 4.0
|
||||
*
|
||||
* @return string CSS string
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
*/
|
||||
public static function parseCSS( array $css_array = array(), string $style = '', string $value = '' ): string { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', __CLASS__ . '::parse_css( $css_array, $style, $value )' );
|
||||
|
||||
return self::parse_css( $css_array, $style, $value );
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse CSS the old way, without mode options.
|
||||
*
|
||||
* @param array $css_array CSS data.
|
||||
* @param string $style CSS style.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function the_old_way( array $css_array, string $style ): string {
|
||||
$keys = implode( ',', $css_array );
|
||||
|
||||
return $keys . '{' . $style . '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return s.
|
||||
*
|
||||
* @access public
|
||||
* @since 4.0.0
|
||||
* @return string
|
||||
*/
|
||||
public static function gs(): string {
|
||||
return get_option( 're' . 'dux_p' . 'ro_lic' . 'ense_key', '' ); // phpcs:ignore Generic.Strings.UnnecessaryStringConcat.Found
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated Initialized the WordPress filesystem, if it already isn't.
|
||||
*
|
||||
* @since 3.2.3
|
||||
* @access public
|
||||
* @deprecated NO longer using camelCase naming conventions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function initWpFilesystem() { // phpcs:ignore WordPress.NamingConventions.ValidFunctionName
|
||||
// phpcs:ignore Squiz.Commenting.InlineComment.InvalidEndChar
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', __CLASS__ . '::init_wp_filesystem()' );
|
||||
|
||||
self::init_wp_filesystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialized the WordPress filesystem, if it already isn't.
|
||||
*
|
||||
* @since 3.2.3
|
||||
* @access public
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init_wp_filesystem() {
|
||||
global $wp_filesystem;
|
||||
|
||||
// Initialize the WordPress filesystem, no more using file_put_contents function.
|
||||
if ( empty( $wp_filesystem ) ) {
|
||||
require_once ABSPATH . '/wp-includes/pluggable.php';
|
||||
require_once ABSPATH . '/wp-admin/includes/file.php';
|
||||
|
||||
WP_Filesystem();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TRU.
|
||||
*
|
||||
* @param string $string .
|
||||
* @param string $opt_name .
|
||||
*
|
||||
* @deprecated Ad Remover extension no longer necessary.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function tru( string $string, string $opt_name ) {
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* DAT.
|
||||
*
|
||||
* @param string $fname .
|
||||
* @param string $opt_name .
|
||||
*
|
||||
* @deprecated Ad Remover extension no longer necessary.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function dat( string $fname, string $opt_name ) {
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* BUB.
|
||||
*
|
||||
* @param string $fname .
|
||||
* @param string $opt_name .
|
||||
*
|
||||
* @deprecated Ad Remover extension no longer necessary.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function bub( string $fname, string $opt_name ) {
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* YO.
|
||||
*
|
||||
* @param string $fname .
|
||||
* @param string $opt_name .
|
||||
*
|
||||
* @deprecated Ad Remover extension no longer necessary.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function yo( string $fname, string $opt_name ) {
|
||||
_deprecated_function( __CLASS__ . '::' . __FUNCTION__, '4.0', '' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize camelCase keys in an array, makes then snake_case.
|
||||
*
|
||||
* @param array $arr Array of keys.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function sanitize_camel_case_array_keys( array $arr ): array {
|
||||
$keys = array_keys( $arr );
|
||||
$values = array_values( $arr );
|
||||
|
||||
$result = preg_replace_callback(
|
||||
'/[A-Z]/',
|
||||
function ( $matches ) {
|
||||
return '-' . Redux_Core::strtolower( $matches[0] );
|
||||
},
|
||||
$keys
|
||||
);
|
||||
|
||||
return array_combine( $result, $values );
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an array into an html data string.
|
||||
*
|
||||
* @param array $data example input: array('id'=>'true').
|
||||
*
|
||||
* @return string $data_string example output: data-id='true'
|
||||
*/
|
||||
public static function create_data_string( array $data = array() ): string {
|
||||
$data_string = '';
|
||||
|
||||
foreach ( $data as $key => $value ) {
|
||||
if ( is_array( $value ) ) {
|
||||
$value = implode( '|', $value );
|
||||
}
|
||||
|
||||
$data_string .= ' data-' . $key . '=' . Redux_Helpers::make_bool_str( $value ) . ' ';
|
||||
}
|
||||
|
||||
return $data_string;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
/**
|
||||
* Load the plugin text domain for translation.
|
||||
*
|
||||
* @package Redux Framework/Classes
|
||||
* @since 3.0.5
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_I18n', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_I18n
|
||||
*/
|
||||
class Redux_I18n extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_I18n constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
add_action( 'init', array( $this, 'load' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load translations.
|
||||
*/
|
||||
public function load() {
|
||||
$domain = 'redux-framework';
|
||||
|
||||
unload_textdomain( $domain );
|
||||
|
||||
$core = $this->core();
|
||||
|
||||
/**
|
||||
* Locale for text domain
|
||||
* filter 'redux/textdomain/basepath/{opt_name}'
|
||||
*/
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$locale = apply_filters( 'redux/locale', get_locale(), 'redux-framework' );
|
||||
$mofile = $domain . '-' . $locale . '.mo';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$basepath = apply_filters( "redux/textdomain/basepath/{$core->args['opt_name']}", Redux_Core::$dir );
|
||||
|
||||
$loaded = load_textdomain( $domain, $basepath . 'languages/' . $mofile );
|
||||
|
||||
if ( ! $loaded ) {
|
||||
$mofile = WP_LANG_DIR . '/plugins/' . $mofile;
|
||||
|
||||
load_textdomain( $domain, $mofile );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php // phpcs:ignore WordPress.Files.FileName
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Installer_Muter', false ) ) {
|
||||
|
||||
/**
|
||||
* Redux_Installer_Muter.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*/
|
||||
class Redux_Installer_Muter extends WP_Upgrader_Skin {
|
||||
|
||||
/**
|
||||
* Suppress feedback.
|
||||
*
|
||||
* @param string|null $feedback A string.
|
||||
* @param array|null ...$args Passed args.
|
||||
*
|
||||
* @return void
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public function feedback( $feedback, ...$args ) {
|
||||
/* no output */
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Framework Instance Container Class
|
||||
* Automatically captures and stores all instances
|
||||
* of ReduxFramework at instantiation.
|
||||
*
|
||||
* @package Redux_Framework/Classes
|
||||
* @subpackage Core
|
||||
* @noinspection PhpIgnoredClassAliasDeclaration
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Instances', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Instances
|
||||
*/
|
||||
class Redux_Instances {
|
||||
|
||||
/**
|
||||
* ReduxFramework instances
|
||||
*
|
||||
* @var ReduxFramework[]
|
||||
*/
|
||||
private static $instances;
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
* Get Redux_Instances instance
|
||||
* OR an instance of ReduxFramework by [opt_name]
|
||||
*
|
||||
* @param string|false $opt_name the defined opt_name.
|
||||
*
|
||||
* @return ReduxFramework|Redux_Instances class instance
|
||||
*/
|
||||
public static function get_instance( $opt_name = false ) {
|
||||
|
||||
if ( $opt_name && ! empty( self::$instances[ $opt_name ] ) ) {
|
||||
return self::$instances[ $opt_name ];
|
||||
}
|
||||
|
||||
return new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shim for old get_redux_instance method.
|
||||
*
|
||||
* @param string|false $opt_name the defined opt_name.
|
||||
*
|
||||
* @return ReduxFramework class instance
|
||||
*/
|
||||
public static function get_redux_instance( $opt_name = '' ) {
|
||||
return self::get_instance( $opt_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all instantiated ReduxFramework instances (so far)
|
||||
*
|
||||
* @return array|null [type] [description]
|
||||
*/
|
||||
public static function get_all_instances(): ?array {
|
||||
return self::$instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redux_Instances constructor.
|
||||
*
|
||||
* @param mixed $redux_framework Is object.
|
||||
*/
|
||||
public function __construct( $redux_framework = false ) {
|
||||
if ( false !== $redux_framework ) {
|
||||
$this->store( $redux_framework );
|
||||
} else {
|
||||
add_action( 'redux/construct', array( $this, 'store' ), 5, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action hook callback.
|
||||
*
|
||||
* @param object $redux_framework Pointer.
|
||||
*/
|
||||
public function store( $redux_framework ) {
|
||||
if ( $redux_framework instanceof ReduxFramework ) {
|
||||
$key = $redux_framework->args['opt_name'];
|
||||
self::$instances[ $key ] = $redux_framework;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'ReduxFrameworkInstances' ) ) {
|
||||
class_alias( 'Redux_Instances', 'ReduxFrameworkInstances' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'get_redux_instance' ) ) {
|
||||
/**
|
||||
* Shim function that some theme oddly used.
|
||||
*
|
||||
* @param string|false $opt_name the defined opt_name.
|
||||
*
|
||||
* @return ReduxFramework class instance
|
||||
*/
|
||||
function get_redux_instance( $opt_name ) {
|
||||
return Redux_Instances::get_instance( $opt_name );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'get_all_redux_instances' ) ) {
|
||||
/**
|
||||
* Fetch all instances of ReduxFramework
|
||||
* as an associative array.
|
||||
*
|
||||
* @return array format ['opt_name' => $ReduxFramework]
|
||||
*/
|
||||
function get_all_redux_instances(): ?array {
|
||||
return Redux_Instances::get_all_instances();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Network Class
|
||||
*
|
||||
* @class Redux_Network
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Network', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Network
|
||||
*/
|
||||
class Redux_Network extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_Network constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
if ( 'network' === $redux->args['database'] && $redux->args['network_admin'] ) {
|
||||
add_action(
|
||||
'network_admin_edit_redux_' . $redux->args['opt_name'],
|
||||
array(
|
||||
$this,
|
||||
'save_network_page',
|
||||
),
|
||||
10,
|
||||
0
|
||||
);
|
||||
|
||||
// phpcs:ignore Generic.Strings.UnnecessaryStringConcat
|
||||
add_action( 'admin' . '_bar' . '_menu', array( $this, 'network_admin_bar' ), 999 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add node to network admin bar.
|
||||
*
|
||||
* @param object $wp_admin_bar Admin bar.
|
||||
*/
|
||||
public function network_admin_bar( $wp_admin_bar ) {
|
||||
$core = $this->core();
|
||||
|
||||
$args = array(
|
||||
'id' => $core->args['opt_name'] . '_network_admin',
|
||||
'title' => $core->args['menu_title'],
|
||||
'parent' => 'network-admin',
|
||||
'href' => network_admin_url( 'settings.php' ) . '?page=' . $core->args['page_slug'],
|
||||
'meta' => array( 'class' => 'redux-network-admin' ),
|
||||
);
|
||||
|
||||
$wp_admin_bar->add_node( $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves network options.
|
||||
*/
|
||||
public function save_network_page() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( isset( $_POST[ $core->args['opt_name'] ] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$opt_name = sanitize_text_field( wp_unslash( $_POST[ $core->args['opt_name'] ] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
}
|
||||
|
||||
$data = $core->options_class->validate_options( $opt_name );
|
||||
|
||||
if ( ! empty( $data ) ) {
|
||||
$core->options_class->set( $data );
|
||||
}
|
||||
|
||||
wp_safe_redirect(
|
||||
add_query_arg(
|
||||
array(
|
||||
'page' => $core->args['page_slug'],
|
||||
'updated' => 'true',
|
||||
),
|
||||
network_admin_url( 'settings.php' )
|
||||
)
|
||||
);
|
||||
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,209 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Option Defaults Class
|
||||
*
|
||||
* @class Redux_Options_Defaults
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Classes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Options_Defaults', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Options_Defaults
|
||||
*/
|
||||
class Redux_Options_Defaults {
|
||||
|
||||
/**
|
||||
* Default options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options_defaults = array();
|
||||
|
||||
/**
|
||||
* Field array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fields = array();
|
||||
|
||||
/**
|
||||
* Is repeater group flag.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_repeater_group = false;
|
||||
|
||||
/**
|
||||
* Repeater ID.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $repeater_id = '';
|
||||
|
||||
/**
|
||||
* Creates a default options array.
|
||||
*
|
||||
* @param string $opt_name Panel opt_name.
|
||||
* @param array $sections Panel sections array.
|
||||
* @param null $wp_data_class WordPress data class.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function default_values( string $opt_name = '', array $sections = array(), $wp_data_class = null ): array {
|
||||
// We want it to be clean each time this is run.
|
||||
$this->options_defaults = array();
|
||||
|
||||
// Check to make sure we're not in the select2 action, we don't want to fetch any there.
|
||||
if ( isset( $_REQUEST['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
$action = sanitize_text_field( wp_unslash( $_REQUEST['action'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( Redux_Functions_Ex::string_ends_with( $action, '_select2' ) && Redux_Functions_Ex::string_starts_with( $action, 'redux_' ) ) {
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $sections ) ) {
|
||||
|
||||
// Fill the cache.
|
||||
foreach ( $sections as $sk => $section ) {
|
||||
if ( ! isset( $section['id'] ) ) {
|
||||
if ( ! is_numeric( $sk ) || ! isset( $section['title'] ) ) {
|
||||
$section['id'] = $sk;
|
||||
} else {
|
||||
$section['id'] = sanitize_title( $section['title'], $sk );
|
||||
}
|
||||
|
||||
$sections[ $sk ] = $section;
|
||||
}
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $field ) {
|
||||
if ( empty( $field['id'] ) && empty( $field['type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->field_default_values( $opt_name, $field, $wp_data_class, false );
|
||||
|
||||
if ( 'tabbed' === $field['type'] ) {
|
||||
if ( ! empty( $field['tabs'] ) ) {
|
||||
foreach ( $field['tabs'] as $val ) {
|
||||
if ( ! empty( $val['fields'] ) ) {
|
||||
foreach ( $val['fields'] as $f ) {
|
||||
$this->field_default_values( $opt_name, $f, $wp_data_class, false, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'repeater' === $field['type'] ) {
|
||||
if ( ! empty( $field['fields'] ) ) {
|
||||
foreach ( $field['fields'] as $f ) {
|
||||
$this->field_default_values( $opt_name, $f, $wp_data_class, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->options_defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field default values.
|
||||
*
|
||||
* @param string $opt_name Panel opt_name.
|
||||
* @param array $field Field array.
|
||||
* @param null $wp_data_class WordPress data class.
|
||||
* @param bool $is_repeater Is a repeater field.
|
||||
* @param bool $is_tabbed Is a tabbed field.
|
||||
*/
|
||||
public function field_default_values( string $opt_name = '', array $field = array(), $wp_data_class = null, bool $is_repeater = false, $is_tabbed = false ) {
|
||||
if ( 'repeater' === $field['type'] ) {
|
||||
if ( isset( $field['group_values'] ) && true === $field['group_values'] ) {
|
||||
$this->is_repeater_group = true;
|
||||
$this->repeater_id = $field['id'];
|
||||
}
|
||||
}
|
||||
|
||||
if ( null === $wp_data_class && class_exists( 'Redux_WordPress_Data' ) && ! ( 'select' === $field['type'] && isset( $field['ajax'] ) && $field['ajax'] ) ) {
|
||||
$wp_data_class = new Redux_WordPress_Data( $opt_name );
|
||||
}
|
||||
|
||||
// Detect what field types are being used.
|
||||
if ( ! isset( $this->fields[ $field['type'] ][ $field['id'] ] ) ) {
|
||||
$this->fields[ $field['type'] ][ $field['id'] ] = 1;
|
||||
} else {
|
||||
$this->fields[ $field['type'] ] = array( $field['id'] => 1 );
|
||||
}
|
||||
|
||||
if ( isset( $field['default'] ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$def = apply_filters( "redux/$opt_name/field/{$field['type']}/defaults", $field['default'], $field );
|
||||
|
||||
if ( true === $is_repeater ) {
|
||||
if ( true === $this->is_repeater_group ) {
|
||||
$this->options_defaults[ $this->repeater_id ][ $field['id'] ] = array( $def );
|
||||
} else {
|
||||
$this->options_defaults[ $field['id'] ] = array( $def );
|
||||
}
|
||||
} elseif ( true === $is_tabbed ) {
|
||||
$this->options_defaults[ $field['id'] ] = $def;
|
||||
} else {
|
||||
$this->options_defaults[ $field['id'] ] = $def;
|
||||
}
|
||||
} elseif ( ( 'ace_editor' !== $field['type'] ) && ! ( 'select' === $field['type'] && ! empty( $field['ajax'] ) ) ) {
|
||||
if ( isset( $field['data'] ) ) {
|
||||
if ( ! isset( $field['args'] ) ) {
|
||||
$field['args'] = array();
|
||||
}
|
||||
if ( is_array( $field['data'] ) && ! empty( $field['data'] ) ) {
|
||||
foreach ( $field['data'] as $key => $data ) {
|
||||
if ( ! empty( $data ) ) {
|
||||
if ( ! isset( $field['args'][ $key ] ) ) {
|
||||
$field['args'][ $key ] = array();
|
||||
}
|
||||
if ( null !== $wp_data_class ) {
|
||||
$field['options'][ $key ] = $wp_data_class->get( $data, $field['args'][ $key ], $opt_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ( null !== $wp_data_class ) {
|
||||
$field['options'] = $wp_data_class->get( $field['data'], $field['args'], $opt_name );
|
||||
}
|
||||
|
||||
if ( 'sorter' === $field['type'] && ! empty( $field['data'] ) && is_array( $field['data'] ) ) {
|
||||
if ( ! isset( $field['args'] ) ) {
|
||||
$field['args'] = array();
|
||||
}
|
||||
foreach ( $field['data'] as $key => $data ) {
|
||||
if ( ! isset( $field['args'][ $key ] ) ) {
|
||||
$field['args'][ $key ] = array();
|
||||
}
|
||||
if ( null !== $wp_data_class ) {
|
||||
$field['options'][ $key ] = $wp_data_class->get( $data, $field['args'][ $key ], $opt_name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $field['options'] ) ) {
|
||||
if ( 'sortable' === $field['type'] ) {
|
||||
$this->options_defaults[ $field['id'] ] = ( true === $is_repeater ) ? array( array() ) : array();
|
||||
} elseif ( 'image_select' === $field['type'] ) {
|
||||
$this->options_defaults[ $field['id'] ] = ( true === $is_repeater ) ? array( '' ) : '';
|
||||
} elseif ( 'select' === $field['type'] ) {
|
||||
$this->options_defaults[ $field['id'] ] = ( true === $is_repeater ) ? array( '' ) : '';
|
||||
} else {
|
||||
$this->options_defaults[ $field['id'] ] = ( true === $is_repeater ) ? array( $field['options'] ) : $field['options'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,370 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Output Class
|
||||
*
|
||||
* @class Redux_Output
|
||||
* @version 3.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpConditionCheckedByNextConditionInspection
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Output', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Output
|
||||
*/
|
||||
class Redux_Output extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_Output constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
// Output dynamic CSS.
|
||||
// Frontend: Maybe enqueue dynamic CSS and Google fonts.
|
||||
if ( empty( $this->args['output_location'] ) || in_array( 'frontend', $this->args['output_location'], true ) ) {
|
||||
add_action( 'wp_head', array( $this, 'output_css' ), 150 );
|
||||
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue' ), 150 );
|
||||
}
|
||||
|
||||
// Login page: Maybe enqueue dynamic CSS and Google fonts.
|
||||
if ( in_array( 'login', $this->args['output_location'], true ) ) {
|
||||
add_action( 'login_head', array( $this, 'output_css' ), 150 );
|
||||
add_action( 'login_enqueue_scripts', array( $this, 'enqueue' ), 150 );
|
||||
}
|
||||
|
||||
// Admin area: Maybe enqueue dynamic CSS and Google fonts.
|
||||
if ( in_array( 'admin', $this->args['output_location'], true ) ) {
|
||||
add_action( 'admin_head', array( $this, 'output_css' ), 150 );
|
||||
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue' ), 150 );
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/output/{$this->parent->args['opt_name']}/construct", $this );
|
||||
// Useful for adding different locations for CSS output.
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue CSS and Google fonts for front end
|
||||
*
|
||||
* @return void
|
||||
* @throws ReflectionException Exception.
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function enqueue() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( false === $core->args['output'] && false === $core->args['compiler'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $core->sections as $k => $section ) {
|
||||
if ( isset( $section['type'] ) && ( 'divide' === $section['type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $fieldk => $field ) {
|
||||
if ( isset( $field['type'] ) && 'callback' !== $field['type'] ) {
|
||||
$field_classes = array( 'Redux_' . $field['type'], 'ReduxFramework_' . $field['type'] );
|
||||
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
|
||||
if ( false === $field_class ) {
|
||||
if ( ! isset( $field['compiler'] ) ) {
|
||||
$field['compiler'] = '';
|
||||
}
|
||||
|
||||
$field_type = str_replace( '_', '-', $field['type'] );
|
||||
$core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/class-redux-$field_type.php";
|
||||
|
||||
if ( ! file_exists( $core_path ) ) {
|
||||
$core_path = Redux_Core::$dir . "inc/fields/{$field['type']}/field_{$field['type']}.php";
|
||||
}
|
||||
|
||||
$filter_path = $core_path;
|
||||
|
||||
/**
|
||||
* Field class file
|
||||
* filter 'redux/{opt_name}/field/class/{field.type}
|
||||
*
|
||||
* @param string $file field class file.
|
||||
* @param array $field field config data
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$class_file = apply_filters( "redux/{$core->args['opt_name']}/field/class/{$field['type']}", $filter_path, $field );
|
||||
|
||||
if ( $class_file && file_exists( $class_file ) && ( ! class_exists( $field_class ) ) ) {
|
||||
require_once $class_file;
|
||||
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
}
|
||||
}
|
||||
|
||||
$field['default'] = $field['default'] ?? '';
|
||||
$value = $core->options[ $field['id'] ] ?? $field['default'];
|
||||
$style_data = '';
|
||||
|
||||
if ( empty( $field_class ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$field_object = new $field_class( $field, $value, $core );
|
||||
|
||||
if ( ! empty( $core->options[ $field['id'] ] ) && class_exists( $field_class ) && method_exists( $field_class, 'output' ) && $this->can_output_css( $core, $field ) ) {
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$field = apply_filters( "redux/field/{$core->args['opt_name']}/output_css", $field );
|
||||
|
||||
if ( ! empty( $field['output'] ) && ! is_array( $field['output'] ) ) {
|
||||
$field['output'] = array( $field['output'] );
|
||||
}
|
||||
|
||||
if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || isset( $field['media_query'] ) && ! empty( $field['media_query'] ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
|
||||
if ( method_exists( $field_class, 'css_style' ) ) {
|
||||
$style_data = $field_object->css_style( $field_object->value );
|
||||
}
|
||||
}
|
||||
|
||||
if ( null !== $style_data ) {
|
||||
if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || 'typography' === $field['type'] || 'icon_select' === $field['type'] || 'social_profiles' === $field['type'] ) ) {
|
||||
$field_object->output( $style_data );
|
||||
}
|
||||
|
||||
if ( isset( $field['media_query'] ) && ! empty( $field['media_query'] ) ) {
|
||||
$field_object->media_query( $style_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/field/{$core->args['opt_name']}/output_loop", $core, $field, $value, $style_data );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/field/{$core->args['opt_name']}/output_loop/{$field['type']}", $core, $field, $value, $style_data );
|
||||
|
||||
if ( method_exists( $field_class, 'output_variables' ) && $this->can_output_css( $core, $field ) ) {
|
||||
$passed_style_data = $field_object->output_variables( $style_data );
|
||||
$this->output_variables( $core, $section, $field, $value, $passed_style_data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $core->outputCSS ) ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
$core->outputCSS = html_entity_decode( $core->outputCSS, ENT_QUOTES, 'UTF-8' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For use like in the customizer. Stops the output, but passes the CSS in the variable for the compiler.
|
||||
if ( isset( $core->no_output ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! empty( $core->typography ) && filter_var( $core->args['output'], FILTER_VALIDATE_BOOLEAN ) ) {
|
||||
$version = ! empty( $core->transients['last_save'] ) ? $core->transients['last_save'] : '';
|
||||
if ( ! class_exists( 'Redux_Typography' ) ) {
|
||||
require_once Redux_Core::$dir . '/inc/fields/typography/class-redux-typography.php';
|
||||
}
|
||||
$typography = new Redux_Typography( null, null, $core );
|
||||
|
||||
if ( ! $core->args['disable_google_fonts_link'] ) {
|
||||
$url = $typography->make_google_web_font_link( $core->typography );
|
||||
wp_enqueue_style( 'redux-google-fonts-' . $core->args['opt_name'], $url, array(), $version );
|
||||
add_filter( 'style_loader_tag', array( $this, 'add_style_attributes' ), 10, 4 );
|
||||
add_filter( 'wp_resource_hints', array( $this, 'google_fonts_preconnect' ), 10, 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a Google Fonts preconnect link.
|
||||
*
|
||||
* @param array $urls HTML to be added.
|
||||
* @param string $relationship_type Handle name.
|
||||
*
|
||||
* @return array
|
||||
* @since 4.1.15
|
||||
* @access public
|
||||
*/
|
||||
public function google_fonts_preconnect( array $urls, string $relationship_type ): array {
|
||||
if ( 'preconnect' !== $relationship_type ) {
|
||||
return $urls;
|
||||
}
|
||||
$urls[] = array(
|
||||
'rel' => 'preconnect',
|
||||
'href' => 'https://fonts.gstatic.com',
|
||||
'crossorigin',
|
||||
);
|
||||
return $urls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to enhance the google fonts enqueue.
|
||||
*
|
||||
* @param string $html HTML to be added.
|
||||
* @param string $handle Handle name.
|
||||
* @param string $href HREF URL of a script.
|
||||
*
|
||||
* @return string
|
||||
* @since 4.1.15
|
||||
* @access public
|
||||
*/
|
||||
public function add_style_attributes( string $html = '', string $handle = '', string $href = '' ): string {
|
||||
if ( Redux_Functions_Ex::string_starts_with( $handle, 'redux-google-fonts-' ) ) {
|
||||
// Revamp thanks to Harry: https://csswizardry.com/2020/05/the-fastest-google-fonts/.
|
||||
$href = str_replace( array( '|', ' ' ), array( '%7C', '%20' ), urldecode( $href ) );
|
||||
$new_html = '<link rel="preload" as="style" href="' . esc_attr( $href ) . '" />';
|
||||
$new_html .= '<link rel="stylesheet" href="' . esc_attr( $href ) . '" media="print" onload="this.media=\'all\'">'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
|
||||
$new_html .= '<noscript><link rel="stylesheet" href="' . esc_attr( $href ) . '" /></noscript>'; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
|
||||
$html = $new_html;
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to output output_variables to the dynamic output.
|
||||
*
|
||||
* @param object $core ReduxFramework core pointer.
|
||||
* @param array $section Section containing this field.
|
||||
* @param array $field Field object.
|
||||
* @param array|string $value Current value of field.
|
||||
* @param string|null $style_data CSS output string to append to the root output variable.
|
||||
*
|
||||
* @return void
|
||||
* @since 4.0.3
|
||||
* @access public
|
||||
*/
|
||||
private function output_variables( $core, array $section = array(), array $field = array(), $value = array(), ?string $style_data = '' ) {
|
||||
// Let's allow section overrides, please.
|
||||
if ( isset( $section['output_variables'] ) && ! isset( $field['output_variables'] ) ) {
|
||||
$field['output_variables'] = $section['output_variables'];
|
||||
}
|
||||
if ( isset( $section['output_variables_prefix'] ) && ! isset( $field['output_variables_prefix'] ) ) {
|
||||
$field['output_variables_prefix'] = $section['output_variables_prefix'];
|
||||
}
|
||||
if ( isset( $field['output_variables'] ) && $field['output_variables'] ) {
|
||||
$output_variables_prefix = $core->args['output_variables_prefix'];
|
||||
if ( isset( $field['output_variables_prefix'] ) && ! empty( $field['output_variables_prefix'] ) ) {
|
||||
$output_variables_prefix = $field['output_variables_prefix'];
|
||||
} elseif ( isset( $section['output_variables_prefix'] ) && ! empty( $section['output_variables_prefix'] ) ) {
|
||||
$output_variables_prefix = $section['output_variables_prefix'];
|
||||
}
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
$val_pieces = array_filter( $value, 'strlen' );
|
||||
// We don't need to show the Google boolean.
|
||||
if ( 'typography' === $field['type'] && isset( $val_pieces['google'] ) ) {
|
||||
unset( $val_pieces['google'] );
|
||||
}
|
||||
|
||||
foreach ( $val_pieces as $val_key => $val_val ) {
|
||||
$val_key = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] ) . '-' . $val_key;
|
||||
$core->output_variables[ $val_key ] = $val_val;
|
||||
if ( ! empty( $style_data ) ) {
|
||||
$val_key = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
|
||||
$core->output_variables[ $val_key ] = $style_data;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$val_key = $output_variables_prefix . sanitize_title_with_dashes( $field['id'] );
|
||||
|
||||
if ( ! empty( $style_data ) ) {
|
||||
$core->output_variables[ $val_key ] = $style_data;
|
||||
} else {
|
||||
$core->output_variables[ $val_key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output dynamic CSS at the bottom of HEAD
|
||||
*
|
||||
* @return void
|
||||
* @since 3.2.8
|
||||
* @access public
|
||||
*/
|
||||
public function output_css() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( false === $core->args['output'] && false === $core->args['compiler'] && empty( $core->output_variables ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isset( $core->no_output ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! empty( $core->output_variables ) ) {
|
||||
$root_css = ':root{';
|
||||
foreach ( $core->output_variables as $key => $value ) {
|
||||
$root_css .= "$key:$value;";
|
||||
}
|
||||
$root_css .= '}';
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
|
||||
$core->outputCSS = $root_css . $core->outputCSS;
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName
|
||||
if ( ! empty( $core->outputCSS ) && ( true === $core->args['output_tag'] || ( isset( $_POST['customized'] ) && isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'preview-customize_' . wp_get_theme()->get_stylesheet() ) ) ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidVariableName, WordPress.Security.EscapeOutput
|
||||
echo '<style id="' . esc_attr( $core->args['opt_name'] ) . '-dynamic-css" title="dynamic-css" class="redux-options-output">' . $core->outputCSS . '</style>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can Output CSS
|
||||
* Check if a field meets its requirements before outputting to CSS
|
||||
*
|
||||
* @param object $core ReduxFramework core pointer.
|
||||
* @param array $field Field array.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function can_output_css( $core, array $field ): ?bool {
|
||||
$return = true;
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$field = apply_filters( "redux/field/{$core->args['opt_name']}/_can_output_css", $field );
|
||||
|
||||
if ( isset( $field['force_output'] ) && true === $field['force_output'] ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
if ( isset( $field['required'][0] ) ) {
|
||||
if ( ! is_array( $field['required'][0] ) && 3 === count( $field['required'] ) ) {
|
||||
$parent_value = $GLOBALS[ $core->args['global_variable'] ][ $field['required'][0] ] ?? '';
|
||||
$check_value = $field['required'][2];
|
||||
$operation = $field['required'][1];
|
||||
$return = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
|
||||
} elseif ( is_array( $field['required'][0] ) ) {
|
||||
foreach ( $field['required'] as $required ) {
|
||||
if ( isset( $required[0] ) && ! is_array( $required[0] ) && 3 === count( $required ) ) {
|
||||
$parent_value = $GLOBALS[ $core->args['global_variable'] ][ $required[0] ] ?? '';
|
||||
$check_value = $required[2];
|
||||
$operation = $required[1];
|
||||
$return = $core->required_class->compare_value_dependencies( $parent_value, $check_value, $operation );
|
||||
}
|
||||
if ( ! $return ) {
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,431 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Panel Class
|
||||
*
|
||||
* @class Redux_Panel
|
||||
* @version 3.0.0
|
||||
* @package Redux Framework/Classes
|
||||
* @noinspection PhpIgnoredClassAliasDeclaration
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Panel', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Panel
|
||||
*/
|
||||
class Redux_Panel {
|
||||
|
||||
/**
|
||||
* ReduxFramework object pointer.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $parent = null;
|
||||
|
||||
/**
|
||||
* Path to templates dir.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
public $template_path = null;
|
||||
|
||||
/**
|
||||
* Original template path.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
public $original_path = null;
|
||||
|
||||
/**
|
||||
* Sets the path from the arg or via filter. Also calls the panel template function.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
$this->parent = $redux;
|
||||
$this->template_path = Redux_Core::$dir . 'templates/panel/';
|
||||
$this->original_path = Redux_Core::$dir . 'templates/panel/';
|
||||
|
||||
if ( ! empty( $this->parent->args['templates_path'] ) ) {
|
||||
$this->template_path = trailingslashit( $this->parent->args['templates_path'] );
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$this->template_path = trailingslashit( apply_filters( "redux/{$this->parent->args['opt_name']}/panel/templates_path", $this->template_path ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class init.
|
||||
*/
|
||||
public function init() {
|
||||
$this->panel_template();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the panel templates where needed and provides the container for Redux
|
||||
*/
|
||||
private function panel_template() {
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
$this->template_file_check_notice();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action 'redux/{opt_name}/panel/before'
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/{$this->parent->args['opt_name']}/panel/before" );
|
||||
|
||||
echo '<div class="wrap"><h2></h2></div>'; // Stupid hack for WordPress alerts and warnings.
|
||||
|
||||
echo '<div class="clear"></div>';
|
||||
echo '<div class="wrap redux-wrap-div" data-opt-name="' . esc_attr( $this->parent->args['opt_name'] ) . '">';
|
||||
|
||||
// Do we support JS?
|
||||
echo '<noscript><div class="no-js">' . esc_html__( 'Warning- This options panel will not work properly without javascript!', 'redux-framework' ) . '</div></noscript>';
|
||||
|
||||
// Security is vital!
|
||||
echo '<input type="hidden" class="redux-ajax-security" data-opt-name="' . esc_attr( $this->parent->args['opt_name'] ) . '" id="ajaxsecurity" name="security" value="' . esc_attr( wp_create_nonce( 'redux_ajax_nonce' . $this->parent->args['opt_name'] ) ) . '" />';
|
||||
|
||||
/**
|
||||
* Action 'redux/page/{opt_name}/form/before'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/page/{$this->parent->args['opt_name']}/form/before", $this );
|
||||
|
||||
if ( is_rtl() ) {
|
||||
$this->parent->args['class'] = ' redux-rtl';
|
||||
}
|
||||
|
||||
$this->get_template( 'container.tpl.php' );
|
||||
|
||||
/**
|
||||
* Action 'redux/page/{opt_name}/form/after'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/page/{$this->parent->args['opt_name']}/form/after", $this );
|
||||
|
||||
echo '<div class="clear"></div>';
|
||||
echo '</div>';
|
||||
|
||||
if ( true === $this->parent->args['dev_mode'] ) {
|
||||
echo '<br /><div class="redux-timer">' . esc_html( get_num_queries() ) . ' queries in ' . esc_html( timer_stop() ) . ' seconds<br/>Redux is currently set to developer mode.</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Action 'redux/{opt_name}/panel/after'
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/{$this->parent->args['opt_name']}/panel/after" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the various notification bars and sets the appropriate templates.
|
||||
*/
|
||||
public function notification_bar() {
|
||||
if ( isset( $this->parent->transients['last_save_mode'] ) ) {
|
||||
|
||||
if ( 'import' === $this->parent->transients['last_save_mode'] ) {
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/import'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/import", $this, $this->parent->transients['changed_values'] );
|
||||
|
||||
echo '<div class="admin-notice notice-blue saved_notice">';
|
||||
|
||||
/**
|
||||
* Filter 'redux-imported-text-{opt_name}'
|
||||
*
|
||||
* @param string $text Translated "settings imported" text.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo '<strong>' . esc_html( apply_filters( "redux-imported-text-{$this->parent->args['opt_name']}", esc_html__( 'Settings Imported!', 'redux-framework' ) ) ) . '</strong>';
|
||||
echo '</div>';
|
||||
} elseif ( 'defaults' === $this->parent->transients['last_save_mode'] ) {
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/reset'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/reset", $this );
|
||||
|
||||
echo '<div class="saved_notice admin-notice notice-yellow">';
|
||||
|
||||
/**
|
||||
* Filter 'redux-defaults-text-{opt_name}'
|
||||
*
|
||||
* @param string $text Translated "settings imported" text.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo '<strong>' . esc_html( apply_filters( "redux-defaults-text-{$this->parent->args['opt_name']}", esc_html__( 'All Defaults Restored!', 'redux-framework' ) ) ) . '</strong>';
|
||||
echo '</div>';
|
||||
} elseif ( 'defaults_section' === $this->parent->transients['last_save_mode'] ) {
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/section/reset'
|
||||
*
|
||||
* @param object $this ReduxFramework
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/section/reset", $this );
|
||||
|
||||
echo '<div class="saved_notice admin-notice notice-yellow">';
|
||||
|
||||
/**
|
||||
* Filter 'redux-defaults-section-text-{opt_name}'
|
||||
*
|
||||
* @param string $text Translated "settings imported" text.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo '<strong>' . esc_html( apply_filters( "redux-defaults-section-text-{$this->parent->args['opt_name']}", esc_html__( 'Section Defaults Restored!', 'redux-framework' ) ) ) . '</strong>';
|
||||
echo '</div>';
|
||||
} elseif ( 'normal' === $this->parent->transients['last_save_mode'] ) {
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/saved'
|
||||
*
|
||||
* @param mixed $value set/saved option value
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/saved", $this->parent->options, $this->parent->transients['changed_values'] );
|
||||
|
||||
echo '<div class="saved_notice admin-notice notice-green">';
|
||||
|
||||
/**
|
||||
* Filter 'redux-saved-text-{opt_name}'
|
||||
*
|
||||
* @param string $text Translated "settings saved" text.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo '<strong>' . esc_html( apply_filters( "redux-saved-text-{$this->parent->args['opt_name']}", esc_html__( 'Settings Saved!', 'redux-framework' ) ) ) . '</strong>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
unset( $this->parent->transients['last_save_mode'] );
|
||||
|
||||
$this->parent->transient_class->set();
|
||||
}
|
||||
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/settings/changes'
|
||||
*
|
||||
* @param mixed $value set/saved option value
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/settings/change", $this->parent->options, $this->parent->transients['changed_values'] );
|
||||
|
||||
echo '<div class="redux-save-warn notice-yellow">';
|
||||
|
||||
/**
|
||||
* Filter 'redux-changed-text-{opt_name}'
|
||||
*
|
||||
* @param string $text Translated "settings have changed" text.
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
echo '<strong>' . esc_html( apply_filters( "redux-changed-text-{$this->parent->args['opt_name']}", esc_html__( 'Settings have changed, you should save them!', 'redux-framework' ) ) ) . '</strong>';
|
||||
echo '</div>';
|
||||
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/errors'
|
||||
*
|
||||
* @param array $this ->errors error information
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/errors", $this->parent->errors );
|
||||
|
||||
echo '<div class="redux-field-errors notice-red">';
|
||||
echo '<strong>';
|
||||
echo '<span></span> ' . esc_html__( 'error(s) were found!', 'redux-framework' );
|
||||
echo '</strong>';
|
||||
echo '</div>';
|
||||
|
||||
/**
|
||||
* Action 'redux/options/{opt_name}/warnings'
|
||||
*
|
||||
* @param array $this ->warnings warning information
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/warnings", $this->parent->warnings );
|
||||
|
||||
echo '<div class="redux-field-warnings notice-yellow">';
|
||||
echo '<strong>';
|
||||
echo '<span></span> ' . esc_html__( 'warning(s) were found!', 'redux-framework' );
|
||||
echo '</strong>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to initialize the settings fields for this panel. Required for saving and redirect.
|
||||
*/
|
||||
private function init_settings_fields() {
|
||||
// Must run or the page won't redirect properly.
|
||||
settings_fields( "{$this->parent->args['opt_name']}_group" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable file deprecate warning from core. This is necessary because the function is considered private.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function tick_file_deprecate_warning(): bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to select the proper template. If it doesn't exist in the path, then the original template file is used.
|
||||
*
|
||||
* @param string $file Path to template file.
|
||||
*/
|
||||
public function get_template( string $file ) {
|
||||
if ( empty( $file ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( file_exists( $this->template_path . $file ) ) {
|
||||
$path = $this->template_path . $file;
|
||||
} else {
|
||||
$path = $this->original_path . $file;
|
||||
}
|
||||
|
||||
// Shim for v3 templates.
|
||||
if ( ! file_exists( $path ) ) {
|
||||
$old_file = $file;
|
||||
|
||||
add_filter( 'deprecated_file_trigger_error', array( $this, 'tick_file_deprecate_warning' ) );
|
||||
|
||||
$file = str_replace( '_', '-', $file );
|
||||
|
||||
_deprecated_file( esc_html( $old_file ), '4.0', esc_html( $file ), 'Please replace this outdated template with the current one from the Redux core.' );
|
||||
|
||||
if ( file_exists( $this->template_path . $file ) ) {
|
||||
$path = $this->template_path . $file;
|
||||
} else {
|
||||
$path = $this->original_path . $file;
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/{$this->parent->args['opt_name']}/panel/template/" . $file . '/before' );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$path = apply_filters( "redux/{$this->parent->args['opt_name']}/panel/template/" . $file, $path );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/{$this->parent->args['opt_name']}/panel/template/" . $file . '/after' );
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
if ( is_readable( $path ) ) {
|
||||
require $path;
|
||||
} else {
|
||||
// translators: %1$s: template path.
|
||||
echo '<div class="error"><p>' . sprintf( esc_html__( 'Redux Panel Template %1$s cannot be read. Please check the permissions for this file.', 'redux-framework' ), '<code>' . esc_html( $path ) . '</code>' ) . '</p></div>';
|
||||
}
|
||||
} elseif ( file_exists( Redux_Core::$dir . 'templates/panel/' . $file ) ) {
|
||||
require Redux_Core::$dir . 'templates/panel/' . $file;
|
||||
} else {
|
||||
// translators: %1$s: template path.
|
||||
echo '<div class="error"><p>' . sprintf( esc_html__( 'Redux Panel Template %1$s does not exist. Please reinstall Redux to replace this file.', 'redux-framework' ), '<code>' . esc_html( $path ) . '</code>' ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the template files.
|
||||
*
|
||||
* @param string $template_path Path to template file.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function scan_template_files( string $template_path ): array {
|
||||
$files = scandir( $template_path );
|
||||
$result = array();
|
||||
if ( $files ) {
|
||||
foreach ( $files as $value ) {
|
||||
if ( ! in_array( $value, array( '.', '..' ), true ) ) {
|
||||
if ( is_dir( $template_path . DIRECTORY_SEPARATOR . $value ) ) {
|
||||
$sub_files = self::scan_template_files( $template_path . DIRECTORY_SEPARATOR . $value );
|
||||
foreach ( $sub_files as $sub_file ) {
|
||||
$result[] = $value . DIRECTORY_SEPARATOR . $sub_file;
|
||||
}
|
||||
} else {
|
||||
$result[] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a notice highlighting bad template files
|
||||
*/
|
||||
public function template_file_check_notice() {
|
||||
if ( $this->original_path === $this->template_path ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$core_templates = $this->scan_template_files( $this->original_path );
|
||||
|
||||
foreach ( $core_templates as $file ) {
|
||||
$developer_theme_file = false;
|
||||
|
||||
if ( file_exists( $this->template_path . $file ) ) {
|
||||
$developer_theme_file = $this->template_path . $file;
|
||||
}
|
||||
|
||||
if ( $developer_theme_file ) {
|
||||
$core_version = Redux_Helpers::get_template_version( $this->original_path . $file );
|
||||
$developer_version = Redux_Helpers::get_template_version( $developer_theme_file );
|
||||
|
||||
if ( $core_version && $developer_version && version_compare( $developer_version, $core_version, '<' ) ) {
|
||||
?>
|
||||
<div id="message" class="error redux-message" style="display:block!important">
|
||||
<p>
|
||||
<strong><?php esc_html_e( 'Your panel has bundled copies of Redux Framework template files that are outdated!', 'redux-framework' ); ?></strong> <?php esc_html_e( 'Please ask the author of this theme to update them as functionality issues could arise.', 'redux-framework' ); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the HTML for a given section using the WordPress settings API.
|
||||
*
|
||||
* @param mixed $k Section number of settings panel to display.
|
||||
*/
|
||||
private function output_section( $k ) {
|
||||
do_settings_sections( $this->parent->args['opt_name'] . $k . '_section_group' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'reduxCorePanel' ) ) {
|
||||
class_alias( 'Redux_Panel', 'reduxCorePanel' );
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Path Class
|
||||
*
|
||||
* @class Redux_Path
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Path', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Path
|
||||
*/
|
||||
class Redux_Path {
|
||||
|
||||
/**
|
||||
* Class init
|
||||
*/
|
||||
public static function init() {}
|
||||
|
||||
/**
|
||||
* Gets Redux path.
|
||||
*
|
||||
* @param string $relative_path Self-explanatory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_path( string $relative_path ): string {
|
||||
return Redux_Core::$redux_path . $relative_path;
|
||||
}
|
||||
}
|
||||
|
||||
Redux_Path::init();
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Required Class
|
||||
*
|
||||
* @class Redux_Required
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Required', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Required
|
||||
*/
|
||||
class Redux_Required extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Array of fields to reload.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $reload_fields = array();
|
||||
|
||||
/**
|
||||
* Redux_Required Constructor.
|
||||
*
|
||||
* @param object $parent ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $parent = null ) {
|
||||
parent::__construct( $parent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks dependencies between objects based on the $field['required'] array
|
||||
* If the array is set it needs to have exactly 3 entries.
|
||||
* The first entry describes which field should be monitored by the current field. e.g.: "content"
|
||||
* The second entry describes the comparison parameter. eg: "equals, not, is_larger, is_smaller, contains"
|
||||
* The third entry describes the value that we are comparing against.
|
||||
* Example: if the required array is set to array('content','equals','Hello World'); then the current
|
||||
* field will only be displayed if the field with id "content" has exactly the value "Hello World"
|
||||
*
|
||||
* @param array $field Field array.
|
||||
*/
|
||||
public function check_dependencies( array $field ) {
|
||||
$core = $this->core();
|
||||
|
||||
if ( isset( $field['ajax_save'] ) && false === $field['ajax_save'] ) {
|
||||
$core->required_class->reload_fields[] = $field['id'];
|
||||
}
|
||||
|
||||
if ( ! empty( $field['required'] ) ) {
|
||||
if ( ! isset( $core->required_child[ $field['id'] ] ) ) {
|
||||
$core->required_child[ $field['id'] ] = array();
|
||||
}
|
||||
|
||||
if ( ! isset( $core->required[ $field['id'] ] ) ) {
|
||||
$core->required[ $field['id'] ] = array();
|
||||
}
|
||||
|
||||
if ( is_array( $field['required'][0] ) ) {
|
||||
|
||||
foreach ( $field['required'] as $value ) {
|
||||
if ( is_array( $value ) && 3 === count( $value ) ) {
|
||||
$data = array();
|
||||
$data['parent'] = $value[0];
|
||||
$data['operation'] = $value[1];
|
||||
$data['checkValue'] = $value[2];
|
||||
|
||||
$core->required[ $data['parent'] ][ $field['id'] ][] = $data;
|
||||
|
||||
if ( ! in_array( $data['parent'], $core->required_child[ $field['id'] ], true ) ) {
|
||||
$core->required_child[ $field['id'] ][] = $data;
|
||||
}
|
||||
|
||||
$this->check_required_dependencies( $core, $field, $data );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data = array();
|
||||
$data['parent'] = $field['required'][0];
|
||||
$data['operation'] = $field['required'][1];
|
||||
$data['checkValue'] = $field['required'][2];
|
||||
|
||||
$core->required[ $data['parent'] ][ $field['id'] ][] = $data;
|
||||
|
||||
if ( false === array_search( $data['parent'], array_column( $core->required_child[ $field['id'] ], 'parent' ), true ) ) {
|
||||
$core->required_child[ $field['id'] ][] = $data;
|
||||
}
|
||||
|
||||
$this->check_required_dependencies( $core, $field, $data );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check field for required deps.
|
||||
*
|
||||
* @param object $core ReduxFramework core pointer.
|
||||
* @param array $field Field array.
|
||||
* @param array $data Required data.
|
||||
*/
|
||||
private function check_required_dependencies( $core, array $field, array $data ) {
|
||||
// The Required field must not be hidden. Otherwise, hide this one by default.
|
||||
if ( ! in_array( $data['parent'], $core->fields_hidden, true ) && ( ! isset( $core->folds[ $field['id'] ] ) || 'hide' !== $core->folds[ $field['id'] ] ) ) {
|
||||
if ( isset( $core->options[ $data['parent'] ] ) ) {
|
||||
$return = $this->compare_value_dependencies( $core->options[ $data['parent'] ], $data['checkValue'], $data['operation'] );
|
||||
} elseif ( isset( $core->options_defaults[ $data['parent'] ] ) ) {
|
||||
$return = $this->compare_value_dependencies( $core->options_defaults[ $data['parent'] ], $data['checkValue'], $data['operation'] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( isset( $return ) && $return ) && ( ! isset( $core->folds[ $field['id'] ] ) || 'hide' !== $core->folds[ $field['id'] ] ) ) {
|
||||
$core->folds[ $field['id'] ] = 'show';
|
||||
} else {
|
||||
$core->folds[ $field['id'] ] = 'hide';
|
||||
|
||||
if ( ! in_array( $field['id'], $core->fields_hidden, true ) ) {
|
||||
$core->fields_hidden[] = $field['id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare data for required field.
|
||||
*
|
||||
* @param mixed $parent_value Parent value.
|
||||
* @param mixed $check_value Check value.
|
||||
* @param string $operation Operation.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function compare_value_dependencies( $parent_value, $check_value, string $operation ): bool {
|
||||
$return = false;
|
||||
switch ( $operation ) {
|
||||
case '=':
|
||||
case 'equals':
|
||||
$data['operation'] = '=';
|
||||
|
||||
if ( is_array( $parent_value ) ) {
|
||||
foreach ( $parent_value as $val ) {
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $v ) {
|
||||
if ( Redux_Helpers::make_bool_str( $val ) === Redux_Helpers::make_bool_str( $v ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( Redux_Helpers::make_bool_str( $val ) === Redux_Helpers::make_bool_str( $check_value ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $v ) {
|
||||
if ( Redux_Helpers::make_bool_str( $parent_value ) === Redux_Helpers::make_bool_str( $v ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( Redux_Helpers::make_bool_str( $parent_value ) === Redux_Helpers::make_bool_str( $check_value ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '!=':
|
||||
case 'not':
|
||||
$data['operation'] = '!==';
|
||||
if ( is_array( $parent_value ) ) {
|
||||
foreach ( $parent_value as $val ) {
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $v ) {
|
||||
if ( Redux_Helpers::make_bool_str( $val ) !== Redux_Helpers::make_bool_str( $v ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( Redux_Helpers::make_bool_str( $val ) !== Redux_Helpers::make_bool_str( $check_value ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $v ) {
|
||||
if ( Redux_Helpers::make_bool_str( $parent_value ) !== Redux_Helpers::make_bool_str( $v ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( Redux_Helpers::make_bool_str( $parent_value ) !== Redux_Helpers::make_bool_str( $check_value ) ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case '>':
|
||||
case 'greater':
|
||||
case 'is_larger':
|
||||
$data['operation'] = '>';
|
||||
if ( $parent_value > $check_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case '>=':
|
||||
case 'greater_equal':
|
||||
case 'is_larger_equal':
|
||||
$data['operation'] = '>=';
|
||||
if ( $parent_value >= $check_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
case 'less':
|
||||
case 'is_smaller':
|
||||
$data['operation'] = '<';
|
||||
if ( $parent_value < $check_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case '<=':
|
||||
case 'less_equal':
|
||||
case 'is_smaller_equal':
|
||||
$data['operation'] = '<=';
|
||||
if ( $parent_value <= $check_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case 'contains':
|
||||
if ( is_array( $parent_value ) ) {
|
||||
$parent_value = implode( ',', $parent_value );
|
||||
}
|
||||
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $opt ) {
|
||||
if ( strpos( $parent_value, (string) $opt ) !== false ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} elseif ( strpos( $parent_value, (string) $check_value ) !== false ) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'doesnt_contain':
|
||||
case 'not_contain':
|
||||
if ( is_array( $parent_value ) ) {
|
||||
$parent_value = implode( ',', $parent_value );
|
||||
}
|
||||
|
||||
if ( is_array( $check_value ) ) {
|
||||
foreach ( $check_value as $opt ) {
|
||||
if ( strpos( $parent_value, (string) $opt ) === false ) {
|
||||
$return = true;
|
||||
}
|
||||
}
|
||||
} elseif ( strpos( $parent_value, (string) $check_value ) === false ) {
|
||||
$return = true;
|
||||
}
|
||||
|
||||
break;
|
||||
case 'is_empty_or':
|
||||
if ( empty( $parent_value ) || $check_value === $parent_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case 'not_empty_and':
|
||||
if ( ! empty( $parent_value ) && $check_value !== $parent_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case 'is_empty':
|
||||
case 'empty':
|
||||
case '!isset':
|
||||
if ( empty( $parent_value ) ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
case 'not_empty':
|
||||
case '!empty':
|
||||
case 'isset':
|
||||
if ( ! empty( $parent_value ) && '' !== $parent_value ) {
|
||||
$return = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Sanitize Class
|
||||
*
|
||||
* @class Redux_Sanitize
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Sanitize', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Sanitize
|
||||
*/
|
||||
class Redux_Sanitize extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Sanitize values from options form (used in settings api validate function)
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $plugin_options Plugin Options.
|
||||
* @param array $options Options.
|
||||
* @param array $sections Sections array.
|
||||
*
|
||||
* @return array $plugin_options
|
||||
*/
|
||||
public function sanitize( array $plugin_options, array $options, array $sections ): array {
|
||||
$core = $this->core();
|
||||
|
||||
foreach ( $sections as $k => $section ) {
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $field ) {
|
||||
|
||||
if ( is_array( $field ) ) {
|
||||
$field['section_id'] = $k;
|
||||
}
|
||||
|
||||
if ( isset( $field['type'] ) && ( 'text' === $field['type'] || 'textarea' === $field['type'] || 'multi_text' === $field['type'] ) ) {
|
||||
|
||||
// Make sure 'sanitize' field is set.
|
||||
if ( isset( $field['sanitize'] ) ) {
|
||||
|
||||
// Can we make this an array of validations?
|
||||
$val_arr = array();
|
||||
|
||||
if ( is_array( $field['sanitize'] ) ) {
|
||||
$val_arr = $field['sanitize'];
|
||||
} else {
|
||||
$val_arr[] = $field['sanitize'];
|
||||
}
|
||||
|
||||
foreach ( $val_arr as $function ) {
|
||||
|
||||
// Check for empty id value.
|
||||
if ( ! isset( $field['id'] ) || ! isset( $plugin_options[ $field['id'] ] ) || ( '' === $plugin_options[ $field['id'] ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( function_exists( $function ) ) {
|
||||
if ( empty( $options[ $field['id'] ] ) ) {
|
||||
$options[ $field['id'] ] = '';
|
||||
}
|
||||
|
||||
if ( is_array( $plugin_options[ $field['id'] ] ) && ! empty( $plugin_options[ $field['id'] ] ) ) {
|
||||
foreach ( $plugin_options[ $field['id'] ] as $key => $value ) {
|
||||
$before = null;
|
||||
$after = null;
|
||||
|
||||
if ( isset( $plugin_options[ $field['id'] ][ $key ] ) && ( ! empty( $plugin_options[ $field['id'] ][ $key ] ) || '0' === $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
if ( is_array( $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
$before = $plugin_options[ $field['id'] ][ $key ];
|
||||
} else {
|
||||
$before = trim( $plugin_options[ $field['id'] ][ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $options[ $field['id'] ][ $key ] ) && ( ! empty( $plugin_options[ $field['id'] ][ $key ] ) || '0' === $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
$after = $options[ $field['id'] ][ $key ];
|
||||
}
|
||||
|
||||
$value = call_user_func( $function, $before );
|
||||
|
||||
if ( false !== $value ) {
|
||||
$plugin_options[ $field['id'] ][ $key ] = $value;
|
||||
} else {
|
||||
unset( $plugin_options[ $field['id'] ][ $key ] );
|
||||
}
|
||||
|
||||
$field['current'] = $value;
|
||||
|
||||
$core->sanitize[] = $field;
|
||||
}
|
||||
} else {
|
||||
if ( isset( $plugin_options[ $field['id'] ] ) ) {
|
||||
if ( is_array( $plugin_options[ $field['id'] ] ) ) {
|
||||
$pofi = $plugin_options[ $field['id'] ];
|
||||
} else {
|
||||
$pofi = trim( $plugin_options[ $field['id'] ] );
|
||||
}
|
||||
} else {
|
||||
$pofi = null;
|
||||
}
|
||||
|
||||
$value = call_user_func( $function, $pofi );
|
||||
|
||||
$plugin_options[ $field['id'] ] = $value;
|
||||
|
||||
$field['current'] = $value;
|
||||
|
||||
$core->sanitize[] = $field;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $plugin_options;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux ThirdParty Fixes Class
|
||||
*
|
||||
* @class Redux_ThirdParty_Fixes
|
||||
* @version 3.0.0
|
||||
* @package Redux Framework/Classes
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_ThirdParty_Fixes', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_ThirdParty_Fixes
|
||||
*/
|
||||
class Redux_ThirdParty_Fixes extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Redux_ThirdParty_Fixes constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux );
|
||||
|
||||
$this->gt3_page_builder();
|
||||
|
||||
// These are necessary to override an outdated extension embedded in themes
|
||||
// that are loaded via the antiquated 'loader.php' method.
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/repeater', array( $this, 'repeater_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/metaboxes', array( $this, 'metaboxes_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/social_profiles', array( $this, 'social_profiles_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/widget_areas', array( $this, 'widget_areas_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/custom_fonts', array( $this, 'custom_fonts_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/icon_select', array( $this, 'icon_select_extension_override' ) );
|
||||
add_filter( 'redux/extension/' . $this->parent->args['opt_name'] . '/color_scheme', array( $this, 'color_scheme_extension_override' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Color Scheme extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function color_scheme_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/color_scheme/class-redux-extension-color-scheme.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon Select extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function icon_select_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/icon_select/class-redux-extension-icon-select.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget Area extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function custom_fonts_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/custom_fonts/class-redux-extension-custom-fonts.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Widget Area extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function widget_areas_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/widget_areas/class-redux-extension-widget-areas.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeater extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function repeater_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/repeater/class-redux-extension-repeater.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Metaboxes extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function metaboxes_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/metaboxes/class-redux-extension-metaboxes.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Social Profiles extension override.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function social_profiles_extension_override(): string {
|
||||
return Redux_core::$dir . 'inc/extensions/social_profiles/class-redux-extension-social-profiles.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* GT3 Page Builder fix.
|
||||
*/
|
||||
private function gt3_page_builder() {
|
||||
// Fix for the GT3 page builder: http://www.gt3themes.com/wordpress-gt3-page-builder-plugin/.
|
||||
if ( has_action( 'ecpt_field_options_' ) ) {
|
||||
global $pagenow;
|
||||
|
||||
if ( 'admin.php' === $pagenow ) {
|
||||
remove_action( 'admin_init', 'pb_admin_init' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Transients Class
|
||||
*
|
||||
* @class Redux_Transients
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Transients', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Transients
|
||||
*/
|
||||
class Redux_Transients extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Get transients from database.
|
||||
*/
|
||||
public function get() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( empty( $core->transients ) ) {
|
||||
$core->transients = get_option( $core->args['opt_name'] . '-transients', array() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set transients in database.
|
||||
*/
|
||||
public function set() {
|
||||
$core = $this->core();
|
||||
|
||||
if ( ! isset( $core->transients ) || ! isset( $core->transients_check ) || $core->transients_check !== $core->transients ) {
|
||||
update_option( $core->args['opt_name'] . '-transients', $core->transients );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Validate Class
|
||||
*
|
||||
* @class Redux_Validate
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Validate', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Validate
|
||||
*/
|
||||
abstract class Redux_Validate {
|
||||
/**
|
||||
* ReduxFramework object.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
public $parent;
|
||||
|
||||
/**
|
||||
* Redux fields array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $field = array();
|
||||
|
||||
/**
|
||||
* Redux values array|string.
|
||||
*
|
||||
* @var array|string
|
||||
*/
|
||||
public $value;
|
||||
|
||||
/**
|
||||
* Validation current value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
public $current;
|
||||
|
||||
/**
|
||||
* Warning array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $warning = array();
|
||||
|
||||
/**
|
||||
* Error array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $error = array();
|
||||
|
||||
/**
|
||||
* Sanitize array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $sanitize = array();
|
||||
|
||||
/**
|
||||
* Redux_Validate constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
* @param array $field Fields array.
|
||||
* @param array|string $value Values array.
|
||||
* @param mixed $current Current.
|
||||
*/
|
||||
public function __construct( $redux, array $field, $value, $current ) {
|
||||
$this->parent = $redux;
|
||||
$this->field = $field;
|
||||
$this->value = $value;
|
||||
$this->current = $current;
|
||||
|
||||
if ( isset( $this->field['validate_msg'] ) ) {
|
||||
$this->field['msg'] = $this->field['validate_msg'];
|
||||
|
||||
unset( $this->field['validate_msg'] );
|
||||
}
|
||||
|
||||
$this->validate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function validate();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Validation Class
|
||||
*
|
||||
* @class Redux_Validation
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Validation', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Validation
|
||||
*/
|
||||
class Redux_Validation extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Validate values from options form (used in settings api validate function)
|
||||
* calls the custom validation class for the field so authors can override with custom classes
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param array $plugin_options Plugin Options.
|
||||
* @param array $options Options.
|
||||
* @param array $sections Sections array.
|
||||
*
|
||||
* @return array $plugin_options
|
||||
*/
|
||||
public function validate( array $plugin_options, array $options, array $sections ): array {
|
||||
$core = $this->core();
|
||||
|
||||
foreach ( $sections as $k => $section ) {
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $fkey => $field ) {
|
||||
if ( is_array( $field ) ) {
|
||||
$field['section_id'] = $k;
|
||||
}
|
||||
|
||||
if ( isset( $field['type'] ) && ( 'checkbox' === $field['type'] || 'checkbox_hide_below' === $field['type'] || 'checkbox_hide_all' === $field['type'] ) ) {
|
||||
if ( ! isset( $plugin_options[ $field['id'] ] ) ) {
|
||||
$plugin_options[ $field['id'] ] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Part of Dovy's serialize typography effort. Preserved here in case it becomes a thing. - kp.
|
||||
/**
|
||||
* If ( isset ( $field['type'] ) && $field['type'] == 'typography' ) {
|
||||
* if ( ! is_array( $plugin_options[ $field['id'] ] ) && ! empty( $plugin_options[ $field['id'] ] ) ) {
|
||||
* $plugin_options[ $field['id'] ] = json_decode( $plugin_options[ $field['id'] ], true );
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
if ( isset( $core->extensions[ $field['type'] ] ) && method_exists( $core->extensions[ $field['type'] ], '_validate_values' ) ) {
|
||||
$plugin_options = $core->extensions[ $field['type'] ]->_validate_values( $plugin_options, $field, $sections );
|
||||
}
|
||||
|
||||
// Make sure 'validate' field is set.
|
||||
if ( isset( $field['validate'] ) ) {
|
||||
|
||||
// Can we make this an array of validations?
|
||||
$val_arr = array();
|
||||
|
||||
if ( is_array( $field['validate'] ) ) {
|
||||
$val_arr = $field['validate'];
|
||||
} else {
|
||||
$val_arr[] = $field['validate'];
|
||||
}
|
||||
|
||||
foreach ( $val_arr as $idx => $val ) {
|
||||
// shim for old *_not_empty validations.
|
||||
if ( 'email_not_empty' === $val || 'numeric_not_empty' === $val ) {
|
||||
$val = 'not_empty';
|
||||
}
|
||||
|
||||
// Make sure 'validate field' is set to 'not_empty'.
|
||||
$is_not_empty = false;
|
||||
|
||||
if ( 'not_empty' === $val ) {
|
||||
// Set the flag.
|
||||
$is_not_empty = true;
|
||||
}
|
||||
|
||||
// Check for empty id value.
|
||||
if ( ! isset( $field['id'] ) || ! isset( $plugin_options[ $field['id'] ] ) || ( '' === $plugin_options[ $field['id'] ] ) ) {
|
||||
|
||||
// If we are looking for an empty value, in the case of 'not_empty'
|
||||
// then we need to keep processing.
|
||||
if ( ! $is_not_empty ) {
|
||||
|
||||
// Empty id and not checking for 'not_empty'. Bail out...
|
||||
if ( ! isset( $field['validate_callback'] ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Force validate of custom field types.
|
||||
if ( isset( $field['type'] ) && ! isset( $val ) && ! isset( $field['validate_callback'] ) ) {
|
||||
if ( 'color' === $field['type'] || 'color_gradient' === $field['type'] ) {
|
||||
$val = 'color';
|
||||
} elseif ( 'date' === $field['type'] ) {
|
||||
$val = 'date';
|
||||
}
|
||||
}
|
||||
|
||||
// No need. Spectrum self validates.
|
||||
if ( 'color_rgba' === $field['type'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Shim out old color rgba validators.
|
||||
if ( 'color_rgba' === $val || 'colorrgba' === $val ) {
|
||||
$val = 'color';
|
||||
}
|
||||
|
||||
$validate = 'Redux_Validation_' . $val;
|
||||
|
||||
if ( ! class_exists( $validate ) ) {
|
||||
$file = str_replace( '_', '-', $val );
|
||||
|
||||
/**
|
||||
* Filter 'redux/validate/{opt_name}/class/{field.validate}'
|
||||
*
|
||||
* @param string $validate validation class file path
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$class_file = apply_filters( "redux/validate/{$core->args['opt_name']}/class/$val", Redux_Core::$dir . "inc/validation/$val/class-redux-validation-$file.php", $validate );
|
||||
|
||||
if ( $class_file ) {
|
||||
if ( file_exists( $class_file ) ) {
|
||||
require_once $class_file;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( class_exists( $validate ) ) {
|
||||
if ( empty( $options[ $field['id'] ] ) ) {
|
||||
$options[ $field['id'] ] = '';
|
||||
}
|
||||
|
||||
if ( isset( $plugin_options[ $field['id'] ] ) && is_array( $plugin_options[ $field['id'] ] ) && ! empty( $plugin_options[ $field['id'] ] ) ) {
|
||||
foreach ( $plugin_options[ $field['id'] ] as $key => $value ) {
|
||||
$before = null;
|
||||
$after = null;
|
||||
|
||||
if ( isset( $plugin_options[ $field['id'] ][ $key ] ) && ( ! empty( $plugin_options[ $field['id'] ][ $key ] ) || '0' === $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
if ( is_array( $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
$before = $plugin_options[ $field['id'] ][ $key ];
|
||||
} else {
|
||||
$before = trim( $plugin_options[ $field['id'] ][ $key ] );
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $options[ $field['id'] ][ $key ] ) && ( ! empty( $plugin_options[ $field['id'] ][ $key ] ) || '0' === $plugin_options[ $field['id'] ][ $key ] ) ) {
|
||||
$after = $options[ $field['id'] ][ $key ];
|
||||
}
|
||||
|
||||
$validation = new $validate( $core, $field, $before, $after );
|
||||
|
||||
if ( ! empty( $validation->value ) || '0' === $validation->value ) {
|
||||
$plugin_options[ $field['id'] ][ $key ] = $validation->value;
|
||||
} else {
|
||||
unset( $plugin_options[ $field['id'] ][ $key ] );
|
||||
}
|
||||
|
||||
if ( ! empty( $validation->error ) ) {
|
||||
$core->errors[] = $validation->error;
|
||||
}
|
||||
|
||||
if ( ! empty( $validation->warning ) ) {
|
||||
$core->warnings[] = $validation->warning;
|
||||
}
|
||||
|
||||
if ( ! empty( $validation->sanitize ) ) {
|
||||
$core->sanitize[] = $validation->sanitize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( isset( $plugin_options[ $field['id'] ] ) ) {
|
||||
if ( is_array( $plugin_options[ $field['id'] ] ) ) {
|
||||
$pofi = $plugin_options[ $field['id'] ];
|
||||
} else {
|
||||
$pofi = trim( $plugin_options[ $field['id'] ] );
|
||||
}
|
||||
} else {
|
||||
$pofi = null;
|
||||
}
|
||||
|
||||
$validation = new $validate( $core, $field, $pofi, $options[ $field['id'] ] );
|
||||
$plugin_options[ $field['id'] ] = $validation->value;
|
||||
|
||||
if ( ! empty( $validation->error ) ) {
|
||||
$core->errors[] = $validation->error;
|
||||
}
|
||||
|
||||
if ( ! empty( $validation->warning ) ) {
|
||||
$core->warnings[] = $validation->warning;
|
||||
}
|
||||
|
||||
if ( ! empty( $validation->sanitize ) ) {
|
||||
$core->sanitize[] = $validation->sanitize;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $field['validate_callback'] ) && ( is_callable( $field['validate_callback'] ) || ( is_string( $field['validate_callback'] ) && function_exists( $field['validate_callback'] ) ) ) ) {
|
||||
$callback = $field['validate_callback'];
|
||||
unset( $field['validate_callback'] );
|
||||
|
||||
$plugin_option = $plugin_options[ $field['id'] ] ?? null;
|
||||
$option = $options[ $field['id'] ] ?? null;
|
||||
|
||||
if ( null !== $plugin_option ) {
|
||||
$callbackvalues = call_user_func( $callback, $field, $plugin_option, $option );
|
||||
|
||||
$plugin_options[ $field['id'] ] = $callbackvalues['value'];
|
||||
|
||||
if ( isset( $callbackvalues['error'] ) ) {
|
||||
$core->errors[] = $callbackvalues['error'];
|
||||
}
|
||||
|
||||
if ( isset( $callbackvalues['warning'] ) ) {
|
||||
$core->warnings[] = $callbackvalues['warning'];
|
||||
}
|
||||
|
||||
if ( isset( $callbackvalues['sanitize'] ) ) {
|
||||
$core->sanitize[] = $callbackvalues['sanitize'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $plugin_options;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,683 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux WordPress Data Class
|
||||
*
|
||||
* @class Redux_WordPress_Data
|
||||
* @version 3.0.0
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_WordPress_Data', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_WordPress_Data
|
||||
*/
|
||||
class Redux_WordPress_Data extends Redux_Class {
|
||||
|
||||
/**
|
||||
* Holds WordPress data.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
private $wp_data = null;
|
||||
|
||||
/**
|
||||
* Redux_WordPress_Data constructor.
|
||||
*
|
||||
* @param mixed $redux ReduxFramework pointer or opt_name.
|
||||
*/
|
||||
public function __construct( $redux = null ) {
|
||||
if ( is_string( $redux ) ) {
|
||||
$this->opt_name = $redux;
|
||||
} else {
|
||||
parent::__construct( $redux );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data.
|
||||
*
|
||||
* @param string|array $type Type.
|
||||
* @param array|string $args Args.
|
||||
* @param string $opt_name Opt name.
|
||||
* @param string|int $current_value Current value.
|
||||
* @param bool $ajax Tells if this is an AJAX call.
|
||||
*
|
||||
* @return array|mixed|string
|
||||
*/
|
||||
public function get( $type, $args = array(), string $opt_name = '', $current_value = '', bool $ajax = false ) {
|
||||
$opt_name = $this->opt_name;
|
||||
|
||||
// We don't want to run this, it's not a string value. Send it back!
|
||||
if ( is_array( $type ) ) {
|
||||
return $type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter 'redux/options/{opt_name}/pre_data/{type}'
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
$pre_data = apply_filters( "redux/options/$opt_name/pre_data/$type", null ); // phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
if ( null !== $pre_data || empty( $type ) ) {
|
||||
return $pre_data;
|
||||
}
|
||||
|
||||
if ( isset( $args['data_sortby'] ) && in_array( $args['data_sortby'], array( 'value', 'key' ), true ) ) {
|
||||
$data_sort = $args['data_sortby'];
|
||||
unset( $args['data_sortby'] );
|
||||
} else {
|
||||
$data_sort = 'value';
|
||||
}
|
||||
if ( isset( $args['data_order'] ) && in_array( $args['data_order'], array( 'asc', 'desc' ), true ) ) {
|
||||
$data_order = $args['data_order'];
|
||||
unset( $args['data_order'] );
|
||||
} else {
|
||||
$data_order = 'asc';
|
||||
}
|
||||
|
||||
$this->maybe_get_translation( $type, $current_value, $args );
|
||||
|
||||
$current_data = array();
|
||||
if ( empty( $current_value ) && ! Redux_Helpers::is_integer( $current_value ) ) {
|
||||
$current_value = null;
|
||||
} else {
|
||||
// Get the args to grab the current data.
|
||||
$current_data_args = $this->get_current_data_args( $type, $args, $current_value );
|
||||
|
||||
// Let's make a unique key for this arg array.
|
||||
$current_data_args_key = md5( maybe_serialize( $current_data_args ) );
|
||||
|
||||
// Check to make sure we haven't already run this call before.
|
||||
$current_data = $this->wp_data[ $type . $current_data_args_key ] ?? $this->get_data( $type, $current_data_args, $current_value );
|
||||
}
|
||||
|
||||
// If ajax is enabled AND $current_data is empty, set a dummy value for the init.
|
||||
if ( $ajax && ! wp_doing_ajax() ) {
|
||||
// Dummy is needed otherwise empty.
|
||||
if ( empty( $current_data ) ) {
|
||||
$current_data = array(
|
||||
'dummy' => '',
|
||||
);
|
||||
}
|
||||
|
||||
return $current_data;
|
||||
}
|
||||
|
||||
// phpcs:ignore Squiz.PHP.CommentedOutCode
|
||||
$args_key = md5( maybe_serialize( $args ) );
|
||||
|
||||
// Data caching.
|
||||
if ( isset( $this->wp_data[ $type . $args_key ] ) ) {
|
||||
$data = $this->wp_data[ $type . $args_key ];
|
||||
} else {
|
||||
/**
|
||||
* Use data from WordPress to populate options array.
|
||||
* */
|
||||
$data = $this->get_data( $type, $args, $current_value );
|
||||
}
|
||||
|
||||
if ( ! empty( $current_data ) ) {
|
||||
$data += $current_data;
|
||||
}
|
||||
|
||||
if ( ! empty( $data ) ) {
|
||||
$data = $this->order_data( $data, $data_sort, $data_order );
|
||||
$this->wp_data[ $type . $args_key ] = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter 'redux/options/{opt_name}/data/{type}'
|
||||
*
|
||||
* @param string $data
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
return apply_filters( "redux/options/$opt_name/data/$type", $data );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process the results into a proper array, fetching the data elements needed for each data type.
|
||||
*
|
||||
* @param array|WP_Error $results Results to process in the data array.
|
||||
* @param string|bool $id_key Key on object/array that represents the ID.
|
||||
* @param string|bool $name_key Key on object/array that represents the name/text.
|
||||
* @param bool $add_key If true, the display key will appear in the text.
|
||||
* @param string|bool $secondary_key If a data type you'd rather display a different ID as the display key.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function process_results( $results = array(), $id_key = '', $name_key = '', bool $add_key = true, $secondary_key = 'slug' ): array {
|
||||
$data = array();
|
||||
if ( ! empty( $results ) && ! is_a( $results, 'WP_Error' ) ) {
|
||||
foreach ( $results as $k => $v ) {
|
||||
if ( empty( $id_key ) ) {
|
||||
$key = $k;
|
||||
} else {
|
||||
if ( is_object( $v ) ) {
|
||||
$key = $v->$id_key;
|
||||
} elseif ( is_array( $v ) ) {
|
||||
$key = $v[ $id_key ];
|
||||
} else {
|
||||
$key = $k;
|
||||
}
|
||||
}
|
||||
|
||||
if ( empty( $name_key ) ) {
|
||||
$value = $v;
|
||||
} else {
|
||||
if ( is_object( $v ) ) {
|
||||
$value = $v->$name_key;
|
||||
} elseif ( is_array( $v ) ) {
|
||||
$value = $v[ $name_key ];
|
||||
} else {
|
||||
$value = $v;
|
||||
}
|
||||
}
|
||||
$display_key = $key;
|
||||
if ( is_object( $v ) && isset( $v->$secondary_key ) ) {
|
||||
$display_key = $v->$secondary_key;
|
||||
} elseif ( ! is_object( $v ) && isset( $v[ $secondary_key ] ) ) {
|
||||
$display_key = $v[ $secondary_key ];
|
||||
}
|
||||
$data[ $key ] = $value;
|
||||
if ( $display_key !== $value && $add_key ) {
|
||||
$data[ $key ] = $data[ $key ] . ' [' . $display_key . ']';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Order / Sort the data.
|
||||
*
|
||||
* @param array $data Data to sort.
|
||||
* @param string $sort Way to sort. Accepts: key|value.
|
||||
* @param string $order Order of the sort. Accepts: asc|desc.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function order_data( array $data = array(), string $sort = 'value', string $order = 'asc' ): array {
|
||||
if ( 'key' === $sort ) {
|
||||
if ( 'asc' === $order ) {
|
||||
ksort( $data );
|
||||
} else {
|
||||
krsort( $data );
|
||||
}
|
||||
} elseif ( 'value' === $sort ) {
|
||||
if ( 'asc' === $order ) {
|
||||
asort( $data );
|
||||
} else {
|
||||
arsort( $data );
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the data for a given type.
|
||||
*
|
||||
* @param string $type The data type we're fetching.
|
||||
* @param array|string $args Arguments to pass.
|
||||
* @param mixed|array $current_value If a current value already set in the database.
|
||||
*
|
||||
* @return array|null|string
|
||||
*/
|
||||
private function get_data( string $type, $args, $current_value ) {
|
||||
$args = $this->get_arg_defaults( $type, $args );
|
||||
|
||||
$opt_name = $this->opt_name;
|
||||
if ( empty( $args ) ) {
|
||||
$args = array();
|
||||
}
|
||||
|
||||
$data = array();
|
||||
if ( isset( $args['args'] ) && empty( $args['args'] ) ) {
|
||||
unset( $args['args'] );
|
||||
}
|
||||
|
||||
$display_keys = false;
|
||||
if ( isset( $args['display_keys'] ) ) {
|
||||
$display_keys = true;
|
||||
unset( $args['display_keys'] );
|
||||
}
|
||||
|
||||
$secondary_key = 'slug';
|
||||
if ( isset( $args['secondary_key'] ) ) {
|
||||
$secondary_key = $args['secondary_key'];
|
||||
unset( $args['secondary_key'] );
|
||||
}
|
||||
|
||||
switch ( $type ) {
|
||||
case 'categories':
|
||||
case 'category':
|
||||
case 'terms':
|
||||
case 'term':
|
||||
if ( isset( $args['taxonomies'] ) ) {
|
||||
$args['taxonomy'] = $args['taxonomies'];
|
||||
unset( $args['taxonomies'] );
|
||||
}
|
||||
$results = get_terms( $args );
|
||||
$data = $this->process_results( $results, 'term_id', 'name', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'pages':
|
||||
case 'page':
|
||||
$results = get_pages( $args );
|
||||
$data = $this->process_results( $results, 'ID', 'post_title', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
case 'tag':
|
||||
$results = get_tags( $args );
|
||||
$data = $this->process_results( $results, 'term_id', 'name', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'menus':
|
||||
case 'menu':
|
||||
$results = wp_get_nav_menus( $args );
|
||||
$data = $this->process_results( $results, 'term_id', 'name', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'posts':
|
||||
case 'post':
|
||||
$results = get_posts( $args );
|
||||
$data = $this->process_results( $results, 'ID', 'post_title', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'users':
|
||||
case 'user':
|
||||
$results = get_users( $args );
|
||||
$data = $this->process_results( $results, 'ID', 'display_name', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'sites':
|
||||
case 'site':
|
||||
$sites = get_sites();
|
||||
|
||||
if ( isset( $sites ) ) {
|
||||
$results = array();
|
||||
foreach ( $sites as $site ) {
|
||||
$site = (array) $site;
|
||||
$k = $site['blog_id'];
|
||||
$v = $site['domain'] . $site['path'];
|
||||
$name = get_blog_option( $k, 'blogname' );
|
||||
if ( ! empty( $name ) ) {
|
||||
$v .= ' - [' . $name . ']';
|
||||
}
|
||||
$results[ $k ] = $v;
|
||||
}
|
||||
$data = $this->process_results( $results, '', '', $display_keys, $secondary_key );
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'taxonomies':
|
||||
case 'taxonomy':
|
||||
case 'tax':
|
||||
$results = get_taxonomies( $args );
|
||||
$data = $this->process_results( $results, '', '', $display_keys, $secondary_key );
|
||||
break;
|
||||
|
||||
case 'post_types':
|
||||
case 'post_type':
|
||||
global $wp_post_types;
|
||||
|
||||
$output = $args['output'];
|
||||
unset( $args['output'] );
|
||||
$operator = $args['operator'];
|
||||
unset( $args['operator'] );
|
||||
|
||||
$post_types = get_post_types( $args, $output, $operator );
|
||||
|
||||
foreach ( $post_types as $name => $title ) {
|
||||
if ( isset( $wp_post_types[ $name ]->labels->menu_name ) ) {
|
||||
$data[ $name ] = $wp_post_types[ $name ]->labels->menu_name;
|
||||
} else {
|
||||
$data[ $name ] = ucfirst( $name );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'menu_locations':
|
||||
case 'menu_location':
|
||||
global $_wp_registered_nav_menus;
|
||||
foreach ( $_wp_registered_nav_menus as $k => $v ) {
|
||||
$data[ $k ] = $v;
|
||||
if ( ! has_nav_menu( $k ) ) {
|
||||
$data[ $k ] .= ' ' . __( '[unassigned]', 'redux-framework' );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'image_sizes':
|
||||
case 'image_size':
|
||||
global $_wp_additional_image_sizes;
|
||||
$results = array();
|
||||
foreach ( $_wp_additional_image_sizes as $size_name => $size_attrs ) {
|
||||
$results[ $size_name ] = $size_name . ' - ' . $size_attrs['width'] . ' x ' . $size_attrs['height'];
|
||||
}
|
||||
$data = $this->process_results( $results, '', '', $display_keys, $secondary_key );
|
||||
|
||||
break;
|
||||
|
||||
case 'elusive-icons':
|
||||
case 'elusive-icon':
|
||||
case 'elusive':
|
||||
case 'icons':
|
||||
case 'font-icon':
|
||||
case 'font-icons':
|
||||
$fs = Redux_Filesystem::get_instance();
|
||||
$fonts = $fs->get_contents( Redux_Core::$dir . 'assets/css/vendor/elusive-icons.css' );
|
||||
if ( ! empty( $fonts ) ) {
|
||||
preg_match_all( '@\.el-(\w+)::before@', $fonts, $matches );
|
||||
foreach ( $matches[1] as $item ) {
|
||||
if ( 'before' === $item ) {
|
||||
continue;
|
||||
}
|
||||
$data[ 'el el-' . $item ] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter 'redux/font-icons'
|
||||
*
|
||||
* @param array $font_icons array of elusive icon classes
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$font_icons = apply_filters_deprecated( 'redux/font-icons', array( $data ), '4.3', 'redux/$opt_name/field/font/icons' );
|
||||
|
||||
/**
|
||||
* Filter 'redux/{opt_name}/field/font/icons'
|
||||
*
|
||||
* @param array $font_icons array of elusive icon classes
|
||||
*/
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$data = apply_filters( "redux/$opt_name/field/font/icons", $font_icons );
|
||||
|
||||
break;
|
||||
|
||||
case 'dashicons':
|
||||
case 'dashicon':
|
||||
case 'dash':
|
||||
$fs = Redux_Filesystem::get_instance();
|
||||
$fonts = $fs->get_contents( ABSPATH . WPINC . '/css/dashicons.css' );
|
||||
if ( ! empty( $fonts ) ) {
|
||||
preg_match_all( '@\.dashicons-(\w+):before@', $fonts, $matches );
|
||||
foreach ( $matches[1] as $item ) {
|
||||
if ( 'before' === $item ) {
|
||||
continue;
|
||||
}
|
||||
$data[ 'dashicons dashicons-' . $item ] = $item;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'roles':
|
||||
case 'role':
|
||||
global $wp_roles;
|
||||
$results = $wp_roles->get_names();
|
||||
$data = $this->process_results( $results, '', '', $display_keys, $secondary_key );
|
||||
|
||||
break;
|
||||
|
||||
case 'sidebars':
|
||||
case 'sidebar':
|
||||
global $wp_registered_sidebars;
|
||||
$data = $this->process_results( $wp_registered_sidebars, '', 'name', $display_keys, $secondary_key );
|
||||
break;
|
||||
case 'capabilities':
|
||||
case 'capability':
|
||||
global $wp_roles;
|
||||
$results = array();
|
||||
foreach ( $wp_roles->roles as $role ) {
|
||||
foreach ( $role['capabilities'] as $key => $cap ) {
|
||||
$results[ $key ] = ucwords( str_replace( '_', ' ', $key ) );
|
||||
}
|
||||
}
|
||||
$data = $this->process_results( $results, '', '', $display_keys, $secondary_key );
|
||||
|
||||
break;
|
||||
|
||||
case 'capabilities_grouped':
|
||||
case 'capability_grouped':
|
||||
case 'capabilities_group':
|
||||
case 'capability_group':
|
||||
global $wp_roles;
|
||||
|
||||
foreach ( $wp_roles->roles as $role ) {
|
||||
$caps = array();
|
||||
foreach ( $role['capabilities'] as $key => $cap ) {
|
||||
$caps[ $key ] = ucwords( str_replace( '_', ' ', $key ) );
|
||||
}
|
||||
asort( $caps );
|
||||
$data[ $role['name'] ] = $caps;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'callback':
|
||||
if ( ! empty( $args ) && is_string( $args ) && function_exists( $args ) ) {
|
||||
$data = call_user_func( $args, $current_value );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Router for translation based on the given post type.
|
||||
*
|
||||
* @param string $type Type of data request.
|
||||
* @param mixed|array $current_value Current value stored in DB.
|
||||
* @param array|string $args Arguments for the call.
|
||||
*/
|
||||
private function maybe_get_translation( string $type, &$current_value = '', $args = array() ) {
|
||||
switch ( $type ) {
|
||||
case 'categories':
|
||||
case 'category':
|
||||
$this->maybe_translate( $current_value, 'category' );
|
||||
break;
|
||||
|
||||
case 'pages':
|
||||
case 'page':
|
||||
$this->maybe_translate( $current_value, 'page' );
|
||||
break;
|
||||
|
||||
case 'terms':
|
||||
case 'term':
|
||||
$this->maybe_translate( $current_value, $args['taxonomy'] ?? '' );
|
||||
break;
|
||||
|
||||
case 'tags':
|
||||
case 'tag':
|
||||
$this->maybe_translate( $current_value, 'post_tag' );
|
||||
break;
|
||||
|
||||
case 'menus':
|
||||
case 'menu':
|
||||
$this->maybe_translate( $current_value, 'nav_menu' );
|
||||
break;
|
||||
|
||||
case 'post':
|
||||
case 'posts':
|
||||
$this->maybe_translate( $current_value, 'post' );
|
||||
break;
|
||||
default:
|
||||
$this->maybe_translate( $current_value, '' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe translate the values.
|
||||
*
|
||||
* @param mixed|array $value Value.
|
||||
* @param mixed|array $post_type Post type.
|
||||
*/
|
||||
private function maybe_translate( &$value, $post_type ) {
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$value = apply_filters( "redux/options/$this->opt_name/wordpress_data/translate/post_type_value", $value, $post_type );
|
||||
|
||||
// WPML Integration, see https://wpml.org/documentation/support/creating-multilingual-wordpress-themes/language-dependent-ids/.
|
||||
if ( function_exists( 'icl_object_id' ) ) {
|
||||
if ( has_filter( 'wpml_object_id' ) ) {
|
||||
if ( Redux_Helpers::is_integer( $value ) ) {
|
||||
$value = apply_filters( 'wpml_object_id', $value, $post_type, true );
|
||||
} elseif ( is_array( $value ) ) {
|
||||
$value = array_map(
|
||||
function ( $val ) use ( $post_type ) {
|
||||
return apply_filters( 'wpml_object_id', $val, $post_type, true );
|
||||
},
|
||||
$value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default arguments for a current query (existing data).
|
||||
*
|
||||
* @param string $type Type of data request.
|
||||
* @param array|string $args Arguments for the call.
|
||||
* @param mixed|array $current_value Current value stored in DB.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_current_data_args( string $type, $args, $current_value ): array {
|
||||
// In this section we set the default arguments for each data type.
|
||||
switch ( $type ) {
|
||||
case 'categories':
|
||||
case 'category':
|
||||
case 'pages':
|
||||
case 'page':
|
||||
case 'terms':
|
||||
case 'term':
|
||||
case 'users':
|
||||
case 'user':
|
||||
$args['include'] = $current_value;
|
||||
break;
|
||||
case 'tags':
|
||||
case 'tag':
|
||||
$args['get'] = 'all';
|
||||
break;
|
||||
case 'menus':
|
||||
case 'menu':
|
||||
$args['object_ids'] = $current_value;
|
||||
break;
|
||||
case 'post':
|
||||
case 'posts':
|
||||
if ( ! empty( $current_value ) ) {
|
||||
$args['post__in'] = is_array( $current_value ) ? $current_value : array( $current_value );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
$args = array();
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get default arguments for a given data type.
|
||||
*
|
||||
* @param string $type Type of data request.
|
||||
* @param array|string $args Arguments for the call.
|
||||
*
|
||||
* @return array|string
|
||||
*/
|
||||
private function get_arg_defaults( string $type, $args = array() ) {
|
||||
// In this section we set the default arguments for each data type.
|
||||
switch ( $type ) {
|
||||
case 'categories':
|
||||
case 'category':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'taxonomy' => 'category',
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'pages':
|
||||
case 'page':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'display_keys' => true,
|
||||
'posts_per_page' => 20,
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'post_type':
|
||||
case 'post_types':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'public' => true,
|
||||
'exclude_from_search' => false,
|
||||
'output' => 'names',
|
||||
'operator' => 'and',
|
||||
)
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
case 'tag':
|
||||
case 'tags':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'get' => 'all',
|
||||
'display_keys' => true,
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'sidebars':
|
||||
case 'sidebar':
|
||||
case 'capabilities':
|
||||
case 'capability':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'display_keys' => true,
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
case 'capabilities_grouped':
|
||||
case 'capability_grouped':
|
||||
case 'capabilities_group':
|
||||
case 'capability_group':
|
||||
$args = wp_parse_args(
|
||||
$args,
|
||||
array(
|
||||
'data_sortby' => '',
|
||||
)
|
||||
);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Accordion Field Class
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Accordion
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Accordion' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_Accordion class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Accordion extends Redux_Field {
|
||||
|
||||
/**
|
||||
* Set field defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
$defaults = array(
|
||||
'position' => 'end',
|
||||
'style' => '',
|
||||
'class' => '',
|
||||
'title' => '',
|
||||
'subtitle' => '',
|
||||
'open' => '',
|
||||
'open-icon' => 'el-plus',
|
||||
'close-icon' => 'el-minus',
|
||||
);
|
||||
|
||||
$this->field = wp_parse_args( $this->field, $defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field Render Function.
|
||||
* Takes the vars and outputs the HTML for the field in the settings
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
$guid = uniqid();
|
||||
$field_pos = '';
|
||||
$add_class = '';
|
||||
|
||||
// primary container.
|
||||
if ( 'start' === $this->field['position'] ) {
|
||||
$add_class = ' form-table-accordion';
|
||||
$field_pos = 'start';
|
||||
} elseif ( 'end' === $this->field['position'] ) {
|
||||
$add_class = ' hide';
|
||||
$field_pos = 'end';
|
||||
}
|
||||
|
||||
echo '<input type="hidden" id="accordion-' . esc_attr( $this->field['id'] ) . '-marker" data-open-icon="' . esc_attr( $this->field['open-icon'] ) . '" data-close-icon="' . esc_attr( $this->field['close-icon'] ) . '"></td></tr></table>';
|
||||
|
||||
$is_open = false;
|
||||
if ( isset( $this->field['open'] ) && true === $this->field['open'] ) {
|
||||
$is_open = true;
|
||||
}
|
||||
|
||||
echo '<div data-state="' . esc_attr( $is_open ) . '" data-position="' . esc_attr( $field_pos ) . '" id="' . esc_attr( $this->field['id'] ) . '" class="redux-accordion-field redux-field ' . esc_attr( $this->field['style'] ) . esc_attr( $this->field['class'] ) . '">';
|
||||
echo '<div class="control">';
|
||||
echo '<div class="redux-accordion-info' . esc_attr( $add_class ) . '">';
|
||||
|
||||
if ( ! empty( $this->field['title'] ) ) {
|
||||
echo '<h3>' . esc_html( $this->field['title'] ) . '</h3>';
|
||||
}
|
||||
|
||||
$icon_class = '';
|
||||
if ( ! empty( $this->field['subtitle'] ) ) {
|
||||
echo '<div class="redux-accordion-desc">' . esc_html( $this->field['subtitle'] ) . '</div>';
|
||||
$icon_class = ' subtitled';
|
||||
}
|
||||
|
||||
echo '<span class="el el-plus' . esc_attr( $icon_class ) . '"></span>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
echo '<table id="accordion-table-' . esc_attr( $this->field['id'] ) . '" data-id="' . esc_attr( $this->field['id'] ) . '" class="form-table form-table-accordion no-border' . esc_attr( $add_class ) . '"><tbody><tr class="hide"><th></th><td id="' . esc_attr( $guid ) . '">';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Function.
|
||||
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
|
||||
// Set up min files for dev_mode = false.
|
||||
$min = Redux_Functions::isMin();
|
||||
|
||||
// Field dependent JS.
|
||||
wp_enqueue_script(
|
||||
'redux-field-accordion',
|
||||
$this->url . 'redux-accordion' . $min . '.js',
|
||||
array( 'jquery', 'redux-js' ),
|
||||
Redux_Extension_Accordion::$version,
|
||||
true
|
||||
);
|
||||
|
||||
// Field CSS.
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-accordion',
|
||||
$this->url . 'redux-accordion.css',
|
||||
array(),
|
||||
Redux_Extension_Accordion::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,21 @@
|
||||
.redux-main .redux-accordion-field { overflow: hidden; cursor: pointer; margin-top: 10px; }
|
||||
|
||||
.redux-main .redux-accordion-field:first-child { margin-top: 0; }
|
||||
|
||||
.redux-main .redux-accordion-field .redux-accordion-info { border: 1px solid #dfdfdf; padding: 10px 15px; height: auto; min-height: 20px; overflow: hidden; word-wrap: break-word; background: #FAFAFA; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); }
|
||||
|
||||
.redux-main .redux-accordion-field .redux-accordion-info:hover { border-color: #999; }
|
||||
|
||||
.redux-main .redux-accordion-field .redux-accordion-info .el { color: #000; float: right; margin-top: -23px; margin-right: 10px; -webkit-transition: all 0.5s; transition: all 0.5s; }
|
||||
|
||||
.redux-main .redux-accordion-field .redux-accordion-info .el.subtitled { margin-top: -33px; }
|
||||
|
||||
.redux-main .redux-accordion-field h3 { margin: 0; border-bottom: 0; }
|
||||
|
||||
.redux-main .redux-accordion-field .redux-accordion-desc { margin: -5px 0 10px; }
|
||||
|
||||
.redux-accordion-wrap { border: 1px solid #e5e5e5; -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.04); border-top: none; padding: 0 15px; background: #fff; }
|
||||
|
||||
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtYWNjb3JkaW9uLmNzcyIsInNvdXJjZXMiOlsicmVkdXgtYWNjb3JkaW9uLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsQUFDSSxXQURPLENBQ1Asc0JBQXNCLENBQUMsRUFDbkIsUUFBUSxFQUFFLE1BQU0sRUFDaEIsTUFBTSxFQUFFLE9BQU8sRUFDZixVQUFVLEVBQUUsSUFBSSxHQXlDbkI7O0FBN0NMLEFBTVEsV0FORyxDQUNQLHNCQUFzQixBQUtqQixZQUFZLENBQUMsRUFDVixVQUFVLEVBQUUsQ0FBQyxHQUNoQjs7QUFSVCxBQVVRLFdBVkcsQ0FDUCxzQkFBc0IsQ0FTbEIscUJBQXFCLENBQUMsRUFDbEIsTUFBTSxFQUFFLGlCQUFpQixFQUN6QixPQUFPLEVBQUUsU0FBUyxFQUNsQixNQUFNLEVBQUUsSUFBSSxFQUNaLFVBQVUsRUFBRSxJQUFJLEVBQ2hCLFFBQVEsRUFBRSxNQUFNLEVBQ2hCLFNBQVMsRUFBRSxVQUFVLEVBQ3JCLFVBQVUsRUFBRSxPQUFPLEVBQ25CLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLG1CQUFrQixFQUNoRCxVQUFVLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsbUJBQWtCLEdBZ0IzQzs7QUFuQ1QsQUFxQlksV0FyQkQsQ0FDUCxzQkFBc0IsQ0FTbEIscUJBQXFCLEFBV2hCLE1BQU0sQ0FBQyxFQUNKLFlBQVksRUFBRSxJQUFJLEdBQ3JCOztBQXZCYixBQXlCWSxXQXpCRCxDQUNQLHNCQUFzQixDQVNsQixxQkFBcUIsQ0FlakIsR0FBRyxDQUFDLEVBQ0EsS0FBSyxFQUFFLElBQUksRUFDWCxLQUFLLEVBQUUsS0FBSyxFQUNaLFVBQVUsRUFBRSxLQUFLLEVBQ2pCLFlBQVksRUFBRSxJQUFJLEVBQ2xCLFVBQVUsRUFBRSxRQUFRLEdBSXZCOztBQWxDYixBQStCZ0IsV0EvQkwsQ0FDUCxzQkFBc0IsQ0FTbEIscUJBQXFCLENBZWpCLEdBQUcsQUFNRSxVQUFVLENBQUMsRUFDUixVQUFVLEVBQUUsS0FBSyxHQUNwQjs7QUFqQ2pCLEFBcUNRLFdBckNHLENBQ1Asc0JBQXNCLENBb0NsQixFQUFFLENBQUMsRUFDQyxNQUFNLEVBQUUsQ0FBQyxFQUNULGFBQWEsRUFBRSxDQUFDLEdBQ25COztBQXhDVCxBQTBDUSxXQTFDRyxDQUNQLHNCQUFzQixDQXlDbEIscUJBQXFCLENBQUMsRUFDbEIsTUFBTSxFQUFFLFdBQVcsR0FDdEI7O0FBSVQsQUFBQSxxQkFBcUIsQ0FBQyxFQUNsQixNQUFNLEVBQUUsaUJBQWlCLEVBQ3pCLGtCQUFrQixFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLG1CQUFrQixFQUNoRCxVQUFVLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsbUJBQWtCLEVBQ3hDLFVBQVUsRUFBRSxJQUFJLEVBQ2hCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsVUFBVSxFQUFFLElBQUksR0FDbkIifQ== */
|
||||
|
||||
/*# sourceMappingURL=redux-accordion.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,109 @@
|
||||
/* global jQuery, document, redux */
|
||||
|
||||
( function ( $ ) {
|
||||
'use strict';
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.accordion = redux.field_objects.accordion || {};
|
||||
|
||||
redux.field_objects.accordion.init = function ( selector ) {
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-accordion:visible' );
|
||||
}
|
||||
|
||||
$( selector ).each(
|
||||
function () {
|
||||
var $id;
|
||||
var group;
|
||||
var test;
|
||||
var accordionMarker;
|
||||
var openIcon;
|
||||
var closeIcon;
|
||||
var table;
|
||||
|
||||
var el = $( this );
|
||||
var parent = el;
|
||||
|
||||
if ( ! el.hasClass( 'redux-field-container' ) ) {
|
||||
parent = el.parents( '.redux-field-container:first' );
|
||||
}
|
||||
if ( parent.hasClass( 'redux-field-init' ) ) {
|
||||
parent.removeClass( 'redux-field-init' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = el.attr( 'data-id' );
|
||||
table = $( '#accordion-' + $id + '-marker' );
|
||||
|
||||
table.parents( 'tr:first' ).css( { display: 'none' } ).prev( 'tr' ).css( 'border-bottom', 'none' );
|
||||
|
||||
group = table.parents( '.redux-group-tab:first' );
|
||||
|
||||
if ( ! group.hasClass( 'accordionsChecked' ) ) {
|
||||
group.addClass( 'accordionsChecked' );
|
||||
test = group.find( '.redux-accordion-indent-start h3' );
|
||||
|
||||
$.each(
|
||||
test,
|
||||
function ( key, value ) {
|
||||
key = null;
|
||||
|
||||
$( value ).css( 'margin-top', '20px' );
|
||||
}
|
||||
);
|
||||
|
||||
if ( '20px' === group.find( 'h3:first' ).css( 'margin-top' ) ) {
|
||||
group.find( 'h3:first' ).css( 'margin-top', '0' );
|
||||
}
|
||||
|
||||
accordionMarker = table;
|
||||
openIcon = accordionMarker.data( 'open-icon' );
|
||||
closeIcon = accordionMarker.data( 'close-icon' );
|
||||
|
||||
group.find( '.redux-accordion-field' ).on(
|
||||
'click',
|
||||
function ( e ) {
|
||||
var id = $( this ).attr( 'id' );
|
||||
var table = $( '#accordion-table-' + id );
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
if ( table.closest( 'div' ).is( ':visible' ) ) {
|
||||
$( this ).find( '.el' ).removeClass( closeIcon ).addClass( openIcon );
|
||||
table.closest( 'div' ).slideUp();
|
||||
} else {
|
||||
table.closest( 'div' ).slideDown();
|
||||
$.redux.initFields();
|
||||
$( this ).find( '.el' ).removeClass( openIcon ).addClass( closeIcon );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
group.find( '.redux-accordion-field' ).each(
|
||||
function () {
|
||||
var id;
|
||||
var state;
|
||||
var table;
|
||||
var position = $( this ).data( 'position' );
|
||||
|
||||
if ( 'start' === position ) {
|
||||
id = $( this ).attr( 'id' );
|
||||
state = Boolean( $( this ).data( 'state' ) );
|
||||
table = $( '#accordion-table-' + id );
|
||||
|
||||
table.wrapAll( '<div class="redux-accordion-wrap"/>' );
|
||||
|
||||
if ( false === state ) {
|
||||
table.closest( 'div' ).hide();
|
||||
} else {
|
||||
$( this ).find( '.el' ).removeClass( openIcon ).addClass( closeIcon );
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
.redux-main .redux-accordion-field{overflow:hidden;cursor:pointer;margin-top:10px}.redux-main .redux-accordion-field:first-child{margin-top:0}.redux-main .redux-accordion-field .redux-accordion-info{border:1px solid #dfdfdf;padding:10px 15px;height:auto;min-height:20px;overflow:hidden;word-wrap:break-word;background:#fafafa;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04)}.redux-main .redux-accordion-field .redux-accordion-info:hover{border-color:#999}.redux-main .redux-accordion-field .redux-accordion-info .el{color:#000;float:right;margin-top:-23px;margin-right:10px;-webkit-transition:all .5s;transition:all .5s}.redux-main .redux-accordion-field .redux-accordion-info .el.subtitled{margin-top:-33px}.redux-main .redux-accordion-field h3{margin:0;border-bottom:0}.redux-main .redux-accordion-field .redux-accordion-desc{margin:0;margin-bottom:10px;margin-top:-5px}.redux-accordian-wrap{border:1px solid #e5e5e5;-webkit-box-shadow:0 1px 1px rgba(0,0,0,0.04);box-shadow:0 1px 1px rgba(0,0,0,0.04);border-top:0;padding:0 15px;background:#fff}
|
||||
@@ -0,0 +1 @@
|
||||
!function(t){"use strict";redux.field_objects=redux.field_objects||{},redux.field_objects.accordion=redux.field_objects.accordion||{},redux.field_objects.accordion.init=function(i){i=i||t(document).find(".redux-group-tab:visible").find(".redux-container-accordion:visible"),t(i).each(function(){var i,s,d,e=t(this),a=e;(a=e.hasClass("redux-field-container")?a:e.parents(".redux-field-container:first")).hasClass("redux-field-init")&&(a.removeClass("redux-field-init"),a=e.attr("data-id"),(e=t("#accordion-"+a+"-marker")).parents("tr:first").css({display:"none"}).prev("tr").css("border-bottom","none"),(a=e.parents(".redux-group-tab:first")).hasClass("accordionsChecked")||(a.addClass("accordionsChecked"),i=a.find(".redux-accordion-indent-start h3"),t.each(i,function(i,e){t(e).css("margin-top","20px")}),"20px"===a.find("h3:first").css("margin-top")&&a.find("h3:first").css("margin-top","0"),s=(i=e).data("open-icon"),d=i.data("close-icon"),a.find(".redux-accordion-field").on("click",function(i){var e=t(this).attr("id"),e=t("#accordion-table-"+e);i.preventDefault(),e.closest("div").is(":visible")?(t(this).find(".el").removeClass(d).addClass(s),e.closest("div").slideUp()):(e.closest("div").slideDown(),t.redux.initFields(),t(this).find(".el").removeClass(s).addClass(d))}),a.find(".redux-accordion-field").each(function(){var i,e;"start"===t(this).data("position")&&(e=t(this).attr("id"),i=Boolean(t(this).data("state")),(e=t("#accordion-table-"+e)).wrapAll('<div class="redux-accordion-wrap"/>'),!1===i?e.closest("div").hide():t(this).find(".el").removeClass(s).addClass(d))})))})}}(jQuery);
|
||||
@@ -0,0 +1,56 @@
|
||||
.redux-main {
|
||||
.redux-accordion-field {
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
margin-top: 10px;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.redux-accordion-info {
|
||||
border: 1px solid #dfdfdf;
|
||||
padding: 10px 15px;
|
||||
height: auto;
|
||||
min-height: 20px;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
background: #FAFAFA;
|
||||
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
||||
|
||||
&:hover {
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
.el {
|
||||
color: #000;
|
||||
float: right;
|
||||
margin-top: -23px;
|
||||
margin-right: 10px;
|
||||
transition: all 0.5s;
|
||||
&.subtitled {
|
||||
margin-top: -33px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.redux-accordion-desc {
|
||||
margin: -5px 0 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-accordion-wrap {
|
||||
border: 1px solid #e5e5e5;
|
||||
-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
||||
box-shadow: 0 1px 1px rgba(0, 0, 0, .04);
|
||||
border-top: none;
|
||||
padding: 0 15px;
|
||||
background: #fff;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Accordion Extension Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Extension_Accordion
|
||||
* @version 4.3.16
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Extension_Accordion' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_Extension_Accordion extension class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Extension_Accordion extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.3.16';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension_name = 'Accordion';
|
||||
|
||||
/**
|
||||
* Class Constructor. Defines the args for the extension class
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param ReduxFramework $redux Parent settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
$this->add_field( 'accordion' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,707 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Color Scheme Extension Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Extension_Color_Scheme
|
||||
*
|
||||
* @version 4.4.10
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Extension_Color_Scheme' ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Extension_Color_Scheme
|
||||
*/
|
||||
class Redux_Extension_Color_Scheme extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.4.10';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension_name = 'Color Schemes';
|
||||
|
||||
/**
|
||||
* Field ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $field_id = '';
|
||||
|
||||
/**
|
||||
* Transparent output bit.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
public $output_transparent = false;
|
||||
|
||||
/**
|
||||
* Extension field name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $field_name = '';
|
||||
|
||||
/**
|
||||
* Class Constructor. Defines the args for the extensions class
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*
|
||||
* @param object $redux Parent settings.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
$this->add_field( 'color_scheme' );
|
||||
$this->field_name = 'color_scheme';
|
||||
|
||||
add_filter( "redux/options/{$this->parent->args['opt_name']}/defaults", array( $this, 'set_defaults' ) );
|
||||
|
||||
// Ajax hooks.
|
||||
add_action( 'wp_ajax_redux_color_schemes', array( $this, 'parse_ajax' ) );
|
||||
add_action( 'wp_ajax_nopriv_redux_color_schemes', array( $this, 'parse_ajax' ) );
|
||||
|
||||
// Reset hooks.
|
||||
add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults', array( $this, 'reset_defaults' ), 0, 3 );
|
||||
add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/defaults_section', array( $this, 'reset_defaults_section' ), 0, 3 );
|
||||
|
||||
// Save filter.
|
||||
add_action( 'redux/validate/' . $this->parent->args['opt_name'] . '/before_validation', array( $this, 'save_hook' ), 0, 3 );
|
||||
|
||||
// Register hook - to get field id and prep helper.
|
||||
add_action( 'redux/options/' . $this->parent->args['opt_name'] . '/field/' . $this->field_name . '/register', array( $this, 'register_field' ) );
|
||||
|
||||
include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
|
||||
Redux_Color_Scheme_Functions::init( $redux );
|
||||
|
||||
$field = Redux_Color_Scheme_Functions::get_field( $redux );
|
||||
|
||||
if ( ! is_array( $field ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->field_id = $field['id'];
|
||||
|
||||
// Prep storage.
|
||||
$upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
|
||||
|
||||
// Create uploads/redux_scheme_colors/ folder.
|
||||
if ( ! is_dir( $upload_dir ) ) {
|
||||
$redux->filesystem->execute( 'mkdir', $upload_dir );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default values after reset.
|
||||
*
|
||||
* @param array $defaults Default values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function set_defaults( array $defaults = array() ): array {
|
||||
if ( ! Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
if ( empty( $this->field_id ) ) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
$x = get_option( $this->parent->args['opt_name'] );
|
||||
$color_opts = $x[ $this->field_id ] ?? array();
|
||||
$wrong_format = false;
|
||||
|
||||
if ( ! isset( $color_opts['color_scheme_name'] ) ) {
|
||||
$wrong_format = true;
|
||||
|
||||
$data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
|
||||
|
||||
if ( ! empty( $data ) && isset( $x[ $this->field_id ] ) ) {
|
||||
$x[ $this->field_id ] = $data;
|
||||
|
||||
update_option( $this->parent->args['opt_name'], $x );
|
||||
}
|
||||
}
|
||||
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
|
||||
$ot_val = Redux_Color_Scheme_Functions::get_output_transparent_val();
|
||||
$this->output_transparent = $ot_val;
|
||||
|
||||
Redux_Color_Scheme_Functions::convert_to_db();
|
||||
|
||||
$scheme_key = Redux_Color_Scheme_Functions::get_scheme_key();
|
||||
$scheme_data = get_option( $scheme_key );
|
||||
|
||||
$scheme_data_exists = ! empty( $scheme_data );
|
||||
|
||||
$default_exists = in_array( 'default', array_map( 'strtolower', Redux_Color_Scheme_Functions::get_scheme_names() ), true );
|
||||
|
||||
if ( ! $scheme_data_exists || ! $default_exists || $wrong_format ) {
|
||||
$data = $this->get_default_data();
|
||||
|
||||
// Add to (and/or create) JSON scheme file.
|
||||
Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
|
||||
|
||||
// Set default scheme.
|
||||
Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
|
||||
|
||||
$data = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
|
||||
|
||||
$this->parent->options[ $this->field_id ] = $data;
|
||||
|
||||
$defaults[ $this->field_id ] = $data;
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field Register. Sets the whole smash up.
|
||||
*
|
||||
* @param array $data Field data.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function register_field( array $data ) {
|
||||
|
||||
// Include color_scheme helper.
|
||||
include_once $this->extension_dir . 'color_scheme/inc/class-redux-color-scheme-functions.php';
|
||||
|
||||
if ( isset( $data['output_transparent'] ) ) {
|
||||
$this->output_transparent = $data['output_transparent'];
|
||||
}
|
||||
|
||||
$this->field_id = $data['id'];
|
||||
Redux_Color_Scheme_Functions::$field_id = $data['id'];
|
||||
|
||||
// Set helper parent object.
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
|
||||
// Prep storage.
|
||||
$upload_dir = Redux_Color_Scheme_Functions::$upload_dir;
|
||||
|
||||
// Set upload_dir cookie.
|
||||
setcookie( 'redux_color_scheme_upload_dir', $upload_dir, 0, '/' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset defaults.
|
||||
*
|
||||
* @param array $defaults Default values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function reset_defaults( array $defaults = array() ): array {
|
||||
if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
|
||||
// Check if reset_all was fired.
|
||||
$this->reset_all();
|
||||
$defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset section defaults.
|
||||
*
|
||||
* @param array $defaults Default values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function reset_defaults_section( array $defaults = array() ): array {
|
||||
if ( Redux_Helpers::is_field_in_use( $this->parent, 'color_scheme' ) ) {
|
||||
// Get the current tab/section number.
|
||||
if ( isset( $_COOKIE['redux_current_tab'] ) ) {
|
||||
$cur_tab = sanitize_text_field( wp_unslash( $_COOKIE['redux_current_tab'] ) );
|
||||
|
||||
// Get the tab/section number field is used on.
|
||||
$tab_num = $this->parent->field_sections['color_scheme'][ $this->field_id ];
|
||||
|
||||
// Match...
|
||||
if ( $cur_tab === $tab_num ) {
|
||||
|
||||
// Reset data.
|
||||
$this->reset_all();
|
||||
}
|
||||
$defaults[ $this->field_id ] = Redux_Color_Scheme_Functions::data_array_from_scheme( 'Default' );
|
||||
}
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Changes Hook. What to do when changes are saved
|
||||
*
|
||||
* @param array $saved_options Saved data.
|
||||
* @param array $old_options Previous data.
|
||||
*
|
||||
* @return array
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function save_hook( array $saved_options = array(), array $old_options = array() ): array {
|
||||
if ( ! isset( $saved_options[ $this->field_id ] ) || empty( $saved_options[ $this->field_id ] ) || ( is_array( $saved_options[ $this->field_id ] ) && $old_options === $saved_options ) || ! array_key_exists( $this->field_id, $saved_options ) ) {
|
||||
return $saved_options;
|
||||
}
|
||||
|
||||
// We'll use the reset hook instead.
|
||||
if ( ! empty( $saved_options['defaults'] ) || ! empty( $saved_options['defaults-section'] ) ) {
|
||||
return $saved_options;
|
||||
}
|
||||
|
||||
$first_value = reset( $saved_options[ $this->field_id ] ); // First Element's Value.
|
||||
|
||||
// Parse the JSON to an array.
|
||||
if ( isset( $first_value['data'] ) ) {
|
||||
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
Redux_Color_Scheme_Functions::$field_id = $this->field_id;
|
||||
|
||||
Redux_Color_Scheme_Functions::set_current_scheme_id( $saved_options['redux-scheme-select'] );
|
||||
|
||||
// Get the current field ID.
|
||||
$raw_data = $saved_options[ $this->field_id ];
|
||||
|
||||
// Create a new array.
|
||||
$save_data = array();
|
||||
|
||||
// Enum through saved data.
|
||||
foreach ( $raw_data as $id => $val ) {
|
||||
|
||||
if ( 'color_scheme_name' !== $id ) {
|
||||
if ( is_array( $val ) ) {
|
||||
|
||||
if ( ! isset( $val['data'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = json_decode( rawurldecode( $val['data'] ), true );
|
||||
|
||||
// Sanitize everything.
|
||||
$color = $data['color'] ?? '';
|
||||
$alpha = $data['alpha'] ?? 1;
|
||||
|
||||
$id = $data['id'] ?? $id;
|
||||
$title = $data['title'] ?? $id;
|
||||
|
||||
$grp = $data['group'] ?? '';
|
||||
|
||||
if ( '' === $color || 'transparent' === $color ) {
|
||||
$rgba = $this->output_transparent ? 'transparent' : '';
|
||||
} else {
|
||||
$rgba = Redux_Helpers::hex2rgba( $color, $alpha );
|
||||
}
|
||||
|
||||
// Create an array of saved data.
|
||||
$save_data[] = array(
|
||||
'id' => $id,
|
||||
'title' => $title,
|
||||
'color' => $color,
|
||||
'alpha' => $alpha,
|
||||
'group' => $grp,
|
||||
'rgba' => $rgba,
|
||||
);
|
||||
} else {
|
||||
$save_data[] = array(
|
||||
'id' => $id,
|
||||
'value' => $val,
|
||||
'type' => 'select',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$new_scheme = array();
|
||||
|
||||
$new_scheme['color_scheme_name'] = Redux_Color_Scheme_Functions::get_current_scheme_id();
|
||||
|
||||
// Enum through values and assign them to a new array.
|
||||
foreach ( $save_data as $val ) {
|
||||
if ( isset( $val['id'] ) ) {
|
||||
$new_scheme[ $val['id'] ] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// Filter for DB save
|
||||
// Doesn't need to save select arrays to a database,
|
||||
// just the id => value.
|
||||
$database_data = $new_scheme;
|
||||
|
||||
foreach ( $database_data as $k => $v ) {
|
||||
if ( isset( $v['type'] ) ) {
|
||||
$val = $v['value'];
|
||||
|
||||
unset( $database_data[ $k ] );
|
||||
|
||||
$database_data[ $k ] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$saved_options[ $this->field_id ] = $database_data;
|
||||
|
||||
// Check if we should save this compared to the old data.
|
||||
$save_scheme = false;
|
||||
|
||||
// Doesn't exist or is empty.
|
||||
if ( ! isset( $old_options[ $this->field_id ] ) || ( isset( $old_options[ $this->field_id ] ) && ! empty( $old_options[ $this->field_id ] ) ) ) {
|
||||
$save_scheme = true;
|
||||
}
|
||||
|
||||
// Isn't empty and isn't the same as the new array.
|
||||
if ( ! empty( $old_options[ $this->field_id ] ) && $saved_options[ $this->field_id ] !== $old_options[ $this->field_id ] ) {
|
||||
$save_scheme = true;
|
||||
}
|
||||
|
||||
if ( $save_scheme ) {
|
||||
$scheme = Redux_Color_Scheme_Functions::get_current_scheme_id();
|
||||
Redux_Color_Scheme_Functions::set_scheme_data( $scheme, $save_data );
|
||||
}
|
||||
}
|
||||
|
||||
return $saved_options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset data. Restores colour picker to default values
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function reset_data() {
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
Redux_Color_Scheme_Functions::$field_id = $this->field_id;
|
||||
|
||||
// Get default data.
|
||||
$data = $this->get_default_data();
|
||||
|
||||
// Add to (and/or create) JSON scheme file.
|
||||
Redux_Color_Scheme_Functions::set_scheme_data( 'Default', $data );
|
||||
|
||||
// Set default scheme.
|
||||
Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset All Hook. Todo list when all data is reset
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function reset_all() {
|
||||
if ( ! empty( $this->field_id ) && isset( $this->parent->options_defaults[ $this->field_id ] ) && ! empty( $this->parent->options_defaults[ $this->field_id ] ) ) {
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
Redux_Color_Scheme_Functions::$field_id = $this->field_id;
|
||||
|
||||
$this->reset_data();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX evaluator. Determine course of action based on AJAX callback
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function parse_ajax() {
|
||||
if ( isset( $_REQUEST['nonce'] ) && isset( $_REQUEST['opt_name'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_REQUEST['nonce'] ) ), 'redux_' . sanitize_text_field( wp_unslash( $_REQUEST['opt_name'] ) ) . '_color_schemes' ) ) {
|
||||
$parent = $this->parent;
|
||||
|
||||
// Do action.
|
||||
if ( isset( $_REQUEST['type'] ) ) {
|
||||
|
||||
// Save scheme.
|
||||
if ( 'save' === $_REQUEST['type'] ) {
|
||||
$this->save_scheme( $parent );
|
||||
|
||||
// Delete scheme.
|
||||
} elseif ( 'delete' === $_REQUEST['type'] ) {
|
||||
$this->delete_scheme( $parent );
|
||||
|
||||
// Scheme change.
|
||||
} elseif ( 'update' === $_REQUEST['type'] ) {
|
||||
$this->get_scheme_html( $parent );
|
||||
|
||||
// Export scheme file.
|
||||
} elseif ( 'export' === $_REQUEST['type'] ) {
|
||||
$this->download_schemes();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wp_die( esc_html__( 'Invalid Security Credentials. Please reload the page and try again.', 'redux-framework' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download Scheme File.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function download_schemes() {
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
Redux_Color_Scheme_Functions::$field_id = $this->field_id;
|
||||
|
||||
// Read contents of scheme file.
|
||||
$content = Redux_Color_Scheme_Functions::read_scheme_file();
|
||||
$content = wp_json_encode( $content );
|
||||
|
||||
// Set header info.
|
||||
header( 'Content-Description: File Transfer' );
|
||||
header( 'Content-type: application/txt' );
|
||||
header( 'Content-Disposition: attachment; filename="redux_schemes_' . $this->parent->args['opt_name'] . '_' . $this->field_id . '_' . gmdate( 'm-d-Y' ) . '.json"' );
|
||||
header( 'Content-Transfer-Encoding: binary' );
|
||||
header( 'Expires: 0' );
|
||||
header( 'Cache-Control: must-revalidate' );
|
||||
header( 'Pragma: public' );
|
||||
|
||||
// File download.
|
||||
echo $content; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
|
||||
// 2B ~! 2B
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save Scheme. Saved an individual scheme to JSON scheme file.
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function save_scheme( $redux ) {
|
||||
Redux_Color_Scheme_Functions::$parent = $redux;
|
||||
Redux_Color_Scheme_Functions::$field_id = $this->field_id;
|
||||
|
||||
// Get the scheme name.
|
||||
if ( isset( $_REQUEST['scheme_name'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$scheme_name = sanitize_text_field( wp_unslash( $_REQUEST['scheme_name'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// Check for duplicates.
|
||||
$names = Redux_Color_Scheme_Functions::get_scheme_names();
|
||||
foreach ( $names as $name ) {
|
||||
$name = strtolower( $name );
|
||||
$tmp_name = strtolower( $scheme_name );
|
||||
|
||||
if ( $name === $tmp_name ) {
|
||||
echo 'fail';
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
// Get scheme data.
|
||||
if ( isset( $_REQUEST['scheme_data'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$scheme_data = wp_unslash( $_REQUEST['scheme_data'] ); // phpcs:ignore WordPress.Security
|
||||
|
||||
// Get field ID.
|
||||
if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$scheme_data = rawurldecode( $scheme_data );
|
||||
$scheme_data = json_decode( $scheme_data, true );
|
||||
|
||||
// Save scheme to file. If successful...
|
||||
if ( true === Redux_Color_Scheme_Functions::set_scheme_data( $scheme_name, $scheme_data ) ) {
|
||||
|
||||
// Update scheme selector.
|
||||
echo Redux_Color_Scheme_Functions::get_scheme_select_html( $scheme_name ); // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
die(); // a horrible death!
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Scheme. Delete individual scheme from JSON scheme file.
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function delete_scheme( $redux ) {
|
||||
|
||||
// Get deleted scheme ID.
|
||||
if ( isset( $_REQUEST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$scheme_id = sanitize_text_field( wp_unslash( $_REQUEST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// Get field ID.
|
||||
if ( isset( $_REQUEST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$field_id = sanitize_text_field( wp_unslash( $_REQUEST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// If scheme ID was passed (and why wouldn't it be?? Hmm??).
|
||||
if ( $scheme_id ) {
|
||||
Redux_Color_Scheme_Functions::$field_id = $field_id;
|
||||
Redux_Color_Scheme_Functions::$parent = $redux;
|
||||
|
||||
// Get the entire scheme file.
|
||||
$schemes = Redux_Color_Scheme_Functions::read_scheme_file();
|
||||
|
||||
// If we got a good read...
|
||||
if ( false !== $schemes ) {
|
||||
|
||||
// If scheme name exists...
|
||||
if ( isset( $schemes[ $scheme_id ] ) ) {
|
||||
|
||||
// Unset it.
|
||||
unset( $schemes[ $scheme_id ] );
|
||||
|
||||
// Save the scheme data, minus the deleted scheme. Upon success...
|
||||
if ( true === Redux_Color_Scheme_Functions::write_scheme_file( $schemes ) ) {
|
||||
|
||||
// Set default scheme.
|
||||
Redux_Color_Scheme_Functions::set_current_scheme_id( 'Default' );
|
||||
|
||||
// Update field ID.
|
||||
Redux_Color_Scheme_Functions::$field_id = $field_id;
|
||||
|
||||
// Meh TODO.
|
||||
Redux_Color_Scheme_Functions::set_database_data();
|
||||
|
||||
echo 'success';
|
||||
} else {
|
||||
echo 'Failed to write JSON file to server.';
|
||||
}
|
||||
} else {
|
||||
echo 'Scheme name does not exist in JSON string. Aborting.';
|
||||
}
|
||||
} else {
|
||||
echo 'Failed to read JSON scheme file, or file is empty.';
|
||||
}
|
||||
} else {
|
||||
echo 'No scheme ID passed. Aborting.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
die(); // rolled a two.
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the new scheme based on selection.
|
||||
*
|
||||
* @param object $redux ReduxFramework object.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return void
|
||||
*/
|
||||
private function get_scheme_html( $redux ) {
|
||||
if ( isset( $_POST['scheme_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// Get the selected scheme name.
|
||||
$scheme_id = sanitize_text_field( wp_unslash( $_POST['scheme_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
if ( isset( $_POST['field_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// Get the field ID.
|
||||
$field_id = sanitize_text_field( wp_unslash( $_POST['field_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
// Get the field class.
|
||||
$field_class = isset( $_POST['field_class'] ) ? sanitize_text_field( wp_unslash( $_POST['field_class'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
Redux_Color_Scheme_Functions::$parent = $redux;
|
||||
|
||||
// Set the updated field ID.
|
||||
Redux_Color_Scheme_Functions::$field_id = $field_id;
|
||||
|
||||
// Set the updated field class.
|
||||
Redux_Color_Scheme_Functions::$field_class = $field_class;
|
||||
|
||||
// Get the color picket layout HTML.
|
||||
$html = Redux_Color_Scheme_Functions::get_current_color_scheme_html( $scheme_id );
|
||||
|
||||
// Print!
|
||||
echo $html; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
}
|
||||
}
|
||||
|
||||
die(); // another day.
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves an array of default data for color picker.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return array Default values from config.
|
||||
*/
|
||||
private function get_default_data(): array {
|
||||
$def_opts = $this->parent->options_defaults[ $this->field_id ];
|
||||
$sections = $this->parent->sections;
|
||||
$data = array();
|
||||
|
||||
foreach ( $sections as $arr ) {
|
||||
if ( isset( $arr['fields'] ) ) {
|
||||
foreach ( $arr['fields'] as $arr2 ) {
|
||||
if ( $arr2['id'] === $this->field_id ) {
|
||||
|
||||
// Select fields.
|
||||
if ( isset( $arr2['select'] ) ) {
|
||||
foreach ( $arr2['select'] as $v ) {
|
||||
$data[] = array(
|
||||
'id' => $v['id'],
|
||||
'value' => $v['default'],
|
||||
'type' => 'select',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( $def_opts as $v ) {
|
||||
$title = $v['title'] ?? $v['id'];
|
||||
$color = $v['color'] ?? '';
|
||||
$alpha = $v['alpha'] ?? 1;
|
||||
$grp = $v['group'] ?? '';
|
||||
|
||||
if ( '' === $color || 'transparent' === $color ) {
|
||||
$rgba = $this->output_transparent ? 'transparent' : '';
|
||||
} else {
|
||||
$rgba = Redux_Helpers::hex2rgba( $color, $alpha );
|
||||
}
|
||||
|
||||
$data[] = array(
|
||||
'id' => $v['id'],
|
||||
'title' => $title,
|
||||
'color' => $color,
|
||||
'alpha' => $alpha,
|
||||
'group' => $grp,
|
||||
'rgba' => $rgba,
|
||||
);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias( 'Redux_Extension_Color_Scheme', 'ReduxFramework_Extension_Color_Scheme' );
|
||||
@@ -0,0 +1,381 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Color Scheme Attach Class
|
||||
*
|
||||
* WordPress' functions are lot loaded in this file due to a post-callback in javascript. We therefore must
|
||||
* compensate for WPCS by creating our own validate/sanitize/nonce functions, which are comments throughout.
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Color_Scheme_Import
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'Redux_Color_Scheme_Import' ) ) {
|
||||
/**
|
||||
* Class Redux_Color_Scheme_Import
|
||||
*/
|
||||
class Redux_Color_Scheme_Import {
|
||||
|
||||
/**
|
||||
* Errors.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $err = '';
|
||||
|
||||
/**
|
||||
* Upload directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $upload_dir = '';
|
||||
|
||||
/**
|
||||
* Field ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $field_id = '';
|
||||
|
||||
/**
|
||||
* Option panel opt_name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $opt_name = '';
|
||||
|
||||
/**
|
||||
* Text result.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $result;
|
||||
|
||||
/**
|
||||
* Data.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $data;
|
||||
|
||||
/**
|
||||
* Redux_Color_Scheme_Import constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// Set result to false.
|
||||
$this->result = false;
|
||||
|
||||
// String used more than once.
|
||||
$abort = ' Aborting import.';
|
||||
|
||||
// This is our nonce check using MD5.
|
||||
// $this->sanitize_input replaces sanitize_title() and wp_unslash().
|
||||
// phpcs:disable WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification
|
||||
if ( isset( $_REQUEST['nonce'] ) && $this->sanitize_input( $_REQUEST['nonce'] ) === md5( 'color_scheme_import' ) ) { // WPCS: CSRF ok, sanitization ok.
|
||||
|
||||
// Is request type set?
|
||||
if ( isset( $_REQUEST['type'] ) ) { // WPCS: CSRF ok.
|
||||
|
||||
// Is request type import?
|
||||
if ( 'import' === $this->sanitize_input( $_REQUEST['type'] ) ) { // WPCS: CSRF ok, sanitization ok.
|
||||
|
||||
// Get upload dir from cookie.
|
||||
if ( true === $this->get_upload_dir() ) {
|
||||
|
||||
// Check for field id.
|
||||
if ( isset( $_REQUEST['field_id'] ) && isset( $_REQUEST['opt_name'] ) ) { // WPCS: CSRF ok.
|
||||
|
||||
// Get field id.
|
||||
$this->field_id = $this->sanitize_input( $_REQUEST['field_id'] );
|
||||
$this->opt_name = $this->sanitize_input( $_REQUEST['opt_name'] );
|
||||
|
||||
// Process import file.
|
||||
if ( true === $this->process_file() ) {
|
||||
$this->result = true;
|
||||
$this->data = 'Import successful! Click <strong>OK</strong> to refresh.';
|
||||
|
||||
// process_file failed, return error message.
|
||||
} else {
|
||||
$this->data = $this->err . $abort;
|
||||
}
|
||||
} else {
|
||||
$this->data = 'Invalid field ID.' . $abort;
|
||||
}
|
||||
|
||||
// Cookie read failed.
|
||||
} else {
|
||||
$this->data = $this->err . $abort;
|
||||
}
|
||||
|
||||
// No request types. Somebody tryin' to do something they shouldn't.
|
||||
} else {
|
||||
$this->data = 'Invalid request type.' . $abort;
|
||||
}
|
||||
|
||||
// No request type? Just in case.
|
||||
} else {
|
||||
$this->data = 'No request type specified.' . $abort;
|
||||
}
|
||||
} else {
|
||||
$this->data = 'Security check failed.' . $abort;
|
||||
}
|
||||
// phpcs:enable WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification
|
||||
|
||||
// data array to return.
|
||||
$arr = array(
|
||||
'result' => $this->result,
|
||||
'data' => $this->data,
|
||||
);
|
||||
|
||||
// json encode.
|
||||
$arr = json_encode( $arr ); // phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||
|
||||
echo $arr; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces proprietary WordPress functions sanitize_title() and wp_unslash().
|
||||
*
|
||||
* @param string|array $input Value to sanitize.
|
||||
*/
|
||||
private function sanitize_input( $input ): string {
|
||||
$input = is_array( $input ) ? array_map( 'stripslashes_deep', $input ) : stripslashes( $input );
|
||||
|
||||
return htmlspecialchars( $input, ENT_QUOTES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get wp upload dir from cookie.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function get_upload_dir(): bool {
|
||||
|
||||
// cookie name.
|
||||
$val = 'redux_color_scheme_upload_dir';
|
||||
|
||||
// Is the cookie there?
|
||||
if ( isset( $_COOKIE[ $val ] ) ) {
|
||||
|
||||
// Get value from cookie.
|
||||
$upload_dir = $this->sanitize_input( $_COOKIE[ $val ] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
||||
|
||||
// Is it blank?
|
||||
if ( '' === $upload_dir ) {
|
||||
$this->err = 'Required cookie is empty.';
|
||||
|
||||
// Nope, grab the data.
|
||||
} else {
|
||||
$this->upload_dir = $upload_dir;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// No cookie for you!
|
||||
} else {
|
||||
$this->err = 'Unable to read required cookie.';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process import file
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function process_file(): bool {
|
||||
|
||||
// Undefined | Multiple Files | $_FILES Corruption Attacks
|
||||
// If this request falls under any of them, treat it invalid.
|
||||
if ( ! isset( $_FILES['file']['error'] ) || is_array( $_FILES['file']['error'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
$this->err = 'Invalid upload parameters.';
|
||||
|
||||
return false;
|
||||
} else {
|
||||
|
||||
switch ( $_FILES['file']['error'] ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
|
||||
// All is good.
|
||||
case UPLOAD_ERR_OK:
|
||||
break;
|
||||
|
||||
// Missing file.
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
$this->err = 'No file chosen.';
|
||||
|
||||
return false;
|
||||
|
||||
// File too big.
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
$this->err = 'Exceeds filesize limit.';
|
||||
|
||||
return false;
|
||||
|
||||
// Unknown err.
|
||||
default:
|
||||
$this->err = 'Unknown error.';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// get file name.
|
||||
$filename = htmlspecialchars( trim( $_FILES['file']['name'] ), ENT_QUOTES ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification.Missing
|
||||
|
||||
// get a temp file path.
|
||||
$filepath = htmlspecialchars( trim( $_FILES['file']['tmp_name'] ), ENT_QUOTES ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput, WordPress.Security.NonceVerification.Missing
|
||||
|
||||
// remove illegal chars.
|
||||
$filename = preg_replace( '#[^a-z (),-_]#i', '', $filename );
|
||||
|
||||
// Is accepted type?
|
||||
if ( true === $this->is_proper_mime( $filepath ) ) {
|
||||
|
||||
// Check for JSON extension.
|
||||
if ( $this->is_ext_json( $filename ) ) {
|
||||
|
||||
// Is the actual scheme file?
|
||||
if ( $this->is_scheme_file( $filepath ) ) {
|
||||
|
||||
// Try moving it from temp to wp upload.
|
||||
if ( ! move_uploaded_file( $filepath, $this->upload_dir . '/' . $this->opt_name . '_' . $this->field_id . '.json' ) ) {
|
||||
$this->err = 'Cannot move Redux color scheme file to the upload folder.';
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for a proper MIME type.
|
||||
*
|
||||
* @param string $filepath File path.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_proper_mime( string $filepath ): bool {
|
||||
// Get MIME type.
|
||||
$finfo = new finfo( FILEINFO_MIME_TYPE );
|
||||
|
||||
// Check a type against accepted list.
|
||||
$ext = in_array(
|
||||
$finfo->file( $filepath ),
|
||||
array(
|
||||
'json' => 'application/json',
|
||||
'tmp' => 'application/json',
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
// Bad type.
|
||||
if ( false === $ext ) {
|
||||
$this->err = 'Invalid file format.';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is file a valid scheme file.
|
||||
*
|
||||
* @param string $filepath File path.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_scheme_file( string $filepath ): bool {
|
||||
|
||||
// Check for valid color scheme backup tag.
|
||||
$content = $this->read_tmp( $filepath );
|
||||
|
||||
// If empty, set the error.
|
||||
if ( '' === $content ) {
|
||||
$this->err = 'The selected file is empty.';
|
||||
|
||||
// check for valid scheme entry.
|
||||
} else {
|
||||
|
||||
// scheme tag.
|
||||
$tag = '"color_scheme_name"';
|
||||
|
||||
// Locate its position in the string.
|
||||
$pos = strpos( $content, $tag );
|
||||
|
||||
// Is There? Return true.
|
||||
if ( $pos > 0 ) {
|
||||
return true;
|
||||
|
||||
// Otherwise, set the error.
|
||||
} else {
|
||||
$this->err = 'The selected file is not a valid color scheme file.';
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for valid extension.
|
||||
*
|
||||
* @param string $filename File name.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_ext_json( string $filename ): bool {
|
||||
// Get last period position.
|
||||
$pos = strrpos( $filename, '.' );
|
||||
|
||||
// One found.
|
||||
if ( $pos > 0 ) {
|
||||
|
||||
// Extract file extension.
|
||||
$ext = substr( $filename, $pos + 1 );
|
||||
|
||||
// Is JSON, then continue.
|
||||
if ( 'json' === $ext ) {
|
||||
return true;
|
||||
|
||||
// If not, set err.
|
||||
} else {
|
||||
$this->err = 'The selected file is a ' . strtoupper( $ext ) . ' file, not a JSON file.';
|
||||
}
|
||||
|
||||
// No file ext found, set error.
|
||||
} else {
|
||||
$this->err = 'The selected file has no JSON extension.';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from file.
|
||||
*
|
||||
* @param string $file File path.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function read_tmp( string $file ) {
|
||||
if ( file_exists( $file ) ) {
|
||||
$fp = fopen( $file, 'r' ); // phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||
$data = fread( $fp, filesize( $file ) ); // phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||
|
||||
fclose( $fp ); // phpcs:ignore WordPress.WP.AlternativeFunctions
|
||||
|
||||
return $data;
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new Redux_Color_Scheme_Import();
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Color Scheme Field Class
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Color_Scheme
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Color_Scheme' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_color_scheme class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Color_Scheme extends Redux_Field {
|
||||
|
||||
/**
|
||||
* Set Defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
// Validate.
|
||||
$this->field['options']['picker_font_size'] = $this->field['options']['picker_font_size'] ?? '11px';
|
||||
$this->field['options']['picker_gap'] = $this->field['options']['picker_gap'] ?? '60px';
|
||||
|
||||
$this->field['options']['show_input'] = $this->field['options']['show_input'] ?? true;
|
||||
$this->field['options']['show_initial'] = $this->field['options']['show_initial'] ?? true;
|
||||
$this->field['options']['show_alpha'] = $this->field['options']['show_alpha'] ?? true;
|
||||
$this->field['options']['show_palette'] = $this->field['options']['show_palette'] ?? true;
|
||||
$this->field['options']['show_palette_only'] = $this->field['options']['show_palette_only'] ?? false;
|
||||
$this->field['options']['max_palette_size'] = $this->field['options']['max_palette_size'] ?? 10;
|
||||
$this->field['options']['show_selection_palette'] = $this->field['options']['show_selection_palette'] ?? true;
|
||||
$this->field['options']['allow_empty'] = $this->field['options']['allow_empty'] ?? true;
|
||||
$this->field['options']['clickout_fires_change'] = $this->field['options']['clickout_fires_change'] ?? false;
|
||||
$this->field['options']['choose_text'] = $this->field['options']['choose_text'] ?? 'Choose';
|
||||
$this->field['options']['cancel_text'] = $this->field['options']['cancel_text'] ?? 'Cancel';
|
||||
$this->field['options']['show_buttons'] = $this->field['options']['show_buttons'] ?? true;
|
||||
$this->field['options']['container_class'] = $this->field['options']['container_class'] ?? 'redux-colorpicker-container';
|
||||
$this->field['options']['replacer_class'] = $this->field['options']['replacer_class'] ?? 'redux-colorpicker-replacer';
|
||||
$this->field['options']['use_extended_classes'] = $this->field['options']['use_extended_classes'] ?? false;
|
||||
$this->field['options']['palette'] = $this->field['options']['palette'] ?? null;
|
||||
$this->field['simple'] = $this->field['simple'] ?? false;
|
||||
|
||||
// Convert an empty array to null, if there.
|
||||
$this->field['options']['palette'] = empty( $this->field['options']['palette'] ) ? null : $this->field['options']['palette'];
|
||||
|
||||
$this->field['no_compiler_output'] = $this->field['no_compiler_output'] ?? false;
|
||||
|
||||
$this->field['output_transparent'] = $this->field['output_transparent'] ?? false;
|
||||
$this->field['accordion'] = $this->field['accordion'] ?? true;
|
||||
|
||||
// tooltips.
|
||||
$this->field['tooltip_toggle'] = $this->field['tooltip_toggle'] ?? true;
|
||||
|
||||
$this->field['tooltips']['style']['color'] = $this->field['tooltips']['style']['color'] ?? 'light';
|
||||
$this->field['tooltips']['style']['shadow'] = $this->field['tooltips']['style']['shadow'] ?? true;
|
||||
$this->field['tooltips']['style']['rounded'] = $this->field['tooltips']['style']['rounded'] ?? false;
|
||||
$this->field['tooltips']['style']['style'] = $this->field['tooltips']['style']['style'] ?? '';
|
||||
|
||||
$this->field['tooltips']['position']['my'] = $this->field['tooltips']['position']['my'] ?? 'top center';
|
||||
$this->field['tooltips']['position']['at'] = $this->field['tooltips']['position']['at'] ?? 'bottom center';
|
||||
|
||||
$this->field['tooltips']['effect']['show_effect'] = $this->field['tooltips']['effect']['show_effect'] ?? 'slide';
|
||||
$this->field['tooltips']['effect']['show_duration'] = $this->field['tooltips']['effect']['show_duration'] ?? 500;
|
||||
$this->field['tooltips']['effect']['show_event'] = $this->field['tooltips']['effect']['show_event'] ?? 'mouseover';
|
||||
$this->field['tooltips']['effect']['hide_effect'] = $this->field['tooltips']['effect']['hide_effect'] ?? 'slide';
|
||||
$this->field['tooltips']['effect']['hide_duration'] = $this->field['tooltips']['effect']['hide_duration'] ?? 500;
|
||||
$this->field['tooltips']['effect']['hide_effect'] = $this->field['tooltips']['effect']['hide_effect'] ?? 'mouseleave';
|
||||
}
|
||||
|
||||
/**
|
||||
* Field Render Function.
|
||||
* Takes the vars and outputs the HTML for the field in the settings
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
$field_id = esc_attr( $this->field['id'] );
|
||||
|
||||
// Set field ID, just in case.
|
||||
Redux_Color_Scheme_Functions::$field_id = $field_id;
|
||||
Redux_Color_Scheme_Functions::$field = $this->field;
|
||||
Redux_Color_Scheme_Functions::$parent = $this->parent;
|
||||
|
||||
if ( isset( $this->field['select'] ) ) {
|
||||
if ( is_array( $this->field['select'] ) && ! empty( $this->field['select'] ) ) {
|
||||
Redux_Color_Scheme_Functions::$select = $this->field['select'];
|
||||
}
|
||||
}
|
||||
|
||||
// Nonce.
|
||||
$nonce = wp_create_nonce( "redux_{$this->parent->args['opt_name']}_color_schemes" );
|
||||
|
||||
// Modal message.
|
||||
echo '<div id="redux-' . esc_attr( $field_id ) . '-scheme-message-notice" style="display:none; cursor: default">';
|
||||
echo ' <h2>message</h2>';
|
||||
echo ' <input type="button" id="redux-' . esc_attr( $field_id ) . '-scheme-ok" value="OK" />';
|
||||
echo '</div>';
|
||||
|
||||
// Waiting message.
|
||||
echo '<div id="redux-' . esc_attr( $field_id ) . '-scheme-wait-message" style="display:none;">';
|
||||
echo ' <h1><img alt="Please wait..." src="' . esc_url( $this->url ) . 'img/busy.gif" /> Please wait...</h1>';
|
||||
echo '</div>';
|
||||
|
||||
// Delete dialog.
|
||||
echo '<div id="redux-' . esc_attr( $field_id ) . '-delete-scheme-question" style="display:none; cursor: default">';
|
||||
echo ' <h2>Are you sure you want to delete this scheme?</h2>';
|
||||
echo ' <input type="button" id="redux-' . esc_attr( $field_id ) . '-delete-scheme-yes" value="Yes" />';
|
||||
echo ' <input type="button" id="redux-' . esc_attr( $field_id ) . '-delete-scheme-no" value="No" />';
|
||||
echo '</div>';
|
||||
|
||||
// Select2 params.
|
||||
if ( isset( $this->field['select2'] ) ) { // if there are any, let's pass them to js.
|
||||
$select2_params = wp_json_encode( $this->field['select2'] );
|
||||
$select2_params = htmlspecialchars( $select2_params, ENT_QUOTES );
|
||||
|
||||
echo '<input type="hidden" class="select2_params" value="' . $select2_params . '">'; // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
}
|
||||
|
||||
$tt_in_use = Redux_Color_Scheme_Functions::tooltips_in_use( $this->field );
|
||||
|
||||
$tooltips = '';
|
||||
if ( $tt_in_use ) {
|
||||
$tooltips = rawurlencode( wp_json_encode( $this->field['tooltips'] ) );
|
||||
}
|
||||
|
||||
$tt_toggle_state = Redux_Color_Scheme_Functions::get_tooltip_toggle_state();
|
||||
|
||||
// Color picker container.
|
||||
// phpcs:disable WordPress.Security.EscapeOutput
|
||||
echo '<div
|
||||
class="redux-color-scheme-container ' . esc_attr( $this->field['class'] ) . '"
|
||||
data-id="' . esc_attr( $field_id ) . '"
|
||||
data-opt-name="' . esc_attr( $this->parent->args['opt_name'] ) . '"
|
||||
data-nonce="' . esc_attr( $nonce ) . '"
|
||||
data-picker-gap="' . esc_attr( $this->field['options']['picker_gap'] ) . '"
|
||||
data-picker-font-size="' . esc_attr( $this->field['options']['picker_font_size'] ) . '"
|
||||
data-accordion="' . esc_attr( $this->field['accordion'] ) . '"
|
||||
data-tooltips="' . $tooltips . '"
|
||||
data-show-tooltips="' . esc_attr( $tt_toggle_state ) . '"
|
||||
data-show-input="' . esc_attr( $this->field['options']['show_input'] ) . '"
|
||||
data-show-initial="' . esc_attr( $this->field['options']['show_initial'] ) . '"
|
||||
data-show-alpha="' . esc_attr( $this->field['options']['show_alpha'] ) . '"
|
||||
data-show-palette="' . esc_attr( $this->field['options']['show_palette'] ) . '"
|
||||
data-show-palette-only="' . esc_attr( $this->field['options']['show_palette_only'] ) . '"
|
||||
data-show-selection-palette="' . esc_attr( $this->field['options']['show_selection_palette'] ) . '"
|
||||
data-max-palette-size="' . esc_attr( $this->field['options']['max_palette_size'] ) . '"
|
||||
data-allow-empty="' . esc_attr( $this->field['options']['allow_empty'] ) . '"
|
||||
data-clickout-fires-change="' . esc_attr( $this->field['options']['clickout_fires_change'] ) . '"
|
||||
data-choose-text="' . esc_attr( $this->field['options']['choose_text'] ) . '"
|
||||
data-cancel-text="' . esc_attr( $this->field['options']['cancel_text'] ) . '"
|
||||
data-palette="' . rawurlencode( wp_json_encode( $this->field['options']['palette'] ) ) . '"
|
||||
>';
|
||||
// phpcs:enable WordPress.Security.EscapeOutput
|
||||
|
||||
// Hide scheme save stuff on simple mode.
|
||||
if ( false === $this->field['simple'] ) {
|
||||
echo '<div>';
|
||||
// Select container.
|
||||
echo '<div class="redux-scheme-select-container input_wrapper">';
|
||||
echo ' <span class="redux-label redux-select-scheme-label">Scheme:</span>';
|
||||
|
||||
// Output scheme selector.
|
||||
echo Redux_Color_Scheme_Functions::get_scheme_select_html( '' ); // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
|
||||
echo '</div>';
|
||||
|
||||
// Text input.
|
||||
echo '<div class="redux-scheme-name input_wrapper">';
|
||||
echo ' <span class="redux-label redux-text-scheme-label">Name:</span>';
|
||||
echo ' <input
|
||||
type="text"
|
||||
class="noUpdate redux-scheme-input-' . esc_attr( $field_id ) . '"
|
||||
id="redux-scheme-input"
|
||||
/>';
|
||||
echo '</div>';
|
||||
|
||||
// Action buttons/links.
|
||||
echo ' <div class="redux-action-links">';
|
||||
echo ' <span class="redux-label redux-action-scheme-label">Actions:</span>';
|
||||
|
||||
// Save button.
|
||||
echo ' <a
|
||||
href="javascript:void(0);"
|
||||
id="redux-' . esc_attr( $field_id ) . '-save-scheme-button"
|
||||
class="redux-save-scheme-button button-secondary">' . esc_html__( 'Add', 'redux-framework' ) . '
|
||||
</a>';
|
||||
|
||||
// Delete button.
|
||||
echo ' <a
|
||||
href="javascript:void(0);"
|
||||
id="redux-' . esc_attr( $field_id ) . '-delete-scheme-button"
|
||||
class="redux-delete-scheme-button button-secondary">' . esc_html__( 'Delete', 'redux-framework' ) . '
|
||||
</a>';
|
||||
|
||||
$link = admin_url( 'admin-ajax.php?action=redux_color_schemes&type=export&nonce=' . esc_attr( $nonce ) ) . '&opt_name=' . esc_attr( $this->parent->args['opt_name'] );
|
||||
|
||||
// Export button.
|
||||
echo ' <a
|
||||
href="' . esc_url( $link ) . '"
|
||||
id="redux-' . esc_attr( $field_id ) . '-export-scheme-button"
|
||||
data-opt-name="' . esc_attr( $this->parent->args['opt_name'] ) . '"
|
||||
data-submit="' . esc_url( $this->url ) . '"
|
||||
class="redux-export-scheme-button button-primary">' . esc_html__( 'Export', 'redux-framework' ) . '
|
||||
</a>';
|
||||
|
||||
// Import button.
|
||||
echo ' <a
|
||||
href="javascript:void(0);"
|
||||
id="redux-' . esc_attr( $field_id ) . '-import-scheme-button"
|
||||
data-submit="' . esc_url( $this->url ) . '"
|
||||
data-nonce="' . esc_attr( md5( 'color_scheme_import' ) ) . '"
|
||||
class="noUpdate redux-import-scheme-button button-secondary">' . esc_html__( 'Import', 'redux-framework' ) . '
|
||||
</a>';
|
||||
|
||||
if ( $this->field['tooltip_toggle'] && $tt_in_use ) {
|
||||
$checked = '';
|
||||
if ( $tt_toggle_state ) {
|
||||
$checked = 'checked';
|
||||
}
|
||||
|
||||
echo '<div class="redux-color-scheme-tooltip-checkbox">';
|
||||
echo '<input class="" name="' . esc_attr( $this->parent->args['opt_name'] ) . '[redux-color-scheme-tooltip-toggle]" id="redux-' . esc_attr( $field_id ) . '-tooltip-checkbox" type="checkbox" value="' . esc_attr( $tt_toggle_state ) . '" ' . esc_html( $checked ) . '>Show Tooltips';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
echo ' </div>';
|
||||
echo '</div>';
|
||||
echo '<div>';
|
||||
echo '<hr/>';
|
||||
}
|
||||
|
||||
// Set field class. Gotta do it this way so custom class makes
|
||||
// it through AJAX.
|
||||
Redux_Color_Scheme_Functions::$field_class = 'redux-color-scheme ';
|
||||
|
||||
// Color picker layout.
|
||||
echo Redux_Color_Scheme_Functions::get_current_color_scheme_html(); // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Function.
|
||||
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
|
||||
// Set up min files for dev_mode = false.
|
||||
$min = Redux_Functions::is_min();
|
||||
|
||||
// One-Click Upload.
|
||||
wp_enqueue_script(
|
||||
'redux-ocupload',
|
||||
$this->url . 'vendor/jquery.ocupload' . $min . '.js',
|
||||
array( 'jquery' ),
|
||||
'1.1.2',
|
||||
true
|
||||
);
|
||||
|
||||
// Field dependent JS.
|
||||
wp_enqueue_script(
|
||||
'redux-field-color-scheme',
|
||||
$this->url . 'redux-color-scheme' . $min . '.js',
|
||||
array( 'jquery', 'redux-spectrum-js', 'select2-js', 'redux-block-ui' ),
|
||||
Redux_Extension_Color_Scheme::$version,
|
||||
true
|
||||
);
|
||||
|
||||
// Field CSS.
|
||||
if ( true === $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-color-scheme',
|
||||
$this->url . 'redux-color-scheme.css',
|
||||
array( 'redux-spectrum-css', 'select2-css' ),
|
||||
Redux_Extension_Color_Scheme::$version
|
||||
);
|
||||
}
|
||||
|
||||
// AJAX.
|
||||
wp_localize_script(
|
||||
'redux-field-color-scheme',
|
||||
'redux_ajax_script',
|
||||
array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default data.
|
||||
*
|
||||
* @param string $id Field ID.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function data_from_default( string $id ): array {
|
||||
$x = $this->field;
|
||||
|
||||
$data = array();
|
||||
|
||||
foreach ( $x['default'] as $arr ) {
|
||||
if ( $arr['id'] === $id ) {
|
||||
$data['selector'] = $arr['selector'] ?? '';
|
||||
$data['mode'] = $arr['mode'] ?? '';
|
||||
$data['important'] = $arr['important'] ?? '';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this field requires any scripts or css, define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access private
|
||||
* @return string
|
||||
*/
|
||||
private function get_css(): string {
|
||||
|
||||
// No notices.
|
||||
$css = '';
|
||||
|
||||
// Must be an array.
|
||||
if ( is_array( $this->value ) ) {
|
||||
|
||||
// Enum array to parse values.
|
||||
foreach ( $this->value as $id => $val ) {
|
||||
|
||||
// Default selector data, so we always have current info.
|
||||
$def_data = $this->data_from_default( $id );
|
||||
|
||||
// Sanitize alpha.
|
||||
$alpha = $val['alpha'] ?? 1;
|
||||
|
||||
// Sanitize color.
|
||||
$color = $val['color'] ?? '';
|
||||
|
||||
// Only build rgba output if alpha ia less than 1.
|
||||
if ( $alpha < 1 && '' !== $alpha ) {
|
||||
$color = Redux_Helpers::hex2rgba( $color, $alpha );
|
||||
}
|
||||
|
||||
$important = $def_data['important'] ?? false;
|
||||
if ( true === $important ) {
|
||||
$important = ' !important';
|
||||
} else {
|
||||
$important = '';
|
||||
}
|
||||
|
||||
// Sanitize selector.
|
||||
$selector = $def_data['selector'] ?? '';
|
||||
|
||||
if ( is_array( $selector ) ) {
|
||||
foreach ( $selector as $mode => $element ) {
|
||||
if ( '' !== $element && '' !== $color ) {
|
||||
$css .= $element . '{' . $mode . ': ' . $color . $important . ';}';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Sanitize mode, default to 'color'.
|
||||
$mode = $def_data['mode'] ?? 'color';
|
||||
|
||||
// Only build value if selector is indicated.
|
||||
if ( '' !== $selector && '' !== $color ) {
|
||||
$css .= $selector . '{' . $mode . ': ' . $color . $important . ';} ';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate CSS style.
|
||||
*
|
||||
* @param string $data Field data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function css_style( $data ): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Output Function.
|
||||
* Used to enqueue to the front-end
|
||||
*
|
||||
* @param string|null|array $style Style.
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function output( $style = '' ) {
|
||||
if ( ! empty( $this->value ) ) {
|
||||
if ( ! empty( $this->field['output'] ) && ( true === $this->field['output'] ) ) {
|
||||
$css = $this->get_css();
|
||||
$this->parent->outputCSS .= $css;
|
||||
}
|
||||
|
||||
if ( ! $this->field['no_compiler_output'] ) {
|
||||
if ( ! empty( $this->field['compiler'] ) && ( true === $this->field['compiler'] ) ) {
|
||||
$css = $this->get_css();
|
||||
$this->parent->compilerCSS .= $css;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,991 @@
|
||||
/* global redux, redux_ajax_script,redux_change, reduxColorSchemeAfterUpdateHTML */
|
||||
|
||||
( function ( $ ) {
|
||||
'use strict';
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.color_scheme = redux.field_objects.color_scheme || {};
|
||||
redux.field_objects.color_scheme.nonce = '';
|
||||
redux.field_objects.color_scheme.fieldID = '';
|
||||
redux.field_objects.color_scheme.optName = '';
|
||||
redux.field_objects.color_scheme.el = '';
|
||||
redux.field_objects.color_scheme.showTooltips = '';
|
||||
redux.field_objects.color_scheme.default_params = {};
|
||||
|
||||
redux.field_objects.color_scheme.hexToRGBA = function ( hex, alpha ) {
|
||||
var result;
|
||||
var r;
|
||||
var b;
|
||||
var g;
|
||||
|
||||
if ( null === hex ) {
|
||||
result = '';
|
||||
} else {
|
||||
hex = hex.replace( '#', '' );
|
||||
|
||||
r = parseInt( hex.substring( 0, 2 ), 16 );
|
||||
g = parseInt( hex.substring( 2, 4 ), 16 );
|
||||
b = parseInt( hex.substring( 4, 6 ), 16 );
|
||||
|
||||
result = 'rgba(' + r + ',' + g + ',' + b + ',' + alpha + ')';
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.init = function ( selector ) {
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-color_scheme:visible' );
|
||||
}
|
||||
|
||||
$( selector ).each(
|
||||
function () {
|
||||
var el = $( this );
|
||||
var parent = el;
|
||||
redux.field_objects.color_scheme.el = el;
|
||||
|
||||
if ( ! el.hasClass( 'redux-field-container' ) ) {
|
||||
parent = el.parents( '.redux-field-container:first' );
|
||||
}
|
||||
|
||||
if ( parent.is( ':hidden' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( parent.hasClass( 'redux-field-init' ) ) {
|
||||
parent.removeClass( 'redux-field-init' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
redux.field_objects.color_scheme.modInit( el );
|
||||
redux.field_objects.color_scheme.setAccordions( el );
|
||||
redux.field_objects.color_scheme.import( el );
|
||||
redux.field_objects.color_scheme.delete( el );
|
||||
redux.field_objects.color_scheme.save( el );
|
||||
redux.field_objects.color_scheme.qtip( el );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.qtip = function ( el ) {
|
||||
var tooltips;
|
||||
var shadow;
|
||||
var rounded;
|
||||
var color;
|
||||
var style;
|
||||
var myPos;
|
||||
var atPos;
|
||||
var classes;
|
||||
|
||||
var destroy = false;
|
||||
|
||||
if ( false === redux.field_objects.color_scheme.showTooltips ) {
|
||||
destroy = true;
|
||||
}
|
||||
|
||||
tooltips = el.find( '.redux-color-scheme-container' ).data( 'tooltips' );
|
||||
|
||||
if ( '' === tooltips ) {
|
||||
return;
|
||||
}
|
||||
|
||||
tooltips = decodeURIComponent( tooltips );
|
||||
tooltips = JSON.parse( tooltips );
|
||||
|
||||
shadow = '';
|
||||
if ( true === tooltips.style.shadow ) {
|
||||
shadow = 'qtip-shadow';
|
||||
}
|
||||
|
||||
rounded = '';
|
||||
if ( true === tooltips.style.rounded ) {
|
||||
rounded = 'qtip-rounded';
|
||||
}
|
||||
|
||||
color = '';
|
||||
if ( '' !== tooltips.style.color ) {
|
||||
color = 'qtip-' + tooltips.style.color;
|
||||
}
|
||||
|
||||
style = '';
|
||||
if ( '' !== tooltips.style.style ) {
|
||||
style = 'qtip-' + tooltips.style.style;
|
||||
}
|
||||
|
||||
classes = shadow + ',' + color + ',' + rounded + ',' + style;
|
||||
classes = classes.replace( /,/g, ' ' );
|
||||
|
||||
myPos = tooltips.position.my;
|
||||
atPos = tooltips.position.at;
|
||||
|
||||
myPos = $.redux.verifyPos( myPos.toLowerCase(), true );
|
||||
atPos = $.redux.verifyPos( atPos.toLowerCase(), false );
|
||||
|
||||
$( 'li.redux-cs-qtip' ).each(
|
||||
function () {
|
||||
var content = $( this ).attr( 'qtip-content' );
|
||||
var title = $( this ).attr( 'qtip-title' );
|
||||
|
||||
if ( '' === content && '' === title ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( true === destroy ) {
|
||||
$( this ).qtip( 'destroy', true );
|
||||
} else {
|
||||
$( this ).qtip(
|
||||
{
|
||||
content: {
|
||||
text: content, title: title
|
||||
},
|
||||
show: {
|
||||
effect: function () {
|
||||
if ( 'slide' === tooltips.effect.show_effect ) {
|
||||
$( this ).slideDown( tooltips.effect.show_duration );
|
||||
} else if ( 'fade' === tooltips.effect.show_effect ) {
|
||||
$( this ).fadeIn( tooltips.effect.show_duration );
|
||||
} else {
|
||||
$( this ).show();
|
||||
}
|
||||
}, event: tooltips.effect.show_event
|
||||
},
|
||||
hide: {
|
||||
effect: function () {
|
||||
if ( 'slide' === tooltips.effect.hide_effect ) {
|
||||
$( this ).slideUp( tooltips.effect.hide_duration );
|
||||
} else if ( 'fade' === tooltips.effect.hide_effect ) {
|
||||
$( this ).fadeOut( tooltips.effect.hide_duration );
|
||||
} else {
|
||||
$( this ).hide();
|
||||
}
|
||||
}, event: tooltips.effect.hide_event
|
||||
},
|
||||
style: {
|
||||
classes: classes
|
||||
},
|
||||
position: {
|
||||
my: myPos, at: atPos
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.setAccordions = function ( el ) {
|
||||
var accordionSection;
|
||||
var isOpen;
|
||||
|
||||
var ulContainer = el.find( 'ul.redux-scheme-layout' );
|
||||
|
||||
var openIcon = ulContainer.data( 'open-icon' );
|
||||
var closeIcon = ulContainer.data( 'close-icon' );
|
||||
|
||||
var isAccordion = Boolean( el.find( '.redux-color-scheme-container' ).data( 'accordion' ) );
|
||||
|
||||
if ( true === isAccordion ) {
|
||||
accordionSection = el.find( '.redux-color-scheme-accordion-section' );
|
||||
|
||||
accordionSection.each(
|
||||
function () {
|
||||
isOpen = Boolean( $( this ).data( 'state' ) );
|
||||
|
||||
if ( false === isOpen ) {
|
||||
$( this ).hide();
|
||||
} else {
|
||||
$( this ).prev( '.redux-color-scheme-accordion' ).find( '.el' ).removeClass( openIcon ).addClass( closeIcon );
|
||||
redux.field_objects.color_scheme.initColorPicker( $( this ) );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '.redux-color-scheme-accordion' ).on(
|
||||
'click',
|
||||
function ( e ) {
|
||||
var nextAccordion;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
nextAccordion = $( this ).next( '.redux-color-scheme-accordion-section' );
|
||||
|
||||
if ( nextAccordion.is( ':visible' ) ) {
|
||||
$( this ).find( '.el' ).removeClass( closeIcon ).addClass( openIcon );
|
||||
nextAccordion.slideUp();
|
||||
} else {
|
||||
$( this ).find( '.el' ).removeClass( openIcon ).addClass( closeIcon );
|
||||
|
||||
redux.field_objects.color_scheme.initColorPicker( nextAccordion );
|
||||
|
||||
nextAccordion.slideDown();
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
redux.field_objects.color_scheme.initColorPicker( el );
|
||||
}
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.modInit = function ( el ) {
|
||||
var select2_handle;
|
||||
var select2_params;
|
||||
|
||||
redux.field_objects.color_scheme.nonce = el.find( '.redux-color-scheme-container' ).data( 'nonce' );
|
||||
redux.field_objects.color_scheme.fieldID = el.find( '.redux-color-scheme-container' ).data( 'id' );
|
||||
redux.field_objects.color_scheme.optName = el.find( '.redux-color-scheme-container' ).data( 'opt-name' );
|
||||
redux.field_objects.color_scheme.showTooltips = el.find( '.redux-color-scheme-container' ).data( 'show-tooltips' );
|
||||
|
||||
redux.field_objects.color_scheme.default_params = {
|
||||
triggerChange: true, allowClear: false
|
||||
};
|
||||
|
||||
select2_handle = el.find( '.redux-container-color_scheme' ).find( '.select2_params' );
|
||||
|
||||
if ( select2_handle.length > 0 ) {
|
||||
select2_params = select2_handle.val();
|
||||
select2_params = JSON.parse( select2_params );
|
||||
|
||||
redux.field_objects.color_scheme.default_params = $.extend( {}, redux.field_objects.color_scheme.default_params, select2_params );
|
||||
}
|
||||
|
||||
// Init select2 for scheme select.
|
||||
el.find( '.redux-scheme-select' ).select2( redux.field_objects.color_scheme.default_params );
|
||||
|
||||
// Init select2 for select boxes.
|
||||
el.find( 'select.redux-color-scheme-opt-select' ).select2( redux.field_objects.color_scheme.default_params );
|
||||
|
||||
// Auto select text in input box.
|
||||
el.find( 'input.redux-scheme-input-' + redux.field_objects.color_scheme.fieldID ).on(
|
||||
'click',
|
||||
function ( e ) {
|
||||
this.focus();
|
||||
this.select();
|
||||
e.preventDefault();
|
||||
}
|
||||
);
|
||||
|
||||
// Set scheme input box to selected value.
|
||||
el.find( 'input.redux-scheme-input-' + redux.field_objects.color_scheme.fieldID ).val( el.find( '#redux-scheme-select-' + redux.field_objects.color_scheme.fieldID ).val() );
|
||||
|
||||
// Select change.
|
||||
el.find( '#redux-scheme-select-' + redux.field_objects.color_scheme.fieldID ).on(
|
||||
'change',
|
||||
function () {
|
||||
redux.field_objects.color_scheme.selectChange( el );
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '#redux-' + redux.field_objects.color_scheme.fieldID + '-tooltip-checkbox' ).on(
|
||||
'change',
|
||||
function () {
|
||||
var checked = $( this ).is( ':checked' );
|
||||
$( this ).val( checked );
|
||||
|
||||
redux.field_objects.color_scheme.showTooltips = checked;
|
||||
redux.field_objects.color_scheme.qtip( el );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.import = function ( el ) {
|
||||
var fieldID = redux.field_objects.color_scheme.fieldID;
|
||||
var optName = redux.field_objects.color_scheme.optName;
|
||||
var myUpload = el.find( '#redux-' + fieldID + '-import-scheme-button' );
|
||||
var submit = myUpload.data( 'submit' );
|
||||
var nonce = myUpload.data( 'nonce' );
|
||||
|
||||
myUpload.upload(
|
||||
{
|
||||
name: 'file',
|
||||
method: 'post',
|
||||
action: submit + 'class-redux-color-scheme-import.php',
|
||||
nonce: nonce,
|
||||
enctype: 'multipart/form-data',
|
||||
fileType: '.json',
|
||||
params: {
|
||||
type: 'import',
|
||||
field_id: fieldID,
|
||||
opt_name: optName,
|
||||
nonce: nonce
|
||||
},
|
||||
autoSubmit: true,
|
||||
onSubmit: function () {},
|
||||
onComplete: function ( data ) {
|
||||
|
||||
// Parse JSON.
|
||||
data = JSON.parse( data );
|
||||
|
||||
// Set success/fail message.
|
||||
el.find( '#redux-' + fieldID + '-scheme-message-notice h2' ).html( data.data );
|
||||
|
||||
// Show message.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + fieldID + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px', padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Click OK.
|
||||
$( '#redux-' + fieldID + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
|
||||
// Unload modal.
|
||||
$.unblockUI();
|
||||
|
||||
// Reload window on success.
|
||||
if ( true === data.result ) {
|
||||
window.onbeforeunload = '';
|
||||
location.reload();
|
||||
}
|
||||
|
||||
// Bail out!
|
||||
return false;
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
// Unused.
|
||||
onSelect: function () {
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.delete = function ( el ) {
|
||||
var field_id = redux.field_objects.color_scheme.fieldID;
|
||||
|
||||
el.find( '#redux-' + field_id + '-delete-scheme-button' ).on(
|
||||
'click',
|
||||
function ( event ) {
|
||||
var select_name;
|
||||
|
||||
// Prevent default action.
|
||||
event.preventDefault();
|
||||
|
||||
// Retrieve selected scheme name.
|
||||
select_name = el.find( '#redux-scheme-select-' + field_id ).val();
|
||||
|
||||
// Check for 'default', as we don't want to delete it.
|
||||
if ( 'default' === select_name.toLowerCase() ) {
|
||||
|
||||
// Set on screen message.
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'Cannot delete the <strong>Default</strong> scheme, as it is reserved.' );
|
||||
|
||||
// Show message.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clicked OK.
|
||||
$( '#redux-' + field_id + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load delete question modal.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-delete-scheme-question' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clicked yes.
|
||||
$( '#redux-' + field_id + '-delete-scheme-yes' ).on(
|
||||
'click',
|
||||
function () {
|
||||
var data;
|
||||
var wait_msg;
|
||||
|
||||
// If selected scheme name is valid...
|
||||
if ( select_name ) {
|
||||
|
||||
// Set ajax parameters.
|
||||
data = {
|
||||
action: 'redux_color_schemes',
|
||||
nonce: redux.field_objects.color_scheme.nonce,
|
||||
opt_name: redux.field_objects.color_scheme.optName,
|
||||
type: 'delete',
|
||||
scheme_id: select_name,
|
||||
field_id: field_id
|
||||
};
|
||||
|
||||
// Load Please wait message.
|
||||
wait_msg = el.find( '#redux-' + field_id + '-scheme-wait-message h1' ).html();
|
||||
$.blockUI(
|
||||
{
|
||||
message: '<h1>' + wait_msg + 'deleting scheme.<h1/>',
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Post ajax.
|
||||
$.post(
|
||||
redux_ajax_script.ajaxurl,
|
||||
data,
|
||||
function ( response ) {
|
||||
|
||||
// Successful delete.
|
||||
if ( 'success' === response ) {
|
||||
|
||||
// Remove deleted scheme from selector.
|
||||
el.find( '#redux-scheme-select-' + field_id + ' option[value=\'' + select_name + '\']' ).remove();
|
||||
|
||||
// Clear selector (default).
|
||||
el.find( '.redux-scheme-select' ).select2();
|
||||
el.find( '.redux-scheme-select' ).val( 'Default' ).trigger( 'change' );
|
||||
|
||||
// Clear input box.
|
||||
el.find( 'input.redux-scheme-input-' + field_id ).val( '' );
|
||||
|
||||
// Update modal message text.
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'The <strong>' + select_name + '</strong> scheme has been removed.<br/><br/>The color table has been reset to default values.' );
|
||||
|
||||
// Display the notice.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Click OK, unload msg, bail out.
|
||||
$( '#redux-' + field_id + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
|
||||
// Update the HTML preview.
|
||||
redux.field_objects.color_scheme.updateSchemeHTML( 0, el );
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
||||
// Update modal message with fail response.
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'Delete failed: ' + response );
|
||||
|
||||
// Display the notice.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Click OK, unload msg, bail out.
|
||||
$( '#redux-' + field_id + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clicked no.
|
||||
$( '#redux-' + field_id + '-delete-scheme-no' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.save = function ( el ) {
|
||||
var field_id = redux.field_objects.color_scheme.fieldID;
|
||||
|
||||
el.find( '#redux-' + field_id + '-save-scheme-button' ).on(
|
||||
'click',
|
||||
function ( event ) {
|
||||
var input_text;
|
||||
var scheme_name;
|
||||
var data;
|
||||
var wait_msg;
|
||||
|
||||
var arrData = [];
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// Prevent blank input.
|
||||
input_text = el.find( 'input.redux-scheme-input-' + field_id ).val();
|
||||
|
||||
// Trim.
|
||||
input_text = input_text.replace( /^\s+|\s+$/gm, '' );
|
||||
|
||||
// Allow only alphanumeric, space, dash, and underscore.
|
||||
input_text = input_text.replace( /[^a-z0-9\s\-]/gi, '' );
|
||||
|
||||
// Do nothing if input_text is empty.
|
||||
if ( '' === input_text ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for default scheme.
|
||||
if ( 'default' === input_text.toLowerCase() ) {
|
||||
|
||||
// Update notice message.
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'The name <strong>Default</strong> cannot be used as it is reserved.' );
|
||||
|
||||
// Display msg.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clicked OK. Close message and exit.
|
||||
$( '#redux-' + field_id + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
// Bail out.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enum through them all and collect data.
|
||||
el.find( '.redux-scheme-layout-container' ).each(
|
||||
function () {
|
||||
var obj = $( this ).children( '.redux-color-scheme' );
|
||||
|
||||
var title = obj.data( 'title' );
|
||||
var id = obj.data( 'id' );
|
||||
var color = obj.data( 'hex-color' );
|
||||
var alpha = obj.data( 'alpha' );
|
||||
var rgba = obj.data( 'rgba' );
|
||||
var group = obj.data( 'group' );
|
||||
|
||||
// Push data into the array.
|
||||
arrData.push(
|
||||
{
|
||||
id: id,
|
||||
title: title,
|
||||
color: color,
|
||||
alpha: alpha,
|
||||
rgba: rgba,
|
||||
group: group
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
arrData = JSON.stringify( arrData );
|
||||
arrData = encodeURIComponent( arrData );
|
||||
|
||||
// Get scheme name from text box.
|
||||
scheme_name = el.find( '.redux-scheme-input-' + field_id ).val();
|
||||
|
||||
// If one exists, proceed.
|
||||
if ( scheme_name ) {
|
||||
|
||||
// Set ajax parameters.
|
||||
data = {
|
||||
action: 'redux_color_schemes',
|
||||
nonce: redux.field_objects.color_scheme.nonce,
|
||||
opt_name: redux.field_objects.color_scheme.optName,
|
||||
type: 'save',
|
||||
scheme_name: scheme_name,
|
||||
scheme_data: arrData,
|
||||
field_id: field_id
|
||||
};
|
||||
|
||||
// Get default wait message.
|
||||
wait_msg = el.find( '#redux-' + field_id + '-scheme-wait-message h1' ).html();
|
||||
|
||||
// Load wait message.
|
||||
$.blockUI(
|
||||
{
|
||||
message: '<h1>' + wait_msg + 'saving scheme.</h1>',
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '.redux-scheme-select' ).select2( 'destroy' );
|
||||
|
||||
// Post ajax.
|
||||
$.post(
|
||||
redux_ajax_script.ajaxurl,
|
||||
data,
|
||||
function ( response ) {
|
||||
|
||||
// New selector change hook.
|
||||
el.find( '#redux-scheme-select-' + field_id ).on(
|
||||
'change',
|
||||
function () {
|
||||
redux.field_objects.color_scheme.selectChange( el );
|
||||
}
|
||||
);
|
||||
|
||||
if ( 'fail' === response ) {
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'The scheme <strong>' + scheme_name + '</strong> already exists and cannot be added again.' );
|
||||
} else {
|
||||
|
||||
// Replace selector with updated values.
|
||||
el.find( '#redux-scheme-select-' + field_id ).replaceWith( response );
|
||||
|
||||
// Update notice message.
|
||||
el.find( '#redux-' + field_id + '-scheme-message-notice h2' ).html( 'The scheme <strong>' + scheme_name + '</strong> has been added to your scheme list.' );
|
||||
}
|
||||
|
||||
// Display notice message.
|
||||
$.blockUI(
|
||||
{
|
||||
message: el.find( '#redux-' + field_id + '-scheme-message-notice' ),
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Clicked OK. Unload and exit.
|
||||
$( '#redux-' + field_id + '-scheme-ok' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.unblockUI();
|
||||
return false;
|
||||
}
|
||||
);
|
||||
|
||||
//redux.field_objects.color_scheme.init( el );
|
||||
el.find( '#redux-scheme-select-' + redux.field_objects.color_scheme.fieldID ).on(
|
||||
'change',
|
||||
function () {
|
||||
redux.field_objects.color_scheme.selectChange( el );
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '.redux-scheme-select' ).select2( redux.field_objects.color_scheme.default_params );
|
||||
el.find( 'select.redux-color-scheme-opt-select' ).select2( redux.field_objects.color_scheme.default_params );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.selectChange = function ( el ) {
|
||||
var selected;
|
||||
|
||||
var field_id = redux.field_objects.color_scheme.fieldID;
|
||||
|
||||
// Fade out the colour pickers.
|
||||
el.find( 'ul.redux-scheme-layout' ).fadeOut();
|
||||
|
||||
// Get selected value.
|
||||
selected = el.find( '#redux-scheme-select-' + field_id ).val();
|
||||
|
||||
// Remove default blank value, if any.
|
||||
el.find( '#redux-scheme-select-' + field_id + ' option[value=\'\']' ).remove();
|
||||
|
||||
// Get scheme name from input box.
|
||||
el.find( 'input.redux-scheme-input-' + field_id ).val( selected );
|
||||
|
||||
// Update colour pickers.
|
||||
redux.field_objects.color_scheme.updateSchemeHTML( selected, el );
|
||||
};
|
||||
|
||||
redux.field_objects.color_scheme.updateSchemeHTML = function ( selected, el ) {
|
||||
var field_class;
|
||||
var data;
|
||||
|
||||
var field_id = redux.field_objects.color_scheme.fieldID;
|
||||
|
||||
// Get default wait msg.
|
||||
var wait_msg = el.find( '#redux-' + field_id + '-scheme-wait-message h1' ).html();
|
||||
|
||||
// Display appended msg.
|
||||
$.blockUI(
|
||||
{
|
||||
message: '<h1>' + wait_msg + 'updating scheme.</h1>',
|
||||
theme: false,
|
||||
css: {
|
||||
width: '500px',
|
||||
padding: '5px'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Get field class. Needed for custom classes from field array.
|
||||
field_class = el.find( '.redux-color-scheme' ).attr( 'class' );
|
||||
|
||||
// Set ajax parameters.
|
||||
data = {
|
||||
action: 'redux_color_schemes',
|
||||
nonce: redux.field_objects.color_scheme.nonce,
|
||||
opt_name: redux.field_objects.color_scheme.optName,
|
||||
type: 'update',
|
||||
scheme_id: selected,
|
||||
field_id: field_id,
|
||||
field_class: field_class
|
||||
};
|
||||
|
||||
// Post ajax.
|
||||
$.post(
|
||||
redux_ajax_script.ajaxurl,
|
||||
data,
|
||||
function ( response ) {
|
||||
|
||||
// Replace colour picker layout.
|
||||
el.find( 'ul.redux-scheme-layout' ).replaceWith( response );
|
||||
|
||||
// Re-init colour pickers.
|
||||
redux.field_objects.color_scheme.setAccordions( el );
|
||||
|
||||
// Fade colour pickers back in.
|
||||
el.find( 'ul.redux-scheme-layout' ).fadeIn();
|
||||
|
||||
// Remove waiting msg.
|
||||
$.unblockUI();
|
||||
|
||||
// Set flags for compiler.
|
||||
redux_change( el.find( '.redux-color-scheme-container' ) );
|
||||
|
||||
el.find( 'select.redux-color-scheme-opt-select' ).select2( redux.field_objects.color_scheme.default_params );
|
||||
|
||||
if ( 'function' === typeof reduxColorSchemeAfterUpdateHTML ) {
|
||||
reduxColorSchemeAfterUpdateHTML( $( this ), el );
|
||||
}
|
||||
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
// Initialize colour picker.
|
||||
redux.field_objects.color_scheme.initColorPicker = function ( el ) {
|
||||
|
||||
// Get field ID.
|
||||
var field_id = redux.field_objects.color_scheme.fieldID;
|
||||
|
||||
// Get the color scheme container.
|
||||
var colorpickerInput = el.find( '.redux-color-scheme' );
|
||||
|
||||
// Get alpha value and sanitize it.
|
||||
var currentAlpha = colorpickerInput.data( 'current-alpha' );
|
||||
|
||||
// Get colour value and sanitize it.
|
||||
var currentColor = colorpickerInput.data( 'current-color' );
|
||||
|
||||
var outputTransparent = colorpickerInput.data( 'output-transparent' );
|
||||
|
||||
// Color picker arguments.
|
||||
var container = redux.field_objects.color_scheme.el.find( '.redux-color-scheme-container' );
|
||||
|
||||
// Get, decode and parse palette.
|
||||
var palette = container.data( 'palette' );
|
||||
|
||||
var pickerGap = container.data( 'picker-gap' );
|
||||
|
||||
var pickerFontSize = container.data( 'picker-font-size' );
|
||||
|
||||
// Get and sanitize show input argument.
|
||||
var showInput = container.data( 'show-input' );
|
||||
|
||||
// Get and sanitize show initial argument.
|
||||
var showInitial = container.data( 'show-initial' );
|
||||
|
||||
// Get and sanitize show alpha argument.
|
||||
var showAlpha = container.data( 'show-alpha' );
|
||||
|
||||
// Get and sanitize allow empty argument.
|
||||
var allowEmpty = container.data( 'allow-empty' );
|
||||
|
||||
// Get and sanitize show palette argument.
|
||||
var showPalette = container.data( 'show-palette' );
|
||||
|
||||
// Get and sanitize show palette only argument.
|
||||
var showPaletteOnly = container.data( 'show-palette-only' );
|
||||
|
||||
// Get and sanitize show selection palette argument.
|
||||
var showSelectionPalette = container.data( 'show-selection-palette' );
|
||||
|
||||
// Get max palette size.
|
||||
var maxPaletteSize = Number( container.data( 'max-palette-size' ) );
|
||||
|
||||
// Get and sanitize clickout fires change argument.
|
||||
var clickoutFiresChange = container.data( 'clickout-fires-change' );
|
||||
|
||||
// Get choose button text.
|
||||
var chooseText = String( container.data( 'choose-text' ) );
|
||||
|
||||
// Get cancel button text.
|
||||
var cancelText = String( container.data( 'cancel-text' ) );
|
||||
|
||||
// Get and sanitize show buttons argument.
|
||||
var showButtons = container.data( 'show-buttons' );
|
||||
|
||||
// Get container class.
|
||||
var containerClass = String( container.data( 'container-class' ) );
|
||||
|
||||
// Get replacer class.
|
||||
var replacerClass = String( container.data( 'replacer-class' ) );
|
||||
|
||||
// Picker gap css.
|
||||
el.find( 'li.redux-scheme-layout' ).css( 'width', pickerGap );
|
||||
|
||||
// Picker font size.
|
||||
el.find( '.redux-layout-label' ).attr( 'style', 'font-size: ' + pickerFontSize + '!important' );
|
||||
|
||||
currentAlpha = Number( ( null === currentAlpha || undefined === currentAlpha ) ? 1 : currentAlpha );
|
||||
currentColor = ( '' === currentColor || 'transparent' === currentColor ) ? '' : currentColor;
|
||||
outputTransparent = Boolean( ( '' === outputTransparent ) ? false : outputTransparent );
|
||||
|
||||
palette = decodeURIComponent( palette );
|
||||
palette = JSON.parse( palette );
|
||||
|
||||
// Default palette.
|
||||
if ( null === palette ) {
|
||||
palette = [
|
||||
['#000000', '#434343', '#666666', '#999999', '#b7b7b7', '#cccccc', '#d9d9d9', '#efefef', '#f3f3f3', '#ffffff'],
|
||||
['#980000', '#ff0000', '#ff9900', '#ffff00', '#00ff00', '#00ffff', '#4a86e8', '#0000ff', '#9900ff', '#ff00ff'],
|
||||
['#e6b8af', '#f4cccc', '#fce5cd', '#fff2cc', '#d9ead3', '#d9ead3', '#c9daf8', '#cfe2f3', '#d9d2e9', '#ead1dc'],
|
||||
['#dd7e6b', '#ea9999', '#f9cb9c', '#ffe599', '#b6d7a8', '#a2c4c9', '#a4c2f4', '#9fc5e8', '#b4a7d6', '#d5a6bd'],
|
||||
['#cc4125', '#e06666', '#f6b26b', '#ffd966', '#93c47d', '#76a5af', '#6d9eeb', '#6fa8dc', '#8e7cc3', '#c27ba0'],
|
||||
['#a61c00', '#cc0000', '#e69138', '#f1c232', '#6aa84f', '#45818e', '#3c78d8', '#3d85c6', '#674ea7', '#a64d79'],
|
||||
['#85200c', '#990000', '#b45f06', '#bf9000', '#38761d', '#134f5c', '#1155cc', '#0b5394', '#351c75', '#741b47'],
|
||||
['#5b0f00', '#660000', '#783f04', '#7f6000', '#274e13', '#0c343d', '#1c4587', '#073763', '#20124d', '#4c1130']
|
||||
];
|
||||
}
|
||||
|
||||
pickerGap = String( ( '' === pickerGap ) ? '60px' : pickerGap );
|
||||
pickerFontSize = String( ( '' === pickerFontSize ) ? '11px' : pickerFontSize );
|
||||
showInput = Boolean( ( '' === showInput ) ? false : showInput );
|
||||
showInitial = Boolean( ( '' === showInitial ) ? false : showInitial );
|
||||
showAlpha = Boolean( ( '' === showAlpha ) ? false : showAlpha );
|
||||
allowEmpty = Boolean( ( '' === allowEmpty ) ? false : allowEmpty );
|
||||
showPalette = Boolean( ( '' === showPalette ) ? false : showPalette );
|
||||
showPaletteOnly = Boolean( ( '' === showPaletteOnly ) ? false : showPaletteOnly );
|
||||
showSelectionPalette = Boolean( ( '' === showSelectionPalette ) ? false : showSelectionPalette );
|
||||
clickoutFiresChange = Boolean( ( '' === clickoutFiresChange ) ? false : clickoutFiresChange );
|
||||
showButtons = Boolean( ( '' === showButtons ) ? false : showButtons );
|
||||
|
||||
// Color picker options.
|
||||
colorpickerInput.spectrum(
|
||||
{
|
||||
color: currentColor,
|
||||
showAlpha: showAlpha,
|
||||
showInput: showInput,
|
||||
allowEmpty: allowEmpty,
|
||||
className: 'redux-full-spectrum',
|
||||
showInitial: showInitial,
|
||||
showPalette: showPalette,
|
||||
showSelectionPalette: showSelectionPalette,
|
||||
maxPaletteSize: maxPaletteSize,
|
||||
showPaletteOnly: showPaletteOnly,
|
||||
clickoutFiresChange: clickoutFiresChange,
|
||||
chooseText: chooseText,
|
||||
cancelText: cancelText,
|
||||
showButtons: showButtons,
|
||||
containerClassName: containerClass,
|
||||
replacerClassName: replacerClass,
|
||||
preferredFormat: 'hex6',
|
||||
localStorageKey: 'redux.spectrum.' + field_id,
|
||||
palette: palette,
|
||||
|
||||
// On change.
|
||||
change: function ( color ) {
|
||||
var colorVal;
|
||||
var alphaVal;
|
||||
var rgbaVal;
|
||||
var blockID;
|
||||
var dataBlock;
|
||||
var rawData;
|
||||
|
||||
if ( null === color ) {
|
||||
if ( true === outputTransparent ) {
|
||||
colorVal = 'transparent';
|
||||
} else {
|
||||
colorVal = null;
|
||||
}
|
||||
alphaVal = null;
|
||||
} else {
|
||||
colorVal = color.toHexString();
|
||||
alphaVal = color.getAlpha();
|
||||
}
|
||||
|
||||
if ( 'transparent' !== colorVal ) {
|
||||
rgbaVal = redux.field_objects.color_scheme.hexToRGBA( colorVal, alphaVal );
|
||||
} else {
|
||||
rgbaVal = 'transparent';
|
||||
}
|
||||
|
||||
blockID = $( this ).data( 'block-id' );
|
||||
dataBlock = el.find( 'input#' + blockID + '-data' );
|
||||
rawData = dataBlock.val();
|
||||
|
||||
rawData = decodeURIComponent( rawData );
|
||||
rawData = JSON.parse( rawData );
|
||||
|
||||
rawData.color = colorVal;
|
||||
rawData.alpha = alphaVal;
|
||||
rawData.rgba = rgbaVal;
|
||||
|
||||
rawData = JSON.stringify( rawData );
|
||||
rawData = encodeURIComponent( rawData );
|
||||
|
||||
dataBlock.val( rawData );
|
||||
|
||||
redux_change( redux.field_objects.color_scheme.el.find( '.redux-color-scheme-container' ) );
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
} )( jQuery );
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,311 @@
|
||||
.sp-container {
|
||||
color: #555;
|
||||
border-color: #cccccc;
|
||||
background: #f7f7f7;
|
||||
-webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
|
||||
box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.sp-replacer {
|
||||
color: #555;
|
||||
border-color: #cccccc;
|
||||
background: #f7f7f7;
|
||||
-webkit-box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
|
||||
box-shadow: inset 0 1px 0 #fff, 0 1px 0 rgba( 0, 0, 0, 0.08 );
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.sp-replacer:focus,
|
||||
.sp-replacer:hover,
|
||||
.sp-replacer.focus,
|
||||
.sp-replacer.hover {
|
||||
background: #fafafa;
|
||||
border-color: #999;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.sp-replacer:focus,
|
||||
.sp-replacer.focus {
|
||||
-webkit-box-shadow:
|
||||
0 0 0 1px #5b9dd9,
|
||||
0 0 2px 1px rgba(30, 140, 190, .8);
|
||||
box-shadow:
|
||||
0 0 0 1px #5b9dd9,
|
||||
0 0 2px 1px rgba(30, 140, 190, .8);
|
||||
|
||||
}
|
||||
|
||||
.sp-replacer.active:focus {
|
||||
-webkit-box-shadow:
|
||||
inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ),
|
||||
0 0 0 1px #5b9dd9,
|
||||
0 0 2px 1px rgba(30, 140, 190, .8);
|
||||
box-shadow:
|
||||
inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 ),
|
||||
0 0 0 1px #5b9dd9,
|
||||
0 0 2px 1px rgba(30, 140, 190, .8);
|
||||
}
|
||||
|
||||
.sp-replacer.active,
|
||||
.sp-replacer.active:hover,
|
||||
.sp-replacer:active{
|
||||
background: #eee;
|
||||
border-color: #999;
|
||||
color: #333;
|
||||
-webkit-box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
|
||||
box-shadow: inset 0 2px 5px -3px rgba( 0, 0, 0, 0.5 );
|
||||
}
|
||||
|
||||
.redux-container-spectrum {
|
||||
|
||||
}
|
||||
|
||||
.redux-container-color_scheme {
|
||||
|
||||
.redux-color-scheme-select-close-hr {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.redux-color-scheme-opt-select {
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.redux-color-scheme-blank-hr {
|
||||
clear: both;
|
||||
border-top: 0 solid;
|
||||
border-bottom: 0 solid;
|
||||
}
|
||||
|
||||
ul.redux-scheme-layout {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
|
||||
.redux-color-scheme-group {
|
||||
&.accordion {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.redux-color-scheme-accordion {
|
||||
border: 1px solid #dfdfdf;
|
||||
background: #FAFAFA;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
border-color: #999;
|
||||
}
|
||||
|
||||
span {
|
||||
&.dashicons {
|
||||
float: right;
|
||||
margin-right: 3px;
|
||||
|
||||
&.not-titled.subtitled {
|
||||
margin-top: -2px;
|
||||
}
|
||||
|
||||
&.titled {
|
||||
margin-top: -25px;
|
||||
}
|
||||
|
||||
&.titled.subtitled {
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-label {
|
||||
cursor: pointer;
|
||||
|
||||
&.redux-layout-group-label {
|
||||
margin-left: 8px!important;
|
||||
margin-top: -10px!important;
|
||||
padding-bottom: 5px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
&.redux-layout-group-desc-label {
|
||||
margin-left: 8px!important;
|
||||
margin-top: -3px!important;
|
||||
color: #444;
|
||||
|
||||
&.not-titled {
|
||||
padding-top: 10px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
&.titled {
|
||||
margin-top: -7px!important;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-color-scheme-accordion-section {
|
||||
display: block;
|
||||
border: 1px solid rgb(223, 223, 223);
|
||||
border-top: 0;
|
||||
background: #fff;
|
||||
|
||||
.redux-color-scheme-group-desc {
|
||||
font-size: 12px !important;
|
||||
text-align: left;
|
||||
cursor: default;
|
||||
margin-left: 13px;
|
||||
margin-right: 13px;
|
||||
margin-bottom: 2px;
|
||||
padding-top: 10px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li.redux-scheme-layout {
|
||||
width: 60px;
|
||||
line-height: 11px;
|
||||
text-align: center;
|
||||
float: left;
|
||||
margin: 8px;
|
||||
height: 95px;
|
||||
|
||||
.redux-full-spectrum.sp-palette {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.redux-layout-label {
|
||||
font-size: 11px;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-color-scheme-container{
|
||||
hr {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.input_wrapper {
|
||||
display: block;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
width: 44%;
|
||||
max-width: 44%;
|
||||
min-width: 70px;
|
||||
float: left;
|
||||
clear: none;
|
||||
height: 57px;
|
||||
box-sizing: border-box;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.redux-label {
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 12px !important;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
margin: 4px 0 2px 0 !important;
|
||||
cursor: default;
|
||||
|
||||
&.redux-layout-group-label {
|
||||
clear: both;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.redux-layout-group-desc-label {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
&.redux-color-scheme-opt-select-title {
|
||||
font-weight: 600;
|
||||
margin-left: 15px!important;
|
||||
}
|
||||
|
||||
&.redux-color-scheme-opt-select-desc {
|
||||
font-style: italic;
|
||||
margin-left: 15px!important;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.redux-scheme-name{
|
||||
.redux-text-scheme-label {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
input#redux-scheme-input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-action-links {
|
||||
clear: left;
|
||||
height: 60px;
|
||||
|
||||
.redux-delete-scheme-button,
|
||||
.redux-import-scheme-button,
|
||||
.redux-export-scheme-button,
|
||||
.redux-save-scheme-button {
|
||||
margin-top: 4px !important;
|
||||
width: 64px !important;
|
||||
text-align: center !important;
|
||||
margin-right: 3px !important;
|
||||
}
|
||||
|
||||
span.redux-action-scheme-label {
|
||||
font-size: 13px;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.hidden-input-div {
|
||||
height: 40px !important;
|
||||
left: 213px !important;
|
||||
top: -34px !important;
|
||||
cursor: pointer !important;
|
||||
}
|
||||
|
||||
.redux-color-scheme-tooltip-checkbox {
|
||||
position: relative;
|
||||
width: 204px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 33px !important;
|
||||
left: 293px !important;
|
||||
top: -55px !important;
|
||||
cursor: pointer !important;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-scheme-select-container {
|
||||
.redux-select-scheme-label {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.redux-scheme-select {
|
||||
width: 95%;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-scheme-layout-container {
|
||||
width: 60px;
|
||||
height: 36px;
|
||||
margin: 0 auto 10px auto;
|
||||
padding-top: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 782px) {
|
||||
.redux-color-scheme-container{
|
||||
.redux-scheme-name {
|
||||
clear: left !important;
|
||||
}
|
||||
|
||||
.redux-action-links {
|
||||
padding-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,909 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Custom Font Extension Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com> & Dovy Paukstys <dovy@reduxframework.com>
|
||||
* @class Redux_Extension_Custom_Fonts
|
||||
* @version 4.4.2
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Extension_Custom_Fonts' ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Extension_Custom_Fonts
|
||||
*/
|
||||
class Redux_Extension_Custom_Fonts extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.4.2';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $ext_name = 'Custom Fonts';
|
||||
|
||||
/**
|
||||
* Custom fonts array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $custom_fonts = array();
|
||||
|
||||
/**
|
||||
* WordPress upload directory.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $upload_dir = '';
|
||||
|
||||
/**
|
||||
* WordPress upload URI.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $upload_url = '';
|
||||
|
||||
/**
|
||||
* Extension instance.
|
||||
*
|
||||
* @var null
|
||||
*/
|
||||
public static $instance = null;
|
||||
|
||||
/**
|
||||
* Is font conversation service available?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $can_convert;
|
||||
|
||||
/**
|
||||
* Class Constructor. Defines the args for the extensions class
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
self::$instance = parent::get_instance();
|
||||
|
||||
$this->add_field( 'custom_fonts' );
|
||||
|
||||
$this->upload_dir = Redux_Core::$upload_dir . 'custom-fonts/';
|
||||
$this->upload_url = Redux_Core::$upload_url . 'custom-fonts/';
|
||||
|
||||
if ( ! is_dir( $this->upload_dir ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir );
|
||||
}
|
||||
|
||||
if ( ! is_dir( $this->upload_dir . '/custom' ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir . '/custom' );
|
||||
}
|
||||
|
||||
$this->get_fonts();
|
||||
|
||||
if ( file_exists( $this->upload_dir . 'fonts.css' ) ) {
|
||||
if ( filemtime( $this->upload_dir . 'custom' ) > ( filemtime( $this->upload_dir . 'fonts.css' ) + 10 ) ) {
|
||||
$this->generate_css();
|
||||
}
|
||||
} else {
|
||||
$this->generate_css();
|
||||
}
|
||||
|
||||
add_action( 'wp_ajax_redux_custom_fonts', array( $this, 'ajax' ) );
|
||||
add_action( 'wp_ajax_redux_custom_font_timer', array( $this, 'timer' ) );
|
||||
|
||||
add_filter( "redux/{$this->parent->args['opt_name']}/field/typography/custom_fonts", array( $this, 'add_custom_fonts' ) );
|
||||
|
||||
// phpcs:disable
|
||||
// $this->is_field = Redux_Helpers::is_field_in_use( $parent, 'custom_fonts' );
|
||||
|
||||
// if ( ! $this->is_field ) {
|
||||
// $this->add_section();
|
||||
// }
|
||||
|
||||
add_filter( "redux/options/{$this->parent->args['opt_name']}/section/redux_dynamic_font_control", array( $this, 'remove_dynamic_section' ) ); // phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
add_filter( 'upload_mimes', array( $this, 'custom_upload_mimes' ) );
|
||||
add_action( 'wp_head', array( $this, 'enqueue_output' ), 150 );
|
||||
add_filter( 'tiny_mce_before_init', array( $this, 'extend_tinymce_dropdown' ) );
|
||||
|
||||
$this->can_convert = true; // has_filter( 'redux/' . $this->parent->args['opt_name'] . '/extensions/custom_fonts/api_url' );
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
public function timer() {
|
||||
$name = get_option( 'redux_custom_font_current' );
|
||||
|
||||
if ( ! empty( $name ) ) {
|
||||
echo esc_html( $name );
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the dynamically added section if the field was used elsewhere
|
||||
*
|
||||
* @param array $section Section array.
|
||||
*
|
||||
* @return array
|
||||
* @since Redux_Framework 3.1.1
|
||||
*/
|
||||
public function remove_dynamic_section( array $section ): array {
|
||||
if ( isset( $this->parent->field_types['custom_fonts'] ) ) {
|
||||
$section = array();
|
||||
}
|
||||
|
||||
return $section;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds FontMeister fonts to the TinyMCE drop-down.
|
||||
* Typekit's fonts don't render properly in the drop-down and in the editor,
|
||||
* because Typekit needs JS and TinyMCE doesn't support that.
|
||||
*
|
||||
* @param array $opt Option array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function extend_tinymce_dropdown( array $opt ): array {
|
||||
if ( ! is_admin() ) {
|
||||
return $opt;
|
||||
}
|
||||
|
||||
if ( file_exists( $this->upload_dir . 'fonts.css' ) ) {
|
||||
$theme_advanced_fonts = $opt['font_formats'] ?? 'Andale Mono=andale mono,times;Arial=arial,helvetica,sans-serif;Arial Black=arial black,avant garde;Book Antiqua=book antiqua,palatino;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier;Georgia=georgia,palatino;Helvetica=helvetica;Impact=impact,chicago;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco;Times New Roman=times new roman,times;Trebuchet MS=trebuchet ms,geneva;Verdana=verdana,geneva;Webdings=webdings;Wingdings=wingdings,zapf dingbats';
|
||||
$custom_fonts = '';
|
||||
|
||||
$stylesheet = $this->upload_url . 'fonts.css';
|
||||
|
||||
if ( empty( $opt['content_css'] ) ) {
|
||||
$opt['content_css'] = $stylesheet;
|
||||
} else {
|
||||
$opt['content_css'] = $opt['content_css'] . ',' . $stylesheet;
|
||||
}
|
||||
|
||||
foreach ( $this->custom_fonts as $arr ) {
|
||||
foreach ( $arr as $font => $pieces ) {
|
||||
$custom_fonts .= ';' . $font . '=' . $font;
|
||||
}
|
||||
}
|
||||
|
||||
$opt['font_formats'] = $theme_advanced_fonts . $custom_fonts;
|
||||
}
|
||||
|
||||
return $opt;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function to enqueue the custom fonts css
|
||||
*/
|
||||
public function enqueue_output() {
|
||||
if ( file_exists( $this->upload_dir . 'fonts.css' ) ) {
|
||||
wp_enqueue_style(
|
||||
'redux-custom-fonts',
|
||||
$this->upload_url . 'fonts.css',
|
||||
array(),
|
||||
time()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the appropriate mime types to WordPress
|
||||
*
|
||||
* @param array $existing_mimes Mine array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function custom_upload_mimes( array $existing_mimes = array() ): array {
|
||||
$existing_mimes['ttf'] = 'font/ttf';
|
||||
$existing_mimes['otf'] = 'font/otf';
|
||||
$existing_mimes['eot'] = 'application/vnd.ms-fontobject';
|
||||
$existing_mimes['woff'] = 'application/font-woff';
|
||||
$existing_mimes['woff2'] = 'application/font-woff2';
|
||||
$existing_mimes['svg'] = 'image/svg+xml';
|
||||
$existing_mimes['zip'] = 'application/zip';
|
||||
|
||||
return $existing_mimes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the fonts in the custom_fonts directory
|
||||
*/
|
||||
public function get_fonts() {
|
||||
if ( empty( $this->custom_fonts ) ) {
|
||||
$params = array(
|
||||
'include_hidden' => false,
|
||||
'recursive' => true,
|
||||
);
|
||||
|
||||
$fonts = $this->parent->filesystem->execute( 'dirlist', $this->upload_dir, $params );
|
||||
|
||||
if ( ! empty( $fonts ) ) {
|
||||
foreach ( $fonts as $section ) {
|
||||
if ( 'd' === $section['type'] && ! empty( $section['name'] ) ) {
|
||||
if ( 'custom' === $section['name'] ) {
|
||||
$section['name'] = esc_html__( 'Custom Fonts', 'redux-framework' );
|
||||
}
|
||||
|
||||
if ( empty( $section['files'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->custom_fonts[ $section['name'] ] = $this->custom_fonts[ $section['name'] ] ?? array();
|
||||
|
||||
foreach ( $section['files'] as $font ) {
|
||||
if ( ! empty( $font['name'] ) ) {
|
||||
if ( empty( $font['files'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$kinds = array();
|
||||
|
||||
foreach ( $font['files'] as $f ) {
|
||||
$valid = $this->check_font_name( $f );
|
||||
if ( $valid ) {
|
||||
$kinds[] = $valid;
|
||||
}
|
||||
}
|
||||
|
||||
$this->custom_fonts[ $section['name'] ][ $font['name'] ] = $kinds;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom fonts.
|
||||
*
|
||||
* @param mixed $custom_fonts Custom fonts.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function add_custom_fonts( $custom_fonts ): array {
|
||||
if ( empty( $custom_fonts ) ) {
|
||||
$custom_fonts = array();
|
||||
}
|
||||
|
||||
return wp_parse_args( $custom_fonts, $this->custom_fonts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajax used within the panel to add and process the fonts
|
||||
*/
|
||||
public function ajax() {
|
||||
if ( ! isset( $_POST['nonce'] ) || ! wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux_custom_fonts' ) ) {
|
||||
die( 0 );
|
||||
}
|
||||
|
||||
if ( isset( $_POST['type'] ) && 'delete' === $_POST['type'] ) {
|
||||
if ( isset( $_POST['section'] ) ) {
|
||||
if ( esc_html__( 'Custom Fonts', 'redux-framework' ) === $_POST['section'] ) {
|
||||
$_POST['section'] = 'custom';
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
if ( isset( $_POST['section'] ) || isset( $_POST['name'] ) ) {
|
||||
$this->parent->filesystem->execute( 'rmdir', $this->upload_dir . sanitize_title( wp_unslash( $_POST['section'] ) ) . '/' . sanitize_title( wp_unslash( $_POST['name'] ) ) . '/', array( 'recursive' => true ) );
|
||||
|
||||
$result = array( 'type' => 'success' );
|
||||
|
||||
echo wp_json_encode( $result );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'Unable to delete font file(s).', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['title'] ) ) {
|
||||
$_POST['title'] = '';
|
||||
}
|
||||
|
||||
if ( ! isset( $_POST['filename'] ) ) {
|
||||
$_POST['filename'] = '';
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['attachment_id'] ) ) {
|
||||
if ( isset( $_POST['title'] ) || isset( $_POST['mime'] ) ) {
|
||||
$msg = $this->process_web_font( sanitize_key( wp_unslash( $_POST['attachment_id'] ) ), sanitize_text_field( wp_unslash( $_POST['title'] ) ), sanitize_text_field( wp_unslash( $_POST['filename'] ) ), sanitize_text_field( wp_unslash( $_POST['mime'] ) ) );
|
||||
|
||||
if ( empty( $msg ) ) {
|
||||
$msg = '';
|
||||
}
|
||||
|
||||
$result = array(
|
||||
'type' => 'success',
|
||||
'msg' => $msg,
|
||||
);
|
||||
|
||||
echo wp_json_encode( $result );
|
||||
}
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get only valid files. Ensure everything is proper for processing.
|
||||
*
|
||||
* @param string $path Path.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_valid_files( string $path ): array {
|
||||
$output = array();
|
||||
$path = trailingslashit( $path );
|
||||
|
||||
$params = array(
|
||||
'include_hidden' => false,
|
||||
'recursive' => true,
|
||||
);
|
||||
|
||||
$files = $this->parent->filesystem->execute( 'dirlist', $path, $params );
|
||||
|
||||
foreach ( $files as $file ) {
|
||||
if ( 'd' === $file['type'] ) {
|
||||
$output = array_merge( $output, $this->get_valid_files( $path . $file['name'] ) );
|
||||
} elseif ( 'f' === $file['type'] ) {
|
||||
$valid = $this->check_font_name( $file );
|
||||
if ( $valid ) {
|
||||
$output[ $valid ] = trailingslashit( $path ) . $file['name'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a valid web font and process the missing pieces.
|
||||
*
|
||||
* @param string $attachment_id ID.
|
||||
* @param string $name Name.
|
||||
* @param string $true_filename Filename.
|
||||
* @param string $mime_type Mine type.
|
||||
*/
|
||||
public function process_web_font( string $attachment_id, string $name, string $true_filename, string $mime_type ) {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
if ( ! isset( $_POST['conversion'] ) ) {
|
||||
$_POST['conversion'] = 'false';
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$conversion = sanitize_text_field( wp_unslash( $_POST['conversion'] ) );
|
||||
|
||||
$missing = array();
|
||||
|
||||
$complete = array(
|
||||
'ttf',
|
||||
'woff',
|
||||
'woff2',
|
||||
'eot',
|
||||
'svg',
|
||||
'otf',
|
||||
);
|
||||
|
||||
$subfolder = 'custom/';
|
||||
$subtype = explode( '/', $mime_type );
|
||||
$subtype = trim( max( $subtype ) );
|
||||
|
||||
if ( ! is_dir( $this->upload_dir ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir );
|
||||
}
|
||||
|
||||
if ( ! is_dir( $this->upload_dir . $subfolder ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir . $subfolder );
|
||||
}
|
||||
|
||||
$temp = $this->upload_dir . 'temp';
|
||||
$path = get_attached_file( $attachment_id );
|
||||
|
||||
if ( empty( $path ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'Attachment does not exist.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
$filename = explode( '/', $path );
|
||||
|
||||
$filename = $filename[ ( count( $filename ) - 1 ) ];
|
||||
|
||||
$fontname = ucfirst(
|
||||
str_replace(
|
||||
array(
|
||||
'.zip',
|
||||
'.ttf',
|
||||
'.woff',
|
||||
'.woff2',
|
||||
'.eot',
|
||||
'.svg',
|
||||
'.otf',
|
||||
),
|
||||
'',
|
||||
strtolower( $filename )
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $name ) ) {
|
||||
$name = $fontname;
|
||||
}
|
||||
|
||||
$ret = array();
|
||||
|
||||
if ( ! is_dir( $temp ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $temp );
|
||||
}
|
||||
|
||||
if ( 'zip' === $subtype ) {
|
||||
$unzipfile = unzip_file( $path, $temp );
|
||||
|
||||
if ( is_wp_error( $unzipfile ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => $unzipfile->get_error_message() . '<br><br>' . esc_html__( 'Unzipping failed.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
$output = $this->get_valid_files( $temp );
|
||||
|
||||
if ( ! empty( $output ) ) {
|
||||
foreach ( $complete as $test ) {
|
||||
if ( ! isset( $output[ $test ] ) ) {
|
||||
$missing[] = $test;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! is_dir( $this->upload_dir . $subfolder . $name . '/' ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir . $subfolder . $name . '/' );
|
||||
}
|
||||
|
||||
foreach ( $output as $key => $value ) {
|
||||
$param_array = array(
|
||||
'destination' => $this->upload_dir . $subfolder . $name . '/' . $fontname . '.' . $key,
|
||||
'overwrite' => true,
|
||||
'chmod' => 755,
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'copy', $value, $param_array );
|
||||
}
|
||||
|
||||
if ( true === $this->can_convert && 'true' === $conversion ) {
|
||||
$ret = $this->get_missing_files( $name, $fontname, $missing, $output, $subfolder, $true_filename );
|
||||
}
|
||||
}
|
||||
|
||||
$this->parent->filesystem->execute( 'rmdir', $temp, array( 'recursive' => true ) );
|
||||
|
||||
$this->generate_css();
|
||||
|
||||
wp_delete_attachment( $attachment_id, true );
|
||||
} elseif ( 'svg+xml' === $subtype || 'vnd.ms-fontobject' === $subtype || 'x-font-ttf' === $subtype || 'ttf' === $subtype || 'otf' === $subtype || 'font-woff' === $subtype || 'font-woff2' === $subtype || 'application-octet-stream' === $subtype || 'octet-stream' === $subtype ) {
|
||||
foreach ( $complete as $test ) {
|
||||
if ( $subtype !== $test ) {
|
||||
if ( ! isset( $output[ $test ] ) ) {
|
||||
$missing[] = $test;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! is_dir( $this->upload_dir . $subfolder . $name . '/' ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $this->upload_dir . $subfolder . $name . '/' );
|
||||
}
|
||||
|
||||
$output = array( $subtype => $path );
|
||||
|
||||
// TODO: COnversion error not moving single file.
|
||||
if ( true === $this->can_convert && 'true' === $conversion ) {
|
||||
$ret = $this->get_missing_files( $name, $fontname, $missing, $output, $subfolder, $true_filename );
|
||||
} else {
|
||||
$param_array = array(
|
||||
'destination' => $this->upload_dir . $subfolder . '/' . $name . '/' . $true_filename, // $fontname . '.' . $subtype,
|
||||
'overwrite' => true,
|
||||
'chmod' => 755,
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'copy', $path, $param_array );
|
||||
}
|
||||
|
||||
$this->parent->filesystem->execute( 'rmdir', $temp, array( 'recursive' => true ) );
|
||||
|
||||
$this->generate_css();
|
||||
|
||||
wp_delete_attachment( $attachment_id, true );
|
||||
} else {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'File type not recognized.', 'redux-framework' ) . ' ' . $subtype,
|
||||
)
|
||||
);
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
if ( is_array( $ret ) && ! empty( $ret ) ) {
|
||||
$msg = esc_html__( 'Unidentified error.', 'redux-framework' );
|
||||
|
||||
if ( isset( $ret['msg'] ) ) {
|
||||
$msg = $ret['msg'];
|
||||
}
|
||||
|
||||
return $msg;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Ping the WebFontOMatic API to get the missing files.
|
||||
*
|
||||
* @param string $name Name.
|
||||
* @param string $fontname Font name.
|
||||
* @param array $missing Missing.
|
||||
* @param array $output Output.
|
||||
* @param string $subfolder Folder.
|
||||
* @param string $true_filename Font name with extension.
|
||||
*/
|
||||
private function get_missing_files( string $name, string $fontname, array $missing, array $output, string $subfolder, string $true_filename ) {
|
||||
if ( ! empty( $name ) && ! empty( $missing ) ) {
|
||||
$temp = $this->upload_dir . 'temp';
|
||||
|
||||
$font_ext = pathinfo( $true_filename, PATHINFO_EXTENSION );
|
||||
|
||||
$unsupported = array( 'eot', 'woff', 'woff2' );
|
||||
|
||||
// Find a file to convert from.
|
||||
foreach ( $output as $key => $value ) {
|
||||
if ( 'eot' === $key ) {
|
||||
continue;
|
||||
} else {
|
||||
$main = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $main ) ) {
|
||||
echo wp_json_encode(
|
||||
array(
|
||||
'type' => 'error',
|
||||
'msg' => esc_html__( 'No valid font file was found.', 'redux-framework' ),
|
||||
)
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'rmdir', $temp, array( 'recursive' => true ) );
|
||||
$this->parent->filesystem->execute( 'rmdir', $this->upload_dir . $subfolder . $name . '/', array( 'recursive' => true ) );
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
update_option( 'redux_custom_font_current', $name . '.zip' );
|
||||
|
||||
$boundary = wp_generate_password( 24 );
|
||||
|
||||
$headers = array(
|
||||
'content-type' => 'multipart/form-data; boundary=' . $boundary,
|
||||
'user-agent' => 'redux-custom-fonts-' . self::$version . ' using ' . wp_get_theme(),
|
||||
);
|
||||
|
||||
$payload = '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="md5"' . "\r\n\r\n";
|
||||
$payload .= md5( 'redux_custom_font' );
|
||||
$payload .= "\r\n";
|
||||
|
||||
if ( $output[ $main ] ) {
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="convert"; filename="' . basename( $output[ $main ] ) . '"' . "\r\n";
|
||||
$payload .= "\r\n";
|
||||
$payload .= $this->parent->filesystem->execute( 'get_contents', $output[ $main ] );
|
||||
$payload .= "\r\n";
|
||||
}
|
||||
|
||||
$payload .= '--' . $boundary . '--';
|
||||
|
||||
$args = array(
|
||||
'headers' => $headers,
|
||||
'body' => $payload,
|
||||
'user-agent' => $headers['user-agent'],
|
||||
'timeout' => 300,
|
||||
'sslverify' => true,
|
||||
);
|
||||
|
||||
// phpcs:disable WordPress.NamingConventions.ValidHookName
|
||||
$api_url = apply_filters( 'redux/' . $this->parent->args['opt_name'] . '/extensions/custom_fonts/api_url', 'https://redux.io/fonts' );
|
||||
|
||||
$response = wp_remote_post( $api_url, $args );
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return array(
|
||||
'type' => 'error',
|
||||
'msg' => $response->get_error_message() . '<br><br>' . esc_html__( 'Your font could not be converted at this time. Please try again later.', 'redux-framework' ),
|
||||
);
|
||||
} elseif ( null !== json_decode( $response['body'] ) ) {
|
||||
return json_decode( $response['body'], true );
|
||||
}
|
||||
|
||||
$param_array = array(
|
||||
'content' => $response['body'],
|
||||
'overwrite' => true,
|
||||
'chmod' => FS_CHMOD_FILE,
|
||||
);
|
||||
|
||||
$zip_file = $temp . DIRECTORY_SEPARATOR . $fontname . '.zip';
|
||||
|
||||
$ret = $this->parent->filesystem->execute( 'put_contents', $zip_file, $param_array );
|
||||
|
||||
$zip = unzip_file( $zip_file, $temp );
|
||||
|
||||
if ( ! is_wp_error( $zip ) ) {
|
||||
$params = array(
|
||||
'include_hidden' => false,
|
||||
'recursive' => false,
|
||||
);
|
||||
|
||||
$files = $this->parent->filesystem->execute( 'dirlist', $temp . DIRECTORY_SEPARATOR . 'fonts' . DIRECTORY_SEPARATOR, $params );
|
||||
|
||||
foreach ( $files as $file ) {
|
||||
$param_array = array(
|
||||
'destination' => $this->upload_dir . $subfolder . $name . DIRECTORY_SEPARATOR . $file['name'],
|
||||
'overwrite' => true,
|
||||
'chmod' => 755,
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'move', $temp . DIRECTORY_SEPARATOR . 'fonts' . DIRECTORY_SEPARATOR . $file['name'], $param_array );
|
||||
}
|
||||
} else {
|
||||
$path_parts = pathinfo( $output[ $main ] );
|
||||
|
||||
$param_array = array(
|
||||
'destination' => $this->upload_dir . $subfolder . $name . DIRECTORY_SEPARATOR . $path_parts['basename'],
|
||||
'overwrite' => true,
|
||||
'chmod' => 755,
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'move', $output[ $main ], $param_array );
|
||||
|
||||
if ( in_array( $font_ext, $unsupported, true ) ) {
|
||||
return array(
|
||||
'type' => 'error',
|
||||
// translators: %s = font extension.
|
||||
'msg' => $zip->get_error_message() . '<br><br>' . sprintf( esc_html__( 'The font converter does not support %s fonts.', 'redux-framework' ), $font_ext ),
|
||||
);
|
||||
} else {
|
||||
return array(
|
||||
'type' => 'error',
|
||||
'msg' => $zip->get_error_message() . '<br><br>' . esc_html__( 'ZIP error. Your font could not be converted at this time. Please try again later.', 'redux-framework' ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
delete_option( 'redux_custom_font_current' );
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the file name is a valid font file.
|
||||
*
|
||||
* @param array $file File.
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
private function check_font_name( array $file ) {
|
||||
if ( '.woff' === strtolower( substr( $file['name'], - 5 ) ) ) {
|
||||
return 'woff';
|
||||
}
|
||||
|
||||
if ( '.woff2' === strtolower( substr( $file['name'], - 6 ) ) ) {
|
||||
return 'woff2';
|
||||
}
|
||||
|
||||
$sub = strtolower( substr( $file['name'], - 4 ) );
|
||||
|
||||
if ( '.ttf' === $sub ) {
|
||||
return 'ttf';
|
||||
}
|
||||
|
||||
if ( '.eot' === $sub ) {
|
||||
return 'eot';
|
||||
}
|
||||
|
||||
if ( '.svg' === $sub ) {
|
||||
return 'svg';
|
||||
}
|
||||
|
||||
if ( '.otf' === $sub ) {
|
||||
return 'otf';
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a new custom CSS file for enqueuing on the frontend and backend.
|
||||
*/
|
||||
private function generate_css() {
|
||||
$params = array(
|
||||
'include_hidden' => false,
|
||||
'recursive' => true,
|
||||
);
|
||||
|
||||
$fonts = $this->parent->filesystem->execute( 'dirlist', $this->upload_dir . 'custom/', $params );
|
||||
|
||||
if ( empty( $fonts ) || ! is_array( $fonts ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ( $fonts as $font ) {
|
||||
if ( 'd' === $font['type'] ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ( file_exists( $this->upload_dir . 'fonts.css' ) ) {
|
||||
$this->parent->filesystem->execute( 'delete', $this->upload_dir . 'fonts.css' );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$css = '';
|
||||
|
||||
foreach ( $fonts as $font ) {
|
||||
if ( 'd' === $font['type'] ) {
|
||||
$css .= $this->generate_font_css( $font['name'], $this->upload_dir . 'custom/' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( '' !== $css ) {
|
||||
$param_array = array(
|
||||
'content' => $css,
|
||||
'chmod' => FS_CHMOD_FILE,
|
||||
);
|
||||
|
||||
$this->parent->filesystem->execute( 'put_contents', $this->upload_dir . 'fonts.css', $param_array );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process to actually construct the custom font css file.
|
||||
*
|
||||
* @param string $name Name.
|
||||
* @param string $dir Directory.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function generate_font_css( string $name, string $dir ): ?string {
|
||||
$path = $dir . $name;
|
||||
|
||||
$params = array(
|
||||
'include_hidden' => false,
|
||||
'recursive' => true,
|
||||
);
|
||||
|
||||
$files = $this->parent->filesystem->execute( 'dirlist', $path, $params );
|
||||
|
||||
if ( empty( $files ) ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$output = array();
|
||||
|
||||
foreach ( $files as $file ) {
|
||||
$output[ $this->check_font_name( $file ) ] = $file['name'];
|
||||
}
|
||||
|
||||
$css = '@font-face {';
|
||||
|
||||
$css .= 'font-family:"' . $name . '";';
|
||||
|
||||
$src = array();
|
||||
|
||||
if ( isset( $output['eot'] ) ) {
|
||||
$src[] = "url('{$this->upload_url}custom/$name/{$output['eot']}?#iefix') format('embedded-opentype')";
|
||||
}
|
||||
|
||||
if ( isset( $output['woff'] ) ) {
|
||||
$src[] = "url('{$this->upload_url}custom/$name/{$output['woff']}') format('woff')";
|
||||
}
|
||||
|
||||
if ( isset( $output['woff2'] ) ) {
|
||||
$src[] = "url('{$this->upload_url}custom/$name/{$output['woff2']}') format('woff2')";
|
||||
}
|
||||
|
||||
if ( isset( $output['ttf'] ) ) {
|
||||
$src[] = "url('{$this->upload_url}custom/$name/{$output['ttf']}') format('truetype')";
|
||||
}
|
||||
|
||||
if ( isset( $output['svg'] ) ) {
|
||||
$src[] = "url('{$this->upload_url}custom/$name/{$output['svg']}#svg$name') format('svg')";
|
||||
}
|
||||
|
||||
if ( ! empty( $src ) ) {
|
||||
$css .= 'src:' . implode( ', ', $src ) . ';';
|
||||
}
|
||||
|
||||
// Replace font weight and style with sub-sets.
|
||||
$css .= 'font-weight: normal;';
|
||||
|
||||
$css .= 'font-style: normal;';
|
||||
|
||||
$css .= '}';
|
||||
|
||||
return $css;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function for filtering the section array.
|
||||
* Good for child themes to override or add to the sections.
|
||||
* Simply include this function in the child themes functions.php file.
|
||||
* NOTE: the defined constants for URLs and directories will NOT be available at this point in a child theme,
|
||||
* so you must use get_template_directory_uri() if you want to use any of the built-in icons
|
||||
*/
|
||||
public function add_section() {
|
||||
if ( ! isset( $this->parent->fontControl ) ) {
|
||||
$this->parent->sections[] = array(
|
||||
'title' => esc_html__( 'Font Control', 'redux-framework' ),
|
||||
'desc' => '<p class="description"></p>',
|
||||
'icon' => 'el-icon-font',
|
||||
'id' => 'redux_dynamic_font_control',
|
||||
// Leave this as a blank section, no options just some intro text set above.
|
||||
'fields' => array(),
|
||||
);
|
||||
|
||||
for ( $i = count( $this->parent->sections ); $i >= 1; $i-- ) {
|
||||
if ( isset( $this->parent->sections[ $i ] ) && isset( $this->parent->sections[ $i ]['title'] ) && esc_html__( 'Font Control', 'redux-framework' ) === $this->parent->sections[ $i ]['title'] ) {
|
||||
$this->parent->fontControl = $i;
|
||||
$this->parent->sections[ $this->parent->fontControl ]['fields'][] = array(
|
||||
'id' => 'redux_font_control',
|
||||
'type' => 'custom_fonts',
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias( 'Redux_Extension_Custom_Fonts', 'ReduxFramework_Extension_custom_fonts' );
|
||||
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Custom Font Field Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com> & Dovy Paukstys <dovy@reduxframework.com>
|
||||
* @class Redux_Custom_Fonts
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Custom_Fonts' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_custom_fonts class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Custom_Fonts extends Redux_Field {
|
||||
|
||||
/**
|
||||
* Set field defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
$defaults = array(
|
||||
'convert' => false,
|
||||
'eot' => false,
|
||||
'svg' => false,
|
||||
'ttf' => false,
|
||||
'woff' => true,
|
||||
'woff2' => true,
|
||||
);
|
||||
|
||||
$this->value = wp_parse_args( $this->value, $defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field Render Function.
|
||||
* Takes the vars and outputs the HTML for the field in the settings
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function render() {
|
||||
echo '</fieldset></td></tr>';
|
||||
echo '<tr>';
|
||||
echo '<td colspan="2">';
|
||||
echo '<fieldset
|
||||
class="redux-field-container redux-field redux-field-init redux-container-custom_font"
|
||||
data-type="' . esc_attr( $this->field['type'] ) . '"
|
||||
data-id="' . esc_attr( $this->field['id'] ) . '"
|
||||
>';
|
||||
|
||||
$can_convert = true;
|
||||
|
||||
$nonce = wp_create_nonce( 'redux_custom_fonts' );
|
||||
|
||||
$this->field['custom_fonts'] = apply_filters( "redux/{$this->parent->args[ 'opt_name' ]}/field/typography/custom_fonts", array() ); // phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
|
||||
if ( $can_convert ) {
|
||||
echo '<div class="">';
|
||||
echo '<label for="custom-font-convert">';
|
||||
echo '<input type="hidden" class="checkbox-check" data-val="1" name="' . esc_attr( $this->field['name'] ) . '[convert]" value="' . esc_attr( $this->value['convert'] ) . '"/>';
|
||||
echo '<input type="checkbox" class="checkbox" id="custom-font-convert" value="1"' . checked( $this->value['convert'], '1', false ) . '">';
|
||||
echo 'Enable font conversion';
|
||||
echo '</label>';
|
||||
echo '</div>';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
if ( ! empty( $this->field['custom_fonts'] ) ) {
|
||||
foreach ( $this->field['custom_fonts'] as $section => $fonts ) {
|
||||
if ( empty( $fonts ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
echo '<h3>' . esc_html( $section ) . '</h3>';
|
||||
echo '<div class="font-error" style="display: none;"><p><strong>' . esc_html__( 'Error', 'redux-framework' ) . '</strong>: <span></span></p></div>';
|
||||
|
||||
echo '<table class="wp-list-table widefat plugins" style="border-spacing:0;"><tbody>';
|
||||
|
||||
foreach ( $fonts as $font => $pieces ) {
|
||||
echo '<tr class="active">';
|
||||
echo '<td class="plugin-title" style="min-width: 40%"><strong>' . esc_html( $font ) . '</strong></td>';
|
||||
echo '<td class="column-description desc">';
|
||||
echo '<div class="plugin-description">';
|
||||
|
||||
if ( is_array( $pieces ) && ! empty( $pieces ) ) {
|
||||
foreach ( $pieces as $piece ) {
|
||||
echo '<span class="button button-primary button-small font-pieces">' . esc_html( $piece ) . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
echo '</td>';
|
||||
echo '<td style="width: 140px;"><div class="action-row visible">';
|
||||
echo '<span style="display:none;"><a href="#" class="rename">Rename</a> | </span>';
|
||||
echo '<a href="#" class="fontDelete delete" data-section="' . esc_attr( $section ) . '" data-name="' . esc_attr( $font ) . '" data-type="delete">' . esc_html__( 'Delete', 'redux-framework' ) . '</a>';
|
||||
echo '<span class="spinner" style="display:none; visibility: visible;"></span>';
|
||||
echo '</div>';
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
echo '</tbody></table>';
|
||||
}
|
||||
|
||||
echo '<div class="upload_button_div"><span class="button media_add_font" data-nonce="' . esc_attr( $nonce ) . '" id="' . esc_attr( $this->field['id'] ) . '-custom_fonts">' . esc_html__( 'Add Font', 'redux-framework' ) . '</span></div><br />';
|
||||
} else {
|
||||
echo '<h3>' . esc_html__( 'No Custom Fonts Found', 'redux-framework' ) . '</h3>';
|
||||
echo '<div class="upload_button_div"><span class="button media_add_font" data-nonce="' . esc_attr( $nonce ) . '" id="' . esc_attr( $this->field['id'] ) . '-custom_fonts">' . esc_html__( 'Add Font', 'redux-framework' ) . '</span></div>';
|
||||
}
|
||||
|
||||
echo '</fieldset></td></tr>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Functions to pass data from the PHP to the JS at render time.
|
||||
*
|
||||
* @param array $field Field.
|
||||
* @param string $value Value.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function localize( $field, $value = '' ): array {
|
||||
$params = array();
|
||||
|
||||
if ( ! isset( $field['mode'] ) ) {
|
||||
$field['mode'] = 'image';
|
||||
}
|
||||
|
||||
$params['mode'] = $field['mode'];
|
||||
|
||||
if ( empty( $value ) && isset( $this->value ) ) {
|
||||
$value = $this->value;
|
||||
}
|
||||
|
||||
$params['val'] = $value;
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Function.
|
||||
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @return void
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function enqueue() {
|
||||
$min = Redux_Functions::isMin();
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-field-custom-fonts',
|
||||
$this->url . '/redux-custom-fonts' . $min . '.js',
|
||||
array( 'jquery', 'redux-block-ui' ),
|
||||
Redux_Extension_Custom_Fonts::$version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'redux-field-custom-fonts',
|
||||
'redux_custom_fonts_l10',
|
||||
apply_filters(
|
||||
'redux_custom_fonts_localized_data',
|
||||
array(
|
||||
'delete_error' => esc_html__( 'There was an error deleting your font:', 'redux-framework' ),
|
||||
'unzip' => esc_html__( 'Unzipping archive and generating any missing font files.', 'redux-framework' ),
|
||||
'convert' => esc_html__( 'Converting font file(s)...', 'redux-framework' ),
|
||||
'partial' => esc_html__( 'The only file(s) imported were those uploaded. Please refresh the page to continue (making note of any errors before doing so, please).', 'redux-framework' ),
|
||||
'unknown' => esc_html__( 'An unknown error occurred. Please try again.', 'redux-framework' ),
|
||||
'complete' => esc_html__( 'Conversion complete. Refreshing page...', 'redux-framework' ),
|
||||
'media_title' => esc_html__( 'Choose Font file or ZIP of font files.', 'redux-framework' ),
|
||||
'media_button' => esc_html__( 'Update', 'redux-framework' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-custom-fonts',
|
||||
$this->url . 'redux-custom-fonts.css',
|
||||
array(),
|
||||
Redux_Extension_Custom_Fonts::$version
|
||||
);
|
||||
}
|
||||
|
||||
$class = Redux_Extension_Custom_Fonts::$instance;
|
||||
|
||||
if ( ! empty( $class->custom_fonts ) ) {
|
||||
if ( file_exists( $class->upload_dir . 'fonts.css' ) ) {
|
||||
wp_enqueue_style(
|
||||
'redux-custom_fonts',
|
||||
$class->upload_url . 'fonts.css',
|
||||
array(),
|
||||
Redux_Core::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,33 @@
|
||||
.redux-container-custom_font table tr td { padding: 10px 9px !important; }
|
||||
|
||||
.redux-container-custom_font table.widefat { border-left: 1px solid #dfdfdf; border-right: 1px solid #dfdfdf; border-top: 1px solid #dfdfdf; }
|
||||
|
||||
.redux-container-custom_font .upload_button_div { margin: 10px 0; float: right; }
|
||||
|
||||
.redux-container-custom_font .spinner { margin-top: 0; }
|
||||
|
||||
.redux-container-custom_font .fontDelete { float: right; }
|
||||
|
||||
.redux-container-custom_font .action-row { text-align: right; padding-right: 5px; line-height: 20px; }
|
||||
|
||||
.redux-container-custom_font .plugins .active td, .redux-container-custom_font .plugins .active th { background-color: #FAFAFA; }
|
||||
|
||||
.redux-container-custom_font .font-error { margin: 5px 0 15px; border-left: 4px solid #dd3d36; background: #fff; -webkit-box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1); padding: 1px 12px; outline: 0; }
|
||||
|
||||
.redux-container-custom_font .font-error p { margin: 0.5em 0; padding: 2px; }
|
||||
|
||||
.redux-container-custom_font .conversion-types { border: solid #e7e7e7 1px; padding-top: 5px; padding-bottom: 5px; padding-left: 10px; margin-bottom: 10px; opacity: 1; }
|
||||
|
||||
.redux-container-custom_font .conversion-types .checkbox { margin-left: 20px !important; }
|
||||
|
||||
.redux-container-custom_font .conversion-types.is-disabled { cursor: not-allowed; opacity: 0.7; }
|
||||
|
||||
.redux-container-custom_font .conversion-types.is-disabled .checkbox, .redux-container-custom_font .conversion-types.is-disabled label { cursor: not-allowed; }
|
||||
|
||||
.redux-container-custom_font .font-pieces { margin-right: 1px; }
|
||||
|
||||
.fontActionWorking { background: green !important; }
|
||||
|
||||
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtY3VzdG9tLWZvbnRzLmNzcyIsInNvdXJjZXMiOlsicmVkdXgtY3VzdG9tLWZvbnRzLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsQUFFUSw0QkFGb0IsQ0FDeEIsS0FBSyxDQUNELEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFDRixPQUFPLEVBQUUsbUJBQW1CLEdBQy9COztBQUpULEFBTVEsNEJBTm9CLENBQ3hCLEtBQUssQUFLQSxRQUFRLENBQUMsRUFDTixXQUFXLEVBQUUsaUJBQWlCLEVBQzlCLFlBQVksRUFBRSxpQkFBaUIsRUFDL0IsVUFBVSxFQUFFLGlCQUFpQixHQUNoQzs7QUFWVCxBQWFJLDRCQWJ3QixDQWF4QixrQkFBa0IsQ0FBQyxFQUNmLE1BQU0sRUFBRSxNQUFNLEVBQ2QsS0FBSyxFQUFFLEtBQUssR0FDZjs7QUFoQkwsQUFrQkksNEJBbEJ3QixDQWtCeEIsUUFBUSxDQUFDLEVBQ0wsVUFBVSxFQUFDLENBQUMsR0FDZjs7QUFwQkwsQUFzQkksNEJBdEJ3QixDQXNCeEIsV0FBVyxDQUFDLEVBQ1IsS0FBSyxFQUFFLEtBQUssR0FDZjs7QUF4QkwsQUEwQkksNEJBMUJ3QixDQTBCeEIsV0FBVyxDQUFDLEVBQ1IsVUFBVSxFQUFFLEtBQUssRUFDakIsYUFBYSxFQUFFLEdBQUcsRUFDbEIsV0FBVyxFQUFFLElBQUksR0FDcEI7O0FBOUJMLEFBa0NZLDRCQWxDZ0IsQ0FnQ3hCLFFBQVEsQ0FDSixPQUFPLENBQ0gsRUFBRSxFQWxDZCw0QkFBNEIsQ0FnQ3hCLFFBQVEsQ0FDSixPQUFPLENBRUgsRUFBRSxDQUFDLEVBQ0MsZ0JBQWdCLEVBQUUsT0FBTyxHQUM1Qjs7QUFyQ2IsQUF5Q0ksNEJBekN3QixDQXlDeEIsV0FBVyxDQUFDLEVBQ1IsTUFBTSxFQUFFLFVBQVUsRUFDbEIsV0FBVyxFQUFFLGlCQUFpQixFQUM5QixVQUFVLEVBQUUsSUFBSSxFQUNoQixrQkFBa0IsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsa0JBQW9CLEVBQ3BELFVBQVUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsa0JBQW9CLEVBQzVDLE9BQU8sRUFBRSxRQUFRLEVBQ2pCLE9BQU8sRUFBRSxDQUFDLEdBS2I7O0FBckRMLEFBaURRLDRCQWpEb0IsQ0F5Q3hCLFdBQVcsQ0FRUCxDQUFDLENBQUMsRUFDRSxNQUFNLEVBQUUsT0FBTyxFQUNmLE9BQU8sRUFBRSxHQUFHLEdBQ2Y7O0FBcERULEFBdURJLDRCQXZEd0IsQ0F1RHhCLGlCQUFpQixDQUFDLEVBQ2QsTUFBTSxFQUFFLGlCQUFpQixFQUN6QixXQUFXLEVBQUUsR0FBRyxFQUNoQixjQUFjLEVBQUUsR0FBRyxFQUNuQixZQUFZLEVBQUUsSUFBSSxFQUNsQixhQUFhLEVBQUUsSUFBSSxFQUNuQixPQUFPLEVBQUMsQ0FBQyxHQWVaOztBQTVFTCxBQStEUSw0QkEvRG9CLENBdUR4QixpQkFBaUIsQ0FRYixTQUFTLENBQUMsRUFDTixXQUFXLEVBQUUsSUFBSSxDQUFBLFVBQVUsR0FDOUI7O0FBakVULEFBbUVRLDRCQW5Fb0IsQ0F1RHhCLGlCQUFpQixBQVlaLFlBQVksQ0FBQyxFQUNWLE1BQU0sRUFBQyxXQUFXLEVBQ2xCLE9BQU8sRUFBRSxHQUFHLEdBTWY7O0FBM0VULEFBdUVZLDRCQXZFZ0IsQ0F1RHhCLGlCQUFpQixBQVlaLFlBQVksQ0FJVCxTQUFTLEVBdkVyQiw0QkFBNEIsQ0F1RHhCLGlCQUFpQixBQVlaLFlBQVksQ0FLVCxLQUFLLENBQUMsRUFDRixNQUFNLEVBQUMsV0FBVyxHQUNyQjs7QUExRWIsQUE4RUksNEJBOUV3QixDQThFeEIsWUFBWSxDQUFDLEVBQ1QsWUFBWSxFQUFFLEdBQUcsR0FDcEI7O0FBR0wsQUFBQSxrQkFBa0IsQ0FBQyxFQUNmLFVBQVUsRUFBRSxnQkFBZ0IsR0FDL0IifQ== */
|
||||
|
||||
/*# sourceMappingURL=redux-custom-fonts.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,329 @@
|
||||
/* global redux, wp, redux_custom_fonts_l10, ajaxurl */
|
||||
|
||||
(function ( $ ) {
|
||||
'use strict';
|
||||
|
||||
var l10n;
|
||||
var reduxObject;
|
||||
var ajaxDone = false;
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.custom_fonts = redux.field_objects.custom_fonts || {};
|
||||
|
||||
redux.field_objects.custom_fonts.init = function ( selector ) {
|
||||
|
||||
// If no selector is passed, grab one from the HTML.
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-custom_font:visible' );
|
||||
}
|
||||
|
||||
// Enum instances of our object.
|
||||
$( selector ).each(
|
||||
function () {
|
||||
var el = $( this );
|
||||
var parent = el;
|
||||
|
||||
if ( ! el.hasClass( 'redux-field-container' ) ) {
|
||||
parent = el.parents( '.redux-field-container:first' );
|
||||
}
|
||||
|
||||
if ( parent.is( ':hidden' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( parent.hasClass( 'redux-field-init' ) ) {
|
||||
parent.removeClass( 'redux-field-init' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Init module level code.
|
||||
redux.field_objects.custom_fonts.modInit( el );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.custom_fonts.modInit = function ( el ) {
|
||||
var optName = $( '.redux-ajax-security' ).data( 'opt-name' );
|
||||
|
||||
l10n = redux_custom_fonts_l10;
|
||||
|
||||
if ( undefined === optName ) {
|
||||
reduxObject = redux;
|
||||
} else {
|
||||
reduxObject = redux.optName;
|
||||
}
|
||||
|
||||
el.find( '.checkbox' ).on(
|
||||
'click',
|
||||
function () {
|
||||
var val = 0;
|
||||
var checkName;
|
||||
var checkVal;
|
||||
var opVal;
|
||||
|
||||
checkName = $( this ).attr( 'id' );
|
||||
|
||||
if ( 'custom-font-convert' === checkName ) {
|
||||
if ( $( this ).is( ':checked' ) ) {
|
||||
checkVal = '';
|
||||
opVal = 1;
|
||||
|
||||
el.find( '.conversion-types' ).removeClass( 'is-disabled' );
|
||||
} else {
|
||||
checkVal = 'disabled';
|
||||
opVal = 0.7;
|
||||
|
||||
el.find( '.conversion-types' ).addClass( 'is-disabled' );
|
||||
}
|
||||
|
||||
el.find( '#custom-font-eot,#custom-font-svg,#custom-font-ttf,#custom-font-woff,#custom-font-woff2' ).prop( 'disabled', checkVal );
|
||||
el.find( '.conversion-types' ).css( 'opacity', opVal );
|
||||
}
|
||||
|
||||
if ( $( this ).is( ':checked' ) ) {
|
||||
val = $( this ).parent().find( '.checkbox-check' ).attr( 'data-val' );
|
||||
}
|
||||
|
||||
$( this ).parent().find( '.checkbox-check' ).val( val );
|
||||
|
||||
redux_change( $( this ) );
|
||||
}
|
||||
);
|
||||
|
||||
// Remove the image button.
|
||||
el.find( '.remove-font' ).off( 'click' ).on(
|
||||
'click',
|
||||
function () {
|
||||
redux.field_objects.custom_fonts.remove_font( el, $( this ).parents( 'fieldset.redux-field:first' ) );
|
||||
}
|
||||
);
|
||||
|
||||
// Upload media button.
|
||||
el.find( '.media_add_font' ).off().on(
|
||||
'click',
|
||||
function ( event ) {
|
||||
redux.field_objects.custom_fonts.add_font( el, event, $( this ).parents( 'fieldset.redux-field:first' ) );
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '.fontDelete' ).on(
|
||||
'click',
|
||||
function ( e ) {
|
||||
var data;
|
||||
|
||||
var parent = $( this ).parents( 'td:first' );
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
parent.find( '.spinner' ).show();
|
||||
|
||||
data = $( this ).data();
|
||||
data.action = 'redux_custom_fonts';
|
||||
data.nonce = $( this ).parents( '.redux-container-custom_font:first' ).find( '.media_add_font' ).attr( 'data-nonce' );
|
||||
|
||||
$.post(
|
||||
ajaxurl,
|
||||
data,
|
||||
function ( response ) {
|
||||
var rowCount;
|
||||
|
||||
response = JSON.parse( response );
|
||||
|
||||
if ( response.type && 'success' === response.type ) {
|
||||
rowCount = parent.parents( 'table:first' ).find( 'tr' ).length;
|
||||
|
||||
if ( 1 === rowCount ) {
|
||||
parent.parents( 'table:first' ).fadeOut().remove();
|
||||
} else {
|
||||
parent.parents( 'tr:first' ).fadeOut().remove();
|
||||
}
|
||||
} else {
|
||||
alert( l10n.delete_error + ' ' + response.msg );
|
||||
|
||||
parent.find( '.spinner' ).hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.custom_fonts.startTimer = function ( el, status ) {
|
||||
var cur_data;
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
url: ajaxurl,
|
||||
type: 'POST',
|
||||
data: {
|
||||
action: 'redux_custom_font_timer'
|
||||
},
|
||||
beforeSend: function () {
|
||||
|
||||
},
|
||||
success: function ( data ) {
|
||||
var msg;
|
||||
|
||||
if ( false === ajaxDone ) {
|
||||
setTimeout( redux.field_objects.custom_fonts.startTimer( el, status ), 500 );
|
||||
|
||||
msg = reduxObject.args.please_wait + ': ' + status + '<br><br>' + data;
|
||||
} else {
|
||||
msg = l10n.complete;
|
||||
data = 'finished';
|
||||
}
|
||||
|
||||
if ( '' !== data ) {
|
||||
if ( cur_data !== data ) {
|
||||
$( '.blockUI.blockMsg h2' ).html( msg );
|
||||
|
||||
cur_data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.custom_fonts.add_font = function ( el, event, selector ) {
|
||||
var frame;
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// If the media frame already exists, reopen it.
|
||||
if ( frame ) {
|
||||
frame.open();
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the media frame.
|
||||
frame = wp.media(
|
||||
{
|
||||
multiple: false,
|
||||
library: {
|
||||
type: ['application', 'font'] // Only allow zip files.
|
||||
}, // Set the title of the modal.
|
||||
title: 'Redux Custom Fonts: ' + l10n.media_title, // Customize the submit button.
|
||||
button: {
|
||||
|
||||
// Set the text of the button.
|
||||
text: l10n.media_button
|
||||
|
||||
// Tell the button not to close the modal, since we're
|
||||
// going to refresh the page when the image is selected.
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// When an image is selected, run a callback.
|
||||
frame.on(
|
||||
'select',
|
||||
function () {
|
||||
var nonce;
|
||||
var data;
|
||||
var status;
|
||||
var conversion;
|
||||
|
||||
// Grab the selected attachment.
|
||||
var attachment = frame.state().get( 'selection' ).first();
|
||||
var error = selector.find( '.font-error' );
|
||||
|
||||
error.slideUp();
|
||||
error.find( 'span' ).text( '' );
|
||||
|
||||
frame.close();
|
||||
if ( 'application' !== attachment.attributes.type && 'font' !== attachment.attributes.type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
nonce = $( selector ).find( '.media_add_font' ).attr( 'data-nonce' );
|
||||
|
||||
conversion = $( '#custom-font-convert' ).is( ':checked' );
|
||||
|
||||
data = {
|
||||
action: 'redux_custom_fonts',
|
||||
nonce: nonce,
|
||||
attachment_id: attachment.id,
|
||||
title: attachment.attributes.title,
|
||||
mime: attachment.attributes.mime,
|
||||
filename: attachment.attributes.filename,
|
||||
conversion: Boolean( conversion )
|
||||
};
|
||||
|
||||
if ( 'application/zip ' === data.mime ) {
|
||||
status = l10n.unzip;
|
||||
} else {
|
||||
status = l10n.convert;
|
||||
}
|
||||
|
||||
redux.field_objects.custom_fonts.startTimer( el, status );
|
||||
|
||||
$.blockUI( { message: '<h2>' + reduxObject.args.please_wait + ': ' + status + '</h2>' } );
|
||||
|
||||
$.post(
|
||||
ajaxurl,
|
||||
data,
|
||||
function ( response ) {
|
||||
console.log( 'Redux Custom Fonts API Response (For support purposes)' );
|
||||
console.log( response );
|
||||
|
||||
response = JSON.parse( response );
|
||||
|
||||
if ( 'success' === response.type ) {
|
||||
if ( '' !== response.msg ) {
|
||||
$.unblockUI();
|
||||
|
||||
error.find( 'span' ).html( response.msg + ' ' + l10n.partial );
|
||||
error.slideDown();
|
||||
|
||||
ajaxDone = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window.onbeforeunload = '';
|
||||
location.reload();
|
||||
} else if ( 'error' === response.type ) {
|
||||
$.unblockUI();
|
||||
error.find( 'span' ).html( response.msg );
|
||||
error.slideDown();
|
||||
} else {
|
||||
$.unblockUI();
|
||||
error.find( 'span' ).text( l10n.unknown );
|
||||
error.slideDown();
|
||||
}
|
||||
|
||||
ajaxDone = true;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
// Finally, open the modal.
|
||||
frame.open();
|
||||
};
|
||||
|
||||
redux.field_objects.custom_fonts.remove_font = function ( el, selector ) {
|
||||
el = null;
|
||||
|
||||
// This shouldn't have been run...
|
||||
if ( ! selector.find( '.remove-image' ).addClass( 'hide' ) ) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
redux.field_objects.custom_fonts.sleep = function ( milliseconds ) {
|
||||
var start = new Date().getTime();
|
||||
|
||||
var i;
|
||||
|
||||
for ( i = 0; i < 1e7; i += 1 ) {
|
||||
if ( ( new Date().getTime() - start ) > milliseconds ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
})( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
.redux-container-custom_font table tr td{padding:10px 9px !important}.redux-container-custom_font table.widefat{border-left:1px solid #dfdfdf;border-right:1px solid #dfdfdf;border-top:1px solid #dfdfdf}.redux-container-custom_font .upload_button_div{margin:10px 0;float:right}.redux-container-custom_font .spinner{margin-top:0}.redux-container-custom_font .fontDelete{float:right}.redux-container-custom_font .action-row{text-align:right;padding-right:5px;line-height:20px}.redux-container-custom_font .plugins .active td,.redux-container-custom_font .plugins .active th{background-color:#fafafa}.redux-container-custom_font .font-error{margin:5px 0 15px;border-left:4px solid #dd3d36;background:#fff;-webkit-box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);box-shadow:0 1px 1px 0 rgba(0,0,0,0.1);padding:1px 12px;outline:0}.redux-container-custom_font .font-error p{margin:.5em 0;padding:2px}.fontActionWorking{background:green !important}
|
||||
@@ -0,0 +1 @@
|
||||
!function(r){"use strict";var a,c,f=!1;redux.field_objects=redux.field_objects||{},redux.field_objects.custom_fonts=redux.field_objects.custom_fonts||{},redux.field_objects.custom_fonts.init=function(t){t=t||r(document).find(".redux-group-tab:visible").find(".redux-container-custom_font:visible"),r(t).each(function(){var t=r(this),e=t;(e=t.hasClass("redux-field-container")?e:t.parents(".redux-field-container:first")).is(":hidden")||e.hasClass("redux-field-init")&&(e.removeClass("redux-field-init"),redux.field_objects.custom_fonts.modInit(t))})},redux.field_objects.custom_fonts.modInit=function(n){var t=r(".redux-ajax-security").data("opt-name");a=redux_custom_fonts_l10,c=void 0===t?redux:redux.optName,n.find(".checkbox").on("click",function(){var t,e,o=0;"custom-font-convert"===r(this).attr("id")&&(r(this).is(":checked")?(t="",e=1,n.find(".conversion-types").removeClass("is-disabled")):(t="disabled",e=.7,n.find(".conversion-types").addClass("is-disabled")),n.find("#custom-font-eot,#custom-font-svg,#custom-font-ttf,#custom-font-woff,#custom-font-woff2").prop("disabled",t),n.find(".conversion-types").css("opacity",e)),r(this).is(":checked")&&(o=r(this).parent().find(".checkbox-check").attr("data-val")),r(this).parent().find(".checkbox-check").val(o),redux_change(r(this))}),n.find(".remove-font").off("click").on("click",function(){redux.field_objects.custom_fonts.remove_font(n,r(this).parents("fieldset.redux-field:first"))}),n.find(".media_add_font").off().on("click",function(t){redux.field_objects.custom_fonts.add_font(n,t,r(this).parents("fieldset.redux-field:first"))}),n.find(".fontDelete").on("click",function(t){var e=r(this).parents("td:first");return t.preventDefault(),e.find(".spinner").show(),(t=r(this).data()).action="redux_custom_fonts",t.nonce=r(this).parents(".redux-container-custom_font:first").find(".media_add_font").attr("data-nonce"),r.post(ajaxurl,t,function(t){(t=JSON.parse(t)).type&&"success"===t.type?(1===e.parents("table:first").find("tr").length?e.parents("table:first"):e.parents("tr:first")).fadeOut().remove():(alert(a.delete_error+" "+t.msg),e.find(".spinner").hide())}),!1})},redux.field_objects.custom_fonts.startTimer=function(o,n){var s;r.ajax({url:ajaxurl,type:"POST",data:{action:"redux_custom_font_timer"},beforeSend:function(){},success:function(t){var e;!1===f?(setTimeout(redux.field_objects.custom_fonts.startTimer(o,n),500),e=c.args.please_wait+": "+n+"<br><br>"+t):(e=a.complete,t="finished"),""!==t&&s!==t&&(r(".blockUI.blockMsg h2").html(e),s=t)}})},redux.field_objects.custom_fonts.add_font=function(s,t,i){var d;t.preventDefault(),(d=wp.media({multiple:!1,library:{type:["application","font"]},title:"Redux Custom Fonts: "+a.media_title,button:{text:a.media_button}})).on("select",function(){var t,e,o=d.state().get("selection").first(),n=i.find(".font-error");n.slideUp(),n.find("span").text(""),d.close(),"application"!==o.attributes.type&&"font"!==o.attributes.type||(t=r(i).find(".media_add_font").attr("data-nonce"),e=r("#custom-font-convert").is(":checked"),o="application/zip "===(t={action:"redux_custom_fonts",nonce:t,attachment_id:o.id,title:o.attributes.title,mime:o.attributes.mime,filename:o.attributes.filename,conversion:Boolean(e)}).mime?a.unzip:a.convert,redux.field_objects.custom_fonts.startTimer(s,o),r.blockUI({message:"<h2>"+c.args.please_wait+": "+o+"</h2>"}),r.post(ajaxurl,t,function(t){if(console.log("Redux Custom Fonts API Response (For support purposes)"),console.log(t),"success"===(t=JSON.parse(t)).type){if(""!==t.msg)return r.unblockUI(),n.find("span").html(t.msg+" "+a.partial),n.slideDown(),void(f=!0);window.onbeforeunload="",location.reload()}else"error"===t.type?(r.unblockUI(),n.find("span").html(t.msg)):(r.unblockUI(),n.find("span").text(a.unknown)),n.slideDown();f=!0}))}),d.open()},redux.field_objects.custom_fonts.remove_font=function(t,e){e.find(".remove-image").addClass("hide")},redux.field_objects.custom_fonts.sleep=function(t){for(var e=(new Date).getTime(),o=0;o<1e7&&!((new Date).getTime()-e>t);o+=1);}}(jQuery);
|
||||
@@ -0,0 +1,86 @@
|
||||
.redux-container-custom_font {
|
||||
table {
|
||||
tr td {
|
||||
padding: 10px 9px !important;
|
||||
}
|
||||
|
||||
&.widefat {
|
||||
border-left: 1px solid #dfdfdf;
|
||||
border-right: 1px solid #dfdfdf;
|
||||
border-top: 1px solid #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
.upload_button_div {
|
||||
margin: 10px 0;
|
||||
float: right;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
margin-top:0;
|
||||
}
|
||||
|
||||
.fontDelete {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.action-row {
|
||||
text-align: right;
|
||||
padding-right: 5px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.plugins {
|
||||
.active {
|
||||
td,
|
||||
th {
|
||||
background-color: #FAFAFA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.font-error {
|
||||
margin: 5px 0 15px;
|
||||
border-left: 4px solid #dd3d36;
|
||||
background: #fff;
|
||||
-webkit-box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
|
||||
box-shadow: 0 1px 1px 0 rgba( 0, 0, 0, 0.1 );
|
||||
padding: 1px 12px;
|
||||
outline: 0;
|
||||
p {
|
||||
margin: 0.5em 0;
|
||||
padding: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.conversion-types {
|
||||
border: solid #e7e7e7 1px;
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
padding-left: 10px;
|
||||
margin-bottom: 10px;
|
||||
opacity:1;
|
||||
|
||||
.checkbox {
|
||||
margin-left: 20px!important;
|
||||
}
|
||||
|
||||
&.is-disabled {
|
||||
cursor:not-allowed;
|
||||
opacity: 0.7;
|
||||
|
||||
.checkbox,
|
||||
label {
|
||||
cursor:not-allowed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.font-pieces {
|
||||
margin-right: 1px;
|
||||
}
|
||||
}
|
||||
|
||||
.fontActionWorking {
|
||||
background: green !important;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,817 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Customizer Extension Class
|
||||
* Short description.
|
||||
*
|
||||
* @package ReduxFramework/Extentions
|
||||
* @class Redux_Extension_Customizer
|
||||
* @version 4.4.11
|
||||
* @noinspection PhpIgnoredClassAliasDeclaration
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Extension_Customizer', false ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework customizer extension class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Extension_Customizer extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Set extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.4.11';
|
||||
|
||||
/**
|
||||
* Set the name of the field. Ideally, this will also be your extension's name.
|
||||
* Please use underscores and NOT dashes.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $field_name = 'customizer';
|
||||
|
||||
/**
|
||||
* Set the friendly name of the extension. This is for display purposes. No underscores or dashes are required.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension_name = 'Customizer';
|
||||
|
||||
/**
|
||||
* Original options.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $orig_options = array();
|
||||
|
||||
/**
|
||||
* Post values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $post_values = array();
|
||||
|
||||
/**
|
||||
* Options array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $options = array();
|
||||
|
||||
/**
|
||||
* Controls array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $controls = array();
|
||||
|
||||
/**
|
||||
* Before save array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $before_save = array();
|
||||
|
||||
/**
|
||||
* Redux object.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
protected $redux;
|
||||
|
||||
/**
|
||||
* Field array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $redux_fields = array();
|
||||
|
||||
/**
|
||||
* Redux_Extension_my_extension constructor.
|
||||
*
|
||||
* @param ReduxFramework $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
global $pagenow;
|
||||
global $wp_customize;
|
||||
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
if ( is_admin() && ! isset( $wp_customize ) && 'customize.php' !== $pagenow && 'admin-ajax.php' !== $pagenow ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->add_field( 'customizer' );
|
||||
|
||||
$this->load();
|
||||
}
|
||||
|
||||
/**
|
||||
* The customizer load code
|
||||
*/
|
||||
private function load() {
|
||||
global $pagenow, $wp_customize;
|
||||
|
||||
if ( false === $this->parent->args['customizer'] ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Override the Redux_Core class.
|
||||
add_filter( "redux/extension/{$this->parent->args['opt_name']}/customizer", array( $this, 'remove_core_customizer_class' ) );
|
||||
|
||||
if ( ! isset( $wp_customize ) && 'customize.php' !== $pagenow && 'admin-ajax.php' !== $pagenow ) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::get_post_values();
|
||||
|
||||
if ( isset( $_POST['wp_customize'] ) && 'on' === $_POST['wp_customize'] ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$this->parent->args['customizer_only'] = true;
|
||||
}
|
||||
|
||||
if ( isset( $_POST['wp_customize'] ) && 'on' === $_POST['wp_customize'] && ! empty( $_POST['customized'] ) && ! isset( $_POST['action'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
add_action( "redux/options/{$this->parent->args['opt_name']}/options", array( $this, 'override_values' ), 100 );
|
||||
}
|
||||
|
||||
add_action( 'customize_register', array( $this, 'register_customizer_controls' ) ); // Create controls.
|
||||
add_action( 'wp_head', array( $this, 'customize_preview_init' ) );
|
||||
|
||||
add_action( 'customize_save_after', array( &$this, 'customizer_save_after' ) ); // After save.
|
||||
|
||||
// Add global controls CSS file.
|
||||
add_action( 'customize_controls_print_scripts', array( $this, 'enqueue_controls_css' ) );
|
||||
add_action( 'customize_controls_init', array( $this, 'enqueue_panel_css' ) );
|
||||
add_action( 'wp_enqueue_styles', array( $this, 'custom_css' ), 11 );
|
||||
|
||||
add_action( 'redux/extension/customizer/control_init', array( $this, 'create_field_classes' ), 1, 2 );
|
||||
|
||||
add_action( 'wp_ajax_' . $this->parent->args['opt_name'] . '_customizer_save', array( $this, 'customizer' ) );
|
||||
add_action( 'customize_controls_print_styles', array( $this, 'add_nonce_html' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nonce HTML for AJAX.
|
||||
*/
|
||||
public function add_nonce_html() {
|
||||
$nonce = wp_create_nonce( 'redux_customer_nonce' );
|
||||
|
||||
?>
|
||||
<div class="redux-customizer-nonce" data-nonce="<?php echo esc_attr( $nonce ); ?>"></div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX callback for customizer save...to make sanitize/validate work.
|
||||
*/
|
||||
public function customizer() {
|
||||
try {
|
||||
$return_array = array();
|
||||
|
||||
if ( isset( $_POST['nonce'] ) && wp_verify_nonce( sanitize_key( wp_unslash( $_POST['nonce'] ) ), 'redux_customer_nonce' ) && isset( $_POST['opt_name'] ) && '' !== $_POST['opt_name'] ) {
|
||||
$redux = Redux::instance( sanitize_text_field( wp_unslash( $_POST['opt_name'] ) ) );
|
||||
|
||||
$post_data = wp_unslash( $_POST['data'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
|
||||
|
||||
// New method to avoid input_var nonsense. Thanks @harunbasic.
|
||||
$values = Redux_Functions_Ex::parse_str( $post_data );
|
||||
|
||||
$all_options = get_option( sanitize_text_field( wp_unslash( $_POST['opt_name'] ) ) );
|
||||
|
||||
$values = wp_parse_args( $values, $all_options );
|
||||
|
||||
$redux->options_class->set( $redux->options_class->validate_options( $values ) );
|
||||
|
||||
$redux->enqueue_class->get_warnings_and_errors_array();
|
||||
|
||||
$return_array = array(
|
||||
'status' => 'success',
|
||||
'options' => $redux->options,
|
||||
'errors' => $redux->enqueue_class->localize_data['errors'] ?? null,
|
||||
'warnings' => $redux->enqueue_class->localize_data['warnings'] ?? null,
|
||||
'sanitize' => $redux->enqueue_class->localize_data['sanitize'] ?? null,
|
||||
);
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$return_array = array( 'status' => $e->getMessage() );
|
||||
}
|
||||
|
||||
echo wp_json_encode( $return_array );
|
||||
|
||||
die;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field classes.
|
||||
*
|
||||
* @param array $option Option.
|
||||
*/
|
||||
public function create_field_classes( array $option ) {
|
||||
if ( empty( $this->redux_fields ) ) {
|
||||
$file_paths = glob( Redux_Core::$dir . 'inc/fields/*' );
|
||||
|
||||
foreach ( $file_paths as $file ) {
|
||||
if ( 'section' !== $file && 'divide' !== $file && 'editor' !== $file ) {
|
||||
$this->redux_fields[] = str_replace( Redux_Core::$dir . 'inc/fields/', '', $file );
|
||||
}
|
||||
}
|
||||
|
||||
$file_paths = glob( Redux_Core::$dir . 'inc/extensions/*' );
|
||||
|
||||
foreach ( $file_paths as $file ) {
|
||||
if ( 'section' !== $file && 'divide' !== $file && 'editor' !== $file ) {
|
||||
$this->redux_fields[] = str_replace( Redux_Core::$dir . 'inc/extensions/', '', $file );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$class_name = 'Redux_Customizer_Control_' . $option['type'];
|
||||
|
||||
if ( ! class_exists( $class_name ) && ( in_array( $option['type'], $this->redux_fields, true ) || ( isset( $option['customizer_enabled'] ) && $option['customizer_enabled'] ) ) ) {
|
||||
$upload_dir = Redux_Core::$upload_dir;
|
||||
|
||||
if ( ! file_exists( $upload_dir . $option['type'] . '.php' ) ) {
|
||||
if ( ! is_dir( $upload_dir ) ) {
|
||||
$this->parent->filesystem->execute( 'mkdir', $upload_dir );
|
||||
}
|
||||
|
||||
$template = str_replace( '{{type}}', $option['type'], '<?php' . PHP_EOL . ' class Redux_Customizer_Control_{{type}} extends Redux_Customizer_Control {' . PHP_EOL . ' public $type = "redux-{{type}}";' . PHP_EOL . ' }' );
|
||||
|
||||
$this->parent->filesystem->execute( 'put_contents', $upload_dir . $option['type'] . '.php', array( 'content' => $template ) );
|
||||
}
|
||||
|
||||
if ( file_exists( $upload_dir . $option['type'] . '.php' ) ) {
|
||||
include_once $upload_dir . $option['type'] . '.php';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue extension scripts/styles.
|
||||
*/
|
||||
public function enqueue_controls_css() {
|
||||
$this->parent->enqueue_class->get_warnings_and_errors_array();
|
||||
$this->parent->enqueue_class->init();
|
||||
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-extension-customizer',
|
||||
$this->extension_url . 'redux-extension-customizer.css',
|
||||
array(),
|
||||
self::$version
|
||||
);
|
||||
}
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-extension-customizer',
|
||||
$this->extension_url . 'redux-extension-customizer' . Redux_Functions::is_min() . '.js',
|
||||
array( 'jquery', 'redux-js' ),
|
||||
self::$version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'redux-extension-customizer',
|
||||
'redux_customizer',
|
||||
array(
|
||||
'body_class' => sanitize_html_class( 'admin-color-' . get_user_option( 'admin_color' ), 'fresh' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue panel CSS>
|
||||
*/
|
||||
public function enqueue_panel_css() {}
|
||||
|
||||
/**
|
||||
* Remove core customizer class.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function remove_core_customizer_class(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize preview init.
|
||||
*/
|
||||
public function customize_preview_init() {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/customizer/live_preview' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get post values.
|
||||
*/
|
||||
protected static function get_post_values() {
|
||||
if ( empty( self::$post_values ) && ! empty( $_POST['customized'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
self::$post_values = json_decode( stripslashes_deep( sanitize_text_field( wp_unslash( $_POST['customized'] ) ) ), true ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override customizer values.
|
||||
*
|
||||
* @param array $data Values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function override_values( array $data ): array {
|
||||
self::get_post_values();
|
||||
|
||||
if ( isset( $_POST['customized'] ) && ! empty( self::$post_values ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
if ( is_array( self::$post_values ) ) {
|
||||
foreach ( self::$post_values as $key => $value ) {
|
||||
if ( strpos( $key, $this->parent->args['opt_name'] ) !== false ) {
|
||||
$key = str_replace( $this->parent->args['opt_name'] . '[', '', rtrim( $key, ']' ) );
|
||||
$data[ $key ] = $value;
|
||||
|
||||
$GLOBALS[ $this->parent->args['global_variable'] ][ $key ] = $value;
|
||||
$this->parent->options[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Redux fields.
|
||||
*
|
||||
* @param object $control .
|
||||
*/
|
||||
public function render( $control ) {
|
||||
$field_id = str_replace( $this->parent->args['opt_name'] . '-', '', $control->redux_id );
|
||||
$field = $this->options[ $field_id ];
|
||||
|
||||
if ( ! empty( $field['compiler'] ) ) {
|
||||
echo '<tr class="compiler">';
|
||||
} else {
|
||||
echo '<tr>';
|
||||
}
|
||||
|
||||
echo '<th scope="row">' . wp_kses_post( $this->parent->field_head[ $field['id'] ] ) . '</th>';
|
||||
echo '<td>';
|
||||
|
||||
$field['name'] = $field['id'];
|
||||
$this->parent->render_class->field_input( $field );
|
||||
|
||||
echo '</td>';
|
||||
echo '</tr>';
|
||||
}
|
||||
|
||||
// All sections, settings, and controls will be added here.
|
||||
|
||||
/**
|
||||
* Register customizer controls.
|
||||
*
|
||||
* @param WP_Customize_Manager $wp_customize .
|
||||
*
|
||||
* @throws ReflectionException Exception.
|
||||
*/
|
||||
public function register_customizer_controls( WP_Customize_Manager $wp_customize ) {
|
||||
if ( ! class_exists( 'Redux_Customizer_Section' ) ) {
|
||||
require_once __DIR__ . '/inc/class-redux-customizer-section.php';
|
||||
|
||||
if ( method_exists( $wp_customize, 'register_section_type' ) ) {
|
||||
$wp_customize->register_section_type( 'Redux_Customizer_Section' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Redux_Customizer_Panel' ) ) {
|
||||
require_once __DIR__ . '/inc/class-redux-customizer-panel.php';
|
||||
|
||||
if ( method_exists( $wp_customize, 'register_panel_type' ) ) {
|
||||
$wp_customize->register_panel_type( 'Redux_Customizer_Panel' );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'Redux_Customizer_Control' ) ) {
|
||||
require_once __DIR__ . '/inc/class-redux-customizer-control.php';
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/extension/customizer/control/includes' );
|
||||
|
||||
$order = array(
|
||||
'heading' => - 500,
|
||||
'option' => - 500,
|
||||
);
|
||||
|
||||
$panel = '';
|
||||
|
||||
$this->parent->args['options_api'] = false;
|
||||
$this->parent->options_class->register();
|
||||
|
||||
$parent_section_id = null;
|
||||
$new_parent = true;
|
||||
|
||||
foreach ( $this->parent->sections as $key => $section ) {
|
||||
// Not a type that should go on the customizer.
|
||||
if ( isset( $section['type'] ) && ( 'divide' === $section['type'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $section['id'] ) && 'import/export' === $section['id'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If section customizer is set to false.
|
||||
if ( isset( $section['customizer'] ) && false === $section['customizer'] ) {
|
||||
continue;
|
||||
}
|
||||
// if we are in a subsection and parent is set to customizer false !!!
|
||||
if ( ( isset( $section['subsection'] ) && $section['subsection'] ) ) {
|
||||
if ( $new_parent ) {
|
||||
$new_parent = false;
|
||||
$parent_section_id = ( $key - 1 );
|
||||
}
|
||||
} else { // not a subsection reset.
|
||||
$parent_section_id = null;
|
||||
$new_parent = true;
|
||||
}
|
||||
if ( isset( $parent_section_id ) && ( isset( $this->parent->sections[ $parent_section_id ]['customizer'] ) && false === $this->parent->sections[ $parent_section_id ]['customizer'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$section['permissions'] = $section['permissions'] ?? 'edit_theme_options';
|
||||
|
||||
// No errors please.
|
||||
if ( ! isset( $section['desc'] ) ) {
|
||||
$section['desc'] = '';
|
||||
}
|
||||
|
||||
// Fill the description if there is a subtitle.
|
||||
if ( empty( $section['desc'] ) && ! empty( $section['subtitle'] ) ) {
|
||||
$section['desc'] = $section['subtitle'];
|
||||
}
|
||||
|
||||
// No title is present, let's show what section is missing a title.
|
||||
if ( ! isset( $section['title'] ) ) {
|
||||
$section['title'] = '';
|
||||
}
|
||||
|
||||
// Let's make a section ID from the title.
|
||||
if ( empty( $section['id'] ) ) {
|
||||
$section['id'] = Redux_Core::strtolower( str_replace( ' ', '', $section['title'] ) );
|
||||
}
|
||||
|
||||
// Let's set a default priority.
|
||||
if ( empty( $section['priority'] ) ) {
|
||||
$section['priority'] = $order['heading'];
|
||||
++$order['heading'];
|
||||
}
|
||||
$section['id'] = $this->parent->args['opt_name'] . '-' . $section['id'];
|
||||
|
||||
if ( method_exists( $wp_customize, 'add_panel' ) && ( ! isset( $section['subsection'] ) || ( true !== $section['subsection'] ) ) && isset( $this->parent->sections[ ( $key + 1 ) ]['subsection'] ) && $this->parent->sections[ ( $key + 1 ) ]['subsection'] ) {
|
||||
$this->add_panel(
|
||||
$this->parent->args['opt_name'] . '-' . $section['id'],
|
||||
array(
|
||||
'priority' => $section['priority'],
|
||||
'capability' => $section['permissions'],
|
||||
'title' => $section['title'],
|
||||
'section' => $section,
|
||||
'opt_name' => $this->parent->args['opt_name'],
|
||||
'description' => '',
|
||||
),
|
||||
$wp_customize
|
||||
);
|
||||
|
||||
$panel = $this->parent->args['opt_name'] . '-' . $section['id'];
|
||||
|
||||
$this->add_section(
|
||||
$section['id'],
|
||||
array(
|
||||
'title' => $section['title'],
|
||||
'priority' => $section['priority'],
|
||||
'description' => $section['desc'],
|
||||
'section' => $section,
|
||||
'opt_name' => $this->parent->args['opt_name'],
|
||||
'capability' => $section['permissions'],
|
||||
'panel' => $panel,
|
||||
),
|
||||
$wp_customize
|
||||
);
|
||||
} else {
|
||||
if ( ! isset( $section['subsection'] ) || ( true !== $section['subsection'] ) ) {
|
||||
$panel = '';
|
||||
}
|
||||
|
||||
$this->add_section(
|
||||
$section['id'],
|
||||
array(
|
||||
'title' => $section['title'],
|
||||
'priority' => $section['priority'],
|
||||
'description' => $section['desc'],
|
||||
'opt_name' => $this->parent->args['opt_name'],
|
||||
'section' => $section,
|
||||
'capability' => $section['permissions'],
|
||||
'panel' => $panel,
|
||||
),
|
||||
$wp_customize
|
||||
);
|
||||
}
|
||||
|
||||
if ( ( empty( $section['fields'] ) ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ( $section['fields'] as $skey => $option ) {
|
||||
|
||||
if ( isset( $option['customizer'] ) && false === $option['customizer'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( false === $this->parent->args['customizer'] && ( ! isset( $option['customizer'] ) || true !== $option['customizer'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->options[ $option['id'] ] = $option;
|
||||
add_action( 'redux/customizer/control/render/' . $this->parent->args['opt_name'] . '-' . $option['id'], array( $this, 'render' ) );
|
||||
|
||||
$option['permissions'] = $option['permissions'] ?? 'edit_theme_options';
|
||||
|
||||
// Change the item priority if not set.
|
||||
if ( 'heading' !== $option['type'] && ! isset( $option['priority'] ) ) {
|
||||
$option['priority'] = $order['option'];
|
||||
++$order['option'];
|
||||
}
|
||||
|
||||
if ( ! empty( $this->options_defaults[ $option['id'] ] ) ) {
|
||||
$option['default'] = $this->options_defaults['option']['id'];
|
||||
}
|
||||
|
||||
if ( ! isset( $option['default'] ) ) {
|
||||
$option['default'] = '';
|
||||
}
|
||||
if ( ! isset( $option['title'] ) ) {
|
||||
$option['title'] = '';
|
||||
}
|
||||
|
||||
$option['id'] = $this->parent->args['opt_name'] . '[' . $option['id'] . ']';
|
||||
|
||||
if ( 'heading' !== $option['type'] && 'import_export' !== $option['type'] && ! empty( $option['type'] ) ) {
|
||||
|
||||
$wp_customize->add_setting(
|
||||
$option['id'],
|
||||
array(
|
||||
'default' => $option['default'],
|
||||
'transport' => 'refresh',
|
||||
'opt_name' => $this->parent->args['opt_name'],
|
||||
'sanitize_callback' => array( $this, 'field_validation' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( ! empty( $option['data'] ) && empty( $option['options'] ) ) {
|
||||
if ( empty( $option['args'] ) ) {
|
||||
$option['args'] = array();
|
||||
}
|
||||
|
||||
if ( 'elusive-icons' === $option['data'] || 'elusive-icon' === $option['data'] || 'elusive' === $option['data'] ) {
|
||||
$icons_file = Redux_Core::$dir . 'inc/fields/select/elusive-icons.php';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$icons_file = apply_filters( 'redux-font-icons-file', $icons_file );
|
||||
|
||||
if ( file_exists( $icons_file ) ) {
|
||||
require_once $icons_file;
|
||||
}
|
||||
}
|
||||
$option['options'] = $this->parent->wordpress_data->get( $option['data'], $option['args'] );
|
||||
}
|
||||
|
||||
$class_name = 'Redux_Customizer_Control_' . $option['type'];
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/extension/customizer/control_init', $option );
|
||||
|
||||
if ( ! class_exists( $class_name ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$wp_customize->add_control(
|
||||
new $class_name(
|
||||
$wp_customize,
|
||||
$option['id'],
|
||||
array(
|
||||
'label' => $option['title'],
|
||||
'section' => $section['id'],
|
||||
'settings' => $option['id'],
|
||||
'type' => 'redux-' . $option['type'],
|
||||
'field' => $option,
|
||||
'ReduxFramework' => $this->parent,
|
||||
'active_callback' => ( isset( $option['required'] ) && class_exists( 'Redux_Customizer_Active_Callback' ) ) ? array(
|
||||
'Redux_Customizer_Active_Callback',
|
||||
'evaluate',
|
||||
) : '__return_true',
|
||||
'priority' => $option['priority'],
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$section['fields'][ $skey ]['name'] = $option['id'];
|
||||
if ( ! isset( $section['fields'][ $skey ]['class'] ) ) { // No errors please.
|
||||
$section['fields'][ $skey ]['class'] = '';
|
||||
}
|
||||
|
||||
$this->controls[ $section['fields'][ $skey ]['id'] ] = $section['fields'][ $skey ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add customizer section.
|
||||
*
|
||||
* @param string $id ID.
|
||||
* @param array $args Args.
|
||||
* @param WP_Customize_Manager $wp_customize .
|
||||
*/
|
||||
public function add_section( string $id, array $args, WP_Customize_Manager $wp_customize ) {
|
||||
|
||||
if ( is_a( $id, 'WP_Customize_Section' ) ) {
|
||||
$section = $id;
|
||||
} else {
|
||||
$section = new Redux_Customizer_Section( $wp_customize, $id, $args );
|
||||
}
|
||||
|
||||
$wp_customize->add_section( $section, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a customize panel.
|
||||
*
|
||||
* @param WP_Customize_Panel|string $id Customize Panel object, or Panel ID.
|
||||
* @param array $args Optional. Panel arguments. Default empty array.
|
||||
* @param WP_Customize_Manager $wp_customize .
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function add_panel( $id, array $args, WP_Customize_Manager $wp_customize ) {
|
||||
if ( is_a( $id, 'WP_Customize_Panel' ) ) {
|
||||
$panel = $id;
|
||||
} else {
|
||||
$panel = new Redux_Customizer_Panel( $wp_customize, $id, $args );
|
||||
}
|
||||
|
||||
$wp_customize->add_panel( $panel, $args );
|
||||
}
|
||||
|
||||
/**
|
||||
* Actions to take after customizer save.
|
||||
*
|
||||
* @throws ReflectionException Exception.
|
||||
*/
|
||||
public function customizer_save_after() {
|
||||
if ( empty( $this->parent->options ) ) {
|
||||
$this->parent->get_options();
|
||||
}
|
||||
|
||||
if ( empty( $this->orig_options ) && ! empty( $this->parent->options ) ) {
|
||||
$this->orig_options = $this->parent->options;
|
||||
}
|
||||
|
||||
if ( isset( $_POST['customized'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
|
||||
$options = json_decode( sanitize_text_field( wp_unslash( $_POST['customized'] ) ), true ); // phpcs:ignore WordPress.Security.NonceVerification
|
||||
|
||||
$compiler = false;
|
||||
$changed = false;
|
||||
|
||||
foreach ( $options as $key => $value ) {
|
||||
if ( strpos( $key, $this->parent->args['opt_name'] ) !== false ) {
|
||||
$key = str_replace( $this->parent->args['opt_name'] . '[', '', rtrim( $key, ']' ) );
|
||||
|
||||
if ( ! isset( $this->orig_options[ $key ] ) || $value !== $this->orig_options[ $key ] || ( isset( $this->orig_options[ $key ] ) && ! empty( $this->orig_options[ $key ] ) && empty( $value ) ) ) {
|
||||
$this->parent->options[ $key ] = $value;
|
||||
$changed = true;
|
||||
|
||||
if ( isset( $this->parent->compiler_fields[ $key ] ) ) {
|
||||
$compiler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( $changed ) {
|
||||
$this->parent->options_class->set( $this->parent->options );
|
||||
if ( $compiler ) {
|
||||
// Have to set this to stop the output of the CSS and typography stuff.
|
||||
$this->parent->no_output = true;
|
||||
$this->parent->output_class->enqueue();
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/compiler", $this->parent->options, $this->parent->compilerCSS );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/options/{$this->parent->args['opt_name']}/compiler/advanced", $this->parent );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue CSS/JS for the customizer controls
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @global $wp_styles
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
$localize = array(
|
||||
'save_pending' => esc_html__( 'You have changes that are not saved. Would you like to save them now?', 'redux-framework' ),
|
||||
'reset_confirm' => esc_html__( 'Are you sure? Resetting will lose all custom values.', 'redux-framework' ),
|
||||
'preset_confirm' => esc_html__( 'Your current options will be replaced with the values of this preset. Would you like to proceed?', 'redux-framework' ),
|
||||
'opt_name' => $this->parent->args['opt_name'],
|
||||
'field' => $this->parent->options,
|
||||
'defaults' => $this->parent->options_defaults,
|
||||
'folds' => $this->parent->folds,
|
||||
);
|
||||
|
||||
// Values used by the javascript.
|
||||
wp_localize_script( 'redux-js', 'redux_opts', $localize );
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux-enqueue-' . $this->parent->args['opt_name'] );
|
||||
|
||||
foreach ( $this->parent->sections as $section ) {
|
||||
if ( isset( $section['fields'] ) ) {
|
||||
foreach ( $section['fields'] as $field ) {
|
||||
if ( isset( $field['type'] ) ) {
|
||||
$field_classes = array( 'Redux_' . $field['type'], 'ReduxFramework_' . $field['type'] );
|
||||
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
|
||||
if ( false === $field_class ) {
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$class_file = apply_filters( 'redux-typeclass-load', $this->path . 'inc/fields/' . $field['type'] . '/field_' . $field['type'] . '.php', $field_class );
|
||||
|
||||
if ( $class_file ) {
|
||||
require_once $class_file;
|
||||
|
||||
$field_class = Redux_Functions::class_exists_ex( $field_classes );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ( class_exists( $field_class ) && method_exists( $field_class, 'enqueue' ) ) {
|
||||
$enqueue = new $field_class( '', '', $this );
|
||||
$enqueue->enqueue();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Option for use
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function register_setting() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the options before insertion
|
||||
*
|
||||
* @param array|string $value The options array.
|
||||
*
|
||||
* @return array|string $value
|
||||
* @since 3.0.0
|
||||
* @access public
|
||||
*/
|
||||
public function field_validation( $value ) {
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'redux_customizer_custom_validation' ) ) {
|
||||
/**
|
||||
* Custom validation.
|
||||
*
|
||||
* @param mixed $field Field.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
function redux_customizer_custom_validation( $field ) {
|
||||
return $field;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'ReduxFramework_extension_customizer' ) ) {
|
||||
class_alias( 'Redux_Extension_Customizer', 'ReduxFramework_extension_customizer' );
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Customizer Control.
|
||||
*
|
||||
* @package Redux Framework/Extensions
|
||||
* @version 3.5
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Customizer_Control', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Customizer_Control
|
||||
*/
|
||||
class Redux_Customizer_Control extends WP_Customize_Control {
|
||||
|
||||
/**
|
||||
* Redux ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $redux_id = '';
|
||||
|
||||
/**
|
||||
* Field render.
|
||||
*/
|
||||
public function render() {
|
||||
|
||||
$this->redux_id = str_replace( 'customize-control-', '', 'customize-control-' . str_replace( '[', '-', str_replace( ']', '', $this->id ) ) );
|
||||
$class = 'customize-control redux-group-tab redux-field customize-control-' . $this->type;
|
||||
$opt_name_arr = explode( '[', $this->id );
|
||||
$opt_name = $opt_name_arr[0];
|
||||
$field_id = str_replace( ']', '', $opt_name_arr[1] );
|
||||
|
||||
$section = Redux_Helpers::section_from_field_id( $opt_name, $field_id );
|
||||
|
||||
if ( isset( $section['disabled'] ) && true === $section['disabled'] ) {
|
||||
$class .= ' disabled';
|
||||
}
|
||||
|
||||
if ( isset( $section['hidden'] ) && true === $section['hidden'] ) {
|
||||
$class .= ' hidden';
|
||||
}
|
||||
|
||||
?>
|
||||
<li id="<?php echo esc_attr( $this->redux_id ); ?>-li" class="<?php echo esc_attr( $class ); ?>">
|
||||
<?php if ( 'repeater' !== $this->type ) { ?>
|
||||
<input
|
||||
type="hidden"
|
||||
data-id="<?php echo esc_attr( $this->id ); ?>"
|
||||
data-key="<?php echo esc_attr( str_replace( $opt_name . '-', '', $this->redux_id ) ); ?>"
|
||||
class="redux-customizer-input"
|
||||
id="customizer_control_id_<?php echo esc_attr( $this->redux_id ); ?>" <?php echo esc_url( $this->get_link() ); ?>
|
||||
value=""/>
|
||||
<?php } ?>
|
||||
<?php $this->render_content(); ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render content hook.
|
||||
*/
|
||||
public function render_content() {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( 'redux/customizer/control/render/' . $this->redux_id, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* Label output.
|
||||
*/
|
||||
public function label() {
|
||||
// The label has already been sanitized in the Fields class, no need to re-sanitize it.
|
||||
echo( $this->label ); // phpcs:ignore WordPress.Security.EscapeOutput
|
||||
}
|
||||
|
||||
/**
|
||||
* Description output.
|
||||
*/
|
||||
public function description() {
|
||||
if ( ! empty( $this->description ) ) {
|
||||
// The description has already been sanitized in the Fields class, no need to re-sanitize it.
|
||||
echo '<span class="description customize-control-description">' . esc_html( $this->description ) . '</span>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Title output.
|
||||
*/
|
||||
public function title() {
|
||||
echo '<span class="customize-control-title">';
|
||||
$this->label();
|
||||
$this->description();
|
||||
echo '</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Customizer Panel Class
|
||||
*
|
||||
* @class Redux_Customizer_Panel
|
||||
* @version 4.0.0
|
||||
* @package Redux Framework/Extentions
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Customizer section representing widget area (sidebar).
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Customize
|
||||
* @since 4.1.0
|
||||
* @see WP_Customize_Section
|
||||
*/
|
||||
class Redux_Customizer_Panel extends WP_Customize_Panel {
|
||||
|
||||
/**
|
||||
* Type of this panel.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'redux';
|
||||
|
||||
/**
|
||||
* Panel opt_name.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $opt_name = '';
|
||||
|
||||
/**
|
||||
* Section array.
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
public $section = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Any supplied $args override class property defaults.
|
||||
*
|
||||
* @since 4.0.0
|
||||
*
|
||||
* @param WP_Customize_Manager $manager Customizer bootstrap instance.
|
||||
* @param string $id A specific ID for the panel.
|
||||
* @param array $args Panel arguments.
|
||||
*/
|
||||
public function __construct( $manager, $id, $args = array() ) {
|
||||
parent::__construct( $manager, $id, $args );
|
||||
|
||||
// Redux addition.
|
||||
if ( isset( $args['section'] ) ) {
|
||||
$this->section = $args['section'];
|
||||
$this->description = $this->section['desc'] ?? '';
|
||||
$this->opt_name = $args['opt_name'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WP < 4.3 Render
|
||||
*
|
||||
* @since
|
||||
* @access protected
|
||||
*/
|
||||
protected function render() {
|
||||
global $wp_version;
|
||||
$version = explode( '-', $wp_version );
|
||||
if ( version_compare( $version[0], '4.3', '<' ) ) {
|
||||
$this->render_fallback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render.
|
||||
*/
|
||||
protected function render_fallback() {
|
||||
$classes = 'accordion-section redux-main redux-panel control-section control-panel control-panel-' . esc_attr( $this->type );
|
||||
|
||||
?>
|
||||
<li id="accordion-panel-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>"
|
||||
data-width="<?php echo isset( $this->section['customizer_width'] ) ? esc_attr( $this->section['customizer_width'] ) : ''; ?>">
|
||||
<h3 class="accordion-section-title" tabindex="0">
|
||||
<?php if ( isset( $this->section['icon'] ) && ! empty( $this->section['icon'] ) ) : ?>
|
||||
<i class="<?php echo esc_attr( $this->section['icon'] ); ?>"></i>
|
||||
<?php endif; ?>
|
||||
<?php
|
||||
echo wp_kses(
|
||||
$this->title,
|
||||
array(
|
||||
'em' => array(),
|
||||
'i' => array(),
|
||||
'strong' => array(),
|
||||
'span' => array(
|
||||
'class' => array(),
|
||||
'style' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
<span class="screen-reader-text"><?php esc_html_e( 'Press return or enter to open this panel', 'redux-framework' ); ?></span>
|
||||
</h3>
|
||||
<ul class="accordion-sub-container control-panel-content">
|
||||
<table class="form-table">
|
||||
<tbody><?php $this->render_content(); ?></tbody>
|
||||
</table>
|
||||
</ul>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the sections that have been added to the panel.
|
||||
*
|
||||
* @since 4.1.0
|
||||
* @access protected
|
||||
*/
|
||||
protected function render_content() {
|
||||
?>
|
||||
<li class="panel-meta accordion-section redux-panel redux-panel-meta control-section
|
||||
<?php
|
||||
if ( empty( $this->description ) ) {
|
||||
echo ' cannot-expand';
|
||||
}
|
||||
?>
|
||||
">
|
||||
<div class="accordion-section-title" tabindex="0">
|
||||
<span class="preview-notice">
|
||||
<?php /* translators: %s is the site/panel title in the Customizer */ ?>
|
||||
<?php printf( esc_html__( 'You are customizing', 'redux-framework' ) . ' %s', '<strong class="panel-title">' . esc_html( $this->title ) . '</strong>' ); ?>
|
||||
</span>
|
||||
</div>
|
||||
<?php if ( ! empty( $this->description ) ) { ?>
|
||||
<div class="accordion-section-content description legacy">
|
||||
<?php echo wp_kses_post( $this->description ); ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function json(): array {
|
||||
$array = wp_array_slice_assoc(
|
||||
parent::json(),
|
||||
array(
|
||||
'id',
|
||||
'title',
|
||||
'description',
|
||||
'priority',
|
||||
'type',
|
||||
)
|
||||
);
|
||||
|
||||
$array['content'] = $this->get_content();
|
||||
$array['active'] = $this->active();
|
||||
$array['instanceNumber'] = $this->instance_number;
|
||||
|
||||
// BEGIN Redux Additions.
|
||||
$array['width'] = $this->section['customizer_width'] ?? '';
|
||||
$array['icon'] = ( isset( $this->section['icon'] ) && ! empty( $this->section['icon'] ) ) ? $this->section['icon'] : 'hide';
|
||||
|
||||
$array['opt_name'] = $this->opt_name;
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Underscore (JS) template for this panel's content (but not its container).
|
||||
* Class variables for this panel class are available in the `data` JS object;
|
||||
* export custom variables by overriding {@see WP_Customize_Panel::json()}.
|
||||
*
|
||||
* @see WP_Customize_Panel::print_template()
|
||||
* @since 4.3.0
|
||||
*/
|
||||
protected function content_template() {
|
||||
?>
|
||||
<li
|
||||
class="panel-meta customize-info redux-customizer-opt-name redux-panel accordion-section <# if ( ! data.description ) { #> cannot-expand<# } #>"
|
||||
data-opt-name="{{{ data.opt_name }}}">
|
||||
<button class="customize-panel-back" tabindex="-1">
|
||||
<span class="screen-reader-text"><?php esc_attr_e( 'Back', 'redux-framework' ); ?></span></button>
|
||||
<div class="accordion-section-title">
|
||||
<span class="preview-notice">
|
||||
<?php /* translators: %s is the site/panel title in the Customizer */ ?>
|
||||
<?php printf( esc_html__( 'You are customizing', 'redux-framework' ) . ' %s', '<strong class="panel-title">{{ data.title }}</strong>' ); ?>
|
||||
</span>
|
||||
<# if ( data.description ) { #>
|
||||
<button
|
||||
class="customize-help-toggle dashicons dashicons-editor-help"
|
||||
tabindex="0"
|
||||
aria-expanded="false">
|
||||
<span class="screen-reader-text"><?php esc_attr_e( 'Help', 'redux-framework' ); ?></span></button>
|
||||
<# } #>
|
||||
</div>
|
||||
<# if ( data.description ) { #>
|
||||
<div class="description customize-panel-description">
|
||||
{{{ data.description }}}
|
||||
</div>
|
||||
<# } #>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* An Underscore (JS) template for rendering this panel's container.
|
||||
* Class variables for this panel class are available in the `data` JS object;
|
||||
* export custom variables by overriding {@see WP_Customize_Panel::json()}.
|
||||
*
|
||||
* @see WP_Customize_Panel::print_template()
|
||||
* @since 4.3.0
|
||||
*/
|
||||
protected function render_template() {
|
||||
?>
|
||||
<li id="accordion-panel-{{ data.id }}"
|
||||
class="accordion-section redux-panel control-section control-panel control-panel-{{ data.type }}"
|
||||
data-width="{{ data.width }}">
|
||||
<h3 class="accordion-section-title" tabindex="0">
|
||||
<# if ( data.icon ) { #><i class="{{ data.icon }}"></i> <# } #>{{ data.title }}
|
||||
<span class="screen-reader-text"><?php echo esc_html__( 'Press return or enter to open this panel', 'redux-framework' ); ?></span>
|
||||
</h3>
|
||||
<ul class="accordion-sub-container control-panel-content"></ul>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
/**
|
||||
* Customizer section representing widget area (sidebar).
|
||||
*
|
||||
* @package WordPress
|
||||
* @subpackage Customize
|
||||
* @since 4.0.0
|
||||
* @see WP_Customize_Section
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* Class Redux_Customizer_Section
|
||||
*/
|
||||
class Redux_Customizer_Section extends WP_Customize_Section {
|
||||
|
||||
/**
|
||||
* Type of this section.
|
||||
*
|
||||
* @since 4.1.0
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $type = 'redux';
|
||||
|
||||
/**
|
||||
* Panel opt_name.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @access public
|
||||
* @var string
|
||||
*/
|
||||
public $opt_name = '';
|
||||
|
||||
/**
|
||||
* Section array.
|
||||
*
|
||||
* @var array|mixed
|
||||
*/
|
||||
public $section = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* Any supplied $args override class property defaults.
|
||||
*
|
||||
* @since 3.4.0
|
||||
*
|
||||
* @param WP_Customize_Manager $manager Customizer bootstrap instance.
|
||||
* @param string $id A specific ID of the section.
|
||||
* @param array $args Section arguments.
|
||||
*/
|
||||
public function __construct( $manager, $id, $args = array() ) {
|
||||
parent::__construct( $manager, $id, $args );
|
||||
// Redux addition.
|
||||
if ( isset( $args['section'] ) ) {
|
||||
$this->section = $args['section'];
|
||||
$this->description = $this->section['desc'] ?? '';
|
||||
$this->opt_name = $args['opt_name'] ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* WP < 4.3 Render
|
||||
*/
|
||||
protected function render() {
|
||||
global $wp_version;
|
||||
$version = explode( '-', $wp_version );
|
||||
if ( version_compare( $version[0], '4.3', '<' ) ) {
|
||||
$this->render_fallback();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the section, and the controls that have been added to it.
|
||||
*
|
||||
* @since 3.4.0
|
||||
*/
|
||||
protected function render_fallback() {
|
||||
$classes = 'accordion-section redux-section control-section control-section-' . $this->type;
|
||||
?>
|
||||
<li id="accordion-section-<?php echo esc_attr( $this->id ); ?>" class="<?php echo esc_attr( $classes ); ?>">
|
||||
<h3 class="accordion-section-title" tabindex="0">
|
||||
<?php
|
||||
echo wp_kses(
|
||||
$this->title,
|
||||
array(
|
||||
'em' => array(),
|
||||
'i' => array(),
|
||||
'strong' => array(),
|
||||
'span' => array(
|
||||
'class' => array(),
|
||||
'style' => array(),
|
||||
),
|
||||
)
|
||||
);
|
||||
?>
|
||||
<span class="screen-reader-text"><?php esc_attr_e( 'Press return or enter to expand', 'redux-framework' ); ?></span>
|
||||
</h3>
|
||||
<ul class="accordion-section-content redux-main">
|
||||
<?php
|
||||
if ( isset( $this->opt_name ) && isset( $this->section ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/page/$this->opt_name/section/before", $this->section );
|
||||
}
|
||||
?>
|
||||
<?php if ( ! empty( $this->description ) ) { ?>
|
||||
<li class="customize-section-description-container">
|
||||
<p class="description customize-section-description legacy"><?php echo wp_kses_post( $this->description ); ?></p>
|
||||
</li>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gather the parameters passed to client JavaScript via JSON.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*
|
||||
* @return array The array to be exported to the client as JSON.
|
||||
*/
|
||||
public function json(): array {
|
||||
$array = wp_array_slice_assoc(
|
||||
parent::json(),
|
||||
array(
|
||||
'id',
|
||||
'title',
|
||||
'description',
|
||||
'priority',
|
||||
'panel',
|
||||
'type',
|
||||
)
|
||||
);
|
||||
|
||||
$array['content'] = $this->get_content();
|
||||
$array['active'] = $this->active();
|
||||
$array['instanceNumber'] = $this->instance_number;
|
||||
|
||||
if ( $this->panel ) {
|
||||
/* translators: ▸ is the unicode right-pointing triangle, and %s is the section title in the Customizer */
|
||||
$array['customizeAction'] = sprintf( __( 'Customizing ▸ %s', 'redux-framework' ), esc_html( $this->manager->get_panel( $this->panel )->title ) );
|
||||
} else {
|
||||
$array['customizeAction'] = __( 'Customizing', 'redux-framework' );
|
||||
}
|
||||
|
||||
// BEGIN Redux Additions.
|
||||
$array['width'] = $this->section['customizer_width'] ?? '';
|
||||
$array['icon'] = ( isset( $this->section['icon'] ) && ! empty( $this->section['icon'] ) ) ? $this->section['icon'] : 'hide';
|
||||
|
||||
$array['opt_name'] = $this->opt_name;
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* An Underscore (JS) template for rendering this section.
|
||||
* Class variables for this section class are available in the `data` JS object;
|
||||
* export custom variables by overriding {@see WP_Customize_Section::json()}.
|
||||
*
|
||||
* @see WP_Customize_Section::print_template()
|
||||
* @since 4.3.0
|
||||
*/
|
||||
protected function render_template() {
|
||||
|
||||
?>
|
||||
<li id="accordion-section-{{ data.id }}"
|
||||
class="redux-standalone-section redux-customizer-opt-name redux-section accordion-section control-section control-section-{{ data.type }}"
|
||||
data-opt-name="{{ data.opt_name }}"
|
||||
data-width="{{ data.width }}">
|
||||
<h3 class="accordion-section-title" tabindex="0">
|
||||
<# if ( data.icon ) { #><i class="{{ data.icon }}"></i> <# } #>{{ data.title }}
|
||||
<span class="screen-reader-text"><?php esc_html_e( 'Press return or enter to open', 'redux-framework' ); ?></span>
|
||||
</h3>
|
||||
<ul class="accordion-section-content redux-main">
|
||||
<li class="customize-section-description-container">
|
||||
<div class="customize-section-title">
|
||||
<button class="customize-section-back" tabindex="-1">
|
||||
<span class="screen-reader-text"><?php esc_html_e( 'Back', 'redux-framework' ); ?></span>
|
||||
</button>
|
||||
<h3>
|
||||
<span class="customize-action">
|
||||
{{{ data.customizeAction }}}
|
||||
</span> {{ data.title }}
|
||||
</h3>
|
||||
</div>
|
||||
<# if ( data.description ) { #>
|
||||
<p class="description customize-section-description">{{{ data.description }}}</p>
|
||||
<# } #>
|
||||
<?php
|
||||
if ( isset( $this->opt_name ) && isset( $this->section ) ) {
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
do_action( "redux/page/$this->opt_name/section/before", $this->section );
|
||||
}
|
||||
?>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Customizer Shim.
|
||||
*
|
||||
* Shim for the old way of calling the customizer.
|
||||
*
|
||||
* @package Redux
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
require_once __DIR__ . '/class-redux-customizer-panel.php';
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Customizer Shim.
|
||||
*
|
||||
* Shim for the old way of calling the customizer.
|
||||
*
|
||||
* @package Redux
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
require_once __DIR__ . '/class-redux-customizer-section.php';
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,59 @@
|
||||
.wp-customizer .redux-container { overflow: visible; }
|
||||
|
||||
.wp-customizer .redux-container .redux-main input { margin: 0 !important; }
|
||||
|
||||
.wp-customizer .redux-container .redux-main input.spinner-input { margin-right: 30px !important; margin-left: 30px !important; margin-top: 0 !important; }
|
||||
|
||||
.wp-customizer .redux-container .redux-main .redux-container-editor .wp-editor-area { color: #000000; }
|
||||
|
||||
.wp-customizer .redux-section.open .redux-group-tab { display: block !important; }
|
||||
|
||||
.wp-customizer .redux-section.open .redux-group-tab.hide { display: none !important; }
|
||||
|
||||
.wp-customizer .redux-section p.customize-section-description { margin-top: 22px; word-break: break-word; }
|
||||
|
||||
.wp-customizer .redux-section p.customize-section-description.legacy { margin-top: 7px; }
|
||||
|
||||
.wp-customizer .control-section-themes .accordion-section-title { margin: 0; }
|
||||
|
||||
.wp-customizer #customize-controls .description { display: block; }
|
||||
|
||||
.wp-customizer #customize-controls .customize-info { margin-bottom: 0; }
|
||||
|
||||
.wp-customizer #customize-controls .redux-section .accordion-section-content { background: #fcfcfc; }
|
||||
|
||||
.wp-customizer .redux-section .accordion-section-title i, .wp-customizer .redux-field .accordion-field-title i, .wp-customizer .redux-panel .accordion-section-title i { margin-right: 5px; }
|
||||
|
||||
.wp-customizer .accordion-section.redux-main { background: inherit; margin-left: inherit; border-left: inherit; -moz-box-shadow: inherit; -webkit-box-shadow: inherit; padding: inherit; box-shadow: inherit; }
|
||||
|
||||
.wp-customizer .redux_field_th { padding: 13px 0 0 0; }
|
||||
|
||||
.wp-customizer .redux-main .redux-field-container { padding: 10px 0; }
|
||||
|
||||
.wp-customizer .redux-main .select_wrapper { float: none; width: 100%; display: inline-block; }
|
||||
|
||||
.wp-customizer .redux-main .select2-container { margin-right: 0 !important; margin-bottom: 5px !important; width: 100% !important; }
|
||||
|
||||
.wp-customizer .redux-main .select_wrapper:nth-child(odd) { margin-right: 0; }
|
||||
|
||||
.wp-customizer .redux-main .redux-option-image { max-width: 42% !important; margin-right: 3%; }
|
||||
|
||||
.wp-customizer .redux-main .customize-control { border-bottom: 1px solid #ddd; padding-bottom: 4px; }
|
||||
|
||||
.wp-customizer .redux-main .customize-control:last-child { border-bottom: 0; padding-bottom: 0; }
|
||||
|
||||
.wp-customizer .redux-main .upload { width: 100% !important; }
|
||||
|
||||
.wp-customizer .redux-main h3 { margin-top: inherit; }
|
||||
|
||||
.wp-customizer .redux-main .redux-container-raw { margin-top: 22px; word-break: break-word; padding: 0 !important; }
|
||||
|
||||
.wp-customizer .redux-main .redux-container-password input { width: 100%; }
|
||||
|
||||
.wp-customizer .select2-drop, .wp-customizer .select2-container { z-index: 999999; }
|
||||
|
||||
.wp-customizer .customize-control-redux-raw { list-style: none; }
|
||||
|
||||
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtZXh0ZW5zaW9uLWN1c3RvbWl6ZXIuY3NzIiwic291cmNlcyI6WyJyZWR1eC1leHRlbnNpb24tY3VzdG9taXplci5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEFBQ0ksY0FEVSxDQUNWLGdCQUFnQixDQUFDLEVBQ2IsUUFBUSxFQUFFLE9BQU8sR0FrQnBCOztBQXBCTCxBQUlZLGNBSkUsQ0FDVixnQkFBZ0IsQ0FFWixXQUFXLENBQ1AsS0FBSyxDQUFDLEVBQ0YsTUFBTSxFQUFFLFlBQVksR0FDdkI7O0FBTmIsQUFRWSxjQVJFLENBQ1YsZ0JBQWdCLENBRVosV0FBVyxDQUtQLEtBQUssQUFBQSxjQUFjLENBQUMsRUFDaEIsWUFBWSxFQUFFLGVBQWUsRUFDN0IsV0FBVyxFQUFFLGVBQWUsRUFDNUIsVUFBVSxFQUFFLFlBQVksR0FDM0I7O0FBWmIsQUFlZ0IsY0FmRixDQUNWLGdCQUFnQixDQUVaLFdBQVcsQ0FXUCx1QkFBdUIsQ0FDbkIsZUFBZSxDQUFDLEVBQ1osS0FBSyxFQUFDLE9BQU8sR0FDaEI7O0FBakJqQixBQXNCSSxjQXRCVSxDQXNCVixjQUFjLEFBQUEsS0FBSyxDQUFDLGdCQUFnQixDQUFDLEVBQ2pDLE9BQU8sRUFBRSxnQkFBZ0IsR0FLNUI7O0FBNUJMLEFBeUJRLGNBekJNLENBc0JWLGNBQWMsQUFBQSxLQUFLLENBQUMsZ0JBQWdCLEFBRy9CLEtBQUssQ0FBQyxFQUNILE9BQU8sRUFBQyxJQUFJLENBQUEsVUFBVSxHQUN6Qjs7QUEzQlQsQUErQlEsY0EvQk0sQ0E4QlYsY0FBYyxDQUNWLENBQUMsQUFBQSw4QkFBOEIsQ0FBQyxFQUM1QixVQUFVLEVBQUUsSUFBSSxFQUNoQixVQUFVLEVBQUUsVUFBVSxHQUl6Qjs7QUFyQ1QsQUFrQ1ksY0FsQ0UsQ0E4QlYsY0FBYyxDQUNWLENBQUMsQUFBQSw4QkFBOEIsQUFHMUIsT0FBTyxDQUFDLEVBQ0wsVUFBVSxFQUFFLEdBQUcsR0FDbEI7O0FBcENiLEFBd0NJLGNBeENVLENBd0NWLHVCQUF1QixDQUFDLHdCQUF3QixDQUFDLEVBQzdDLE1BQU0sRUFBRSxDQUFDLEdBQ1o7O0FBMUNMLEFBNkNRLGNBN0NNLENBNENWLG1CQUFtQixDQUNmLFlBQVksQ0FBQyxFQUNULE9BQU8sRUFBRSxLQUFLLEdBQ2pCOztBQS9DVCxBQWdEUSxjQWhETSxDQTRDVixtQkFBbUIsQ0FJZixlQUFlLENBQUMsRUFDWixhQUFhLEVBQUUsQ0FBQyxHQUNuQjs7QUFsRFQsQUFtRFEsY0FuRE0sQ0E0Q1YsbUJBQW1CLENBT2YsY0FBYyxDQUFDLDBCQUEwQixDQUFDLEVBQ3RDLFVBQVUsRUFBRSxPQUFPLEdBQ3RCOztBQXJEVCxBQXdESSxjQXhEVSxDQXdEVixjQUFjLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxFQXhEN0MsY0FBYyxDQXlEVixZQUFZLENBQUMsc0JBQXNCLENBQUMsQ0FBQyxFQXpEekMsY0FBYyxDQTBEVixZQUFZLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDLEVBQ3BDLFlBQVksRUFBRSxHQUFHLEdBQ3BCOztBQTVETCxBQThESSxjQTlEVSxDQThEVixrQkFBa0IsQUFBQSxXQUFXLENBQUMsRUFDMUIsVUFBVSxFQUFFLE9BQU8sRUFDbkIsV0FBVyxFQUFFLE9BQU8sRUFDcEIsV0FBVyxFQUFFLE9BQU8sRUFDcEIsZUFBZSxFQUFFLE9BQU8sRUFDeEIsa0JBQWtCLEVBQUUsT0FBTyxFQUMzQixPQUFPLEVBQUUsT0FBTyxFQUNoQixVQUFVLEVBQUUsT0FBTyxHQUN0Qjs7QUF0RUwsQUF3RUksY0F4RVUsQ0F3RVYsZUFBZSxDQUFDLEVBQ1osT0FBTyxFQUFFLFVBQVUsR0FDdEI7O0FBMUVMLEFBNkVRLGNBN0VNLENBNEVWLFdBQVcsQ0FDUCxzQkFBc0IsQ0FBQyxFQUNuQixPQUFPLEVBQUUsTUFBTSxHQUNsQjs7QUEvRVQsQUFnRlEsY0FoRk0sQ0E0RVYsV0FBVyxDQUlQLGVBQWUsQ0FBQyxFQUNaLEtBQUssRUFBRSxJQUFJLEVBQ1gsS0FBSyxFQUFFLElBQUksRUFDWCxPQUFPLEVBQUUsWUFBWSxHQUN4Qjs7QUFwRlQsQUFxRlEsY0FyRk0sQ0E0RVYsV0FBVyxDQVNQLGtCQUFrQixDQUFDLEVBQ2YsWUFBWSxFQUFFLFlBQVksRUFDMUIsYUFBYSxFQUFFLGNBQWMsRUFDN0IsS0FBSyxFQUFFLGVBQWUsR0FDekI7O0FBekZULEFBMEZRLGNBMUZNLENBNEVWLFdBQVcsQ0FjUCxlQUFlLEFBQUEsVUFBVyxDQUFBLEdBQUcsRUFBRSxFQUMzQixZQUFZLEVBQUUsQ0FBQyxHQUNsQjs7QUE1RlQsQUE2RlEsY0E3Rk0sQ0E0RVYsV0FBVyxDQWlCUCxtQkFBbUIsQ0FBQyxFQUNoQixTQUFTLEVBQUUsY0FBYyxFQUN6QixZQUFZLEVBQUUsRUFBRSxHQUNuQjs7QUFoR1QsQUFpR1EsY0FqR00sQ0E0RVYsV0FBVyxDQXFCUCxrQkFBa0IsQ0FBQyxFQUNmLGFBQWEsRUFBRSxjQUFjLEVBQzdCLGNBQWMsRUFBRSxHQUFHLEdBQ3RCOztBQXBHVCxBQXFHUSxjQXJHTSxDQTRFVixXQUFXLENBeUJQLGtCQUFrQixBQUFBLFdBQVcsQ0FBQyxFQUMxQixhQUFhLEVBQUUsQ0FBQyxFQUNoQixjQUFjLEVBQUUsQ0FBQyxHQUNwQjs7QUF4R1QsQUF5R1EsY0F6R00sQ0E0RVYsV0FBVyxDQTZCUCxPQUFPLENBQUMsRUFDSixLQUFLLEVBQUUsZUFBZSxHQUN6Qjs7QUEzR1QsQUE0R1EsY0E1R00sQ0E0RVYsV0FBVyxDQWdDUCxFQUFFLENBQUMsRUFDQyxVQUFVLEVBQUUsT0FBTyxHQUN0Qjs7QUE5R1QsQUErR1EsY0EvR00sQ0E0RVYsV0FBVyxDQW1DUCxvQkFBb0IsQ0FBQyxFQUNqQixVQUFVLEVBQUUsSUFBSSxFQUNoQixVQUFVLEVBQUUsVUFBVSxFQUN0QixPQUFPLEVBQUUsWUFBWSxHQUN4Qjs7QUFuSFQsQUFvSFEsY0FwSE0sQ0E0RVYsV0FBVyxDQXdDUCx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsRUFDNUIsS0FBSyxFQUFFLElBQUksR0FDZDs7QUF0SFQsQUF5SEksY0F6SFUsQ0F5SFYsYUFBYSxFQXpIakIsY0FBYyxDQTBIVixrQkFBa0IsQ0FBQyxFQUNmLE9BQU8sRUFBRSxNQUFNLEdBQ2xCOztBQTVITCxBQThISSxjQTlIVSxDQThIViw0QkFBNEIsQ0FBQyxFQUN6QixVQUFVLEVBQUUsSUFBSSxHQUNuQiJ9 */
|
||||
|
||||
/*# sourceMappingURL=redux-extension-customizer.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,233 @@
|
||||
/* global jQuery, document, redux, redux_change:true, wp, ajaxurl */
|
||||
|
||||
(function ( $ ) {
|
||||
'use strict';
|
||||
|
||||
redux.customizer = redux.customizer || {};
|
||||
|
||||
$( document ).ready(
|
||||
function () {
|
||||
redux.customizer.init();
|
||||
}
|
||||
);
|
||||
|
||||
redux.customizer.init = function () {
|
||||
var reduxChange;
|
||||
var redux_initFields;
|
||||
|
||||
$( 'body' ).addClass( redux.customizer.body_class );
|
||||
|
||||
$( '.accordion-section.redux-section, .accordion-section.redux-panel, .accordion-section-title' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$.redux.initFields();
|
||||
}
|
||||
);
|
||||
|
||||
$( '.accordion-section.redux-section h3, .accordion-section.redux-panel h3' ).on(
|
||||
'click',
|
||||
function () {
|
||||
redux.customizer.resize( $( this ).parent() );
|
||||
}
|
||||
);
|
||||
|
||||
if ( undefined === redux.optName ) {
|
||||
console.log( 'Redux customizer extension failure' );
|
||||
return;
|
||||
}
|
||||
|
||||
$( '.control-panel-back, .customize-panel-back' ).on(
|
||||
'click',
|
||||
function () {
|
||||
$( document ).find( 'form#customize-controls' ).removeAttr( 'style' );
|
||||
$( document ).find( '.wp-full-overlay' ).removeAttr( 'style' );
|
||||
redux.customizer.width = 0;
|
||||
}
|
||||
);
|
||||
|
||||
$( '.control-section-back, .customize-section-back' ).on(
|
||||
'click',
|
||||
function () {
|
||||
redux.customizer.resize( $( this ).parent().parent().parent() );
|
||||
}
|
||||
);
|
||||
|
||||
if ( redux.customizer ) {
|
||||
|
||||
// Customizer save hook.
|
||||
$( '#customize-save-button-wrapper #save' ).on(
|
||||
'click',
|
||||
function () {
|
||||
setTimeout(
|
||||
function () {
|
||||
var $parent = $( document.getElementById( 'customize-controls' ) );
|
||||
var $data = $parent.serialize();
|
||||
var nonce = $( '.redux-customizer-nonce' ).data( 'nonce' );
|
||||
|
||||
$.ajax(
|
||||
{
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
url: ajaxurl,
|
||||
data: {
|
||||
action: redux.optName.args.opt_name + '_customizer_save',
|
||||
nonce: nonce,
|
||||
opt_name: redux.optName.args.opt_name,
|
||||
data: $data
|
||||
},
|
||||
error: function ( response ) {
|
||||
if ( true === redux.optName.args.dev_mode ) {
|
||||
console.log( response.responseText );
|
||||
}
|
||||
},
|
||||
success: function ( response ) {
|
||||
if ( 'success' === response.status ) {
|
||||
console.log( response );
|
||||
$( '.redux-action_bar .spinner' ).removeClass( 'is-active' );
|
||||
redux.optName.options = response.options;
|
||||
redux.optName.errors = response.errors;
|
||||
redux.optName.warnings = response.warnings;
|
||||
redux.optName.sanitize = response.sanitize;
|
||||
|
||||
if ( null !== response.errors || null !== response.warnings ) {
|
||||
$.redux.notices();
|
||||
}
|
||||
|
||||
if ( null !== response.sanitize ) {
|
||||
$.redux.sanitize();
|
||||
}
|
||||
} else {
|
||||
console.log( response.responseText );
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
},
|
||||
1000
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
redux.optName.args.disable_save_warn = true;
|
||||
|
||||
reduxChange = redux_change;
|
||||
redux_change = function ( variable ) {
|
||||
variable = $( variable );
|
||||
reduxChange.apply( this, arguments );
|
||||
redux.customizer.save( variable );
|
||||
};
|
||||
|
||||
redux_initFields = $.redux.initFields;
|
||||
|
||||
$.redux.initFiles = function () {
|
||||
redux_initFields();
|
||||
};
|
||||
};
|
||||
|
||||
redux.customizer.resize = function ( el ) {
|
||||
var width;
|
||||
var test;
|
||||
var id;
|
||||
var parentId;
|
||||
|
||||
if ( el.attr( 'data-width' ) ) {
|
||||
redux.customizer.width = el.attr( 'data-width' );
|
||||
|
||||
width = redux.customizer.width;
|
||||
|
||||
} else {
|
||||
width = redux.customizer.width;
|
||||
}
|
||||
|
||||
if ( $( 'body' ).width() < 640 ) {
|
||||
width = '';
|
||||
}
|
||||
if ( '' !== width ) {
|
||||
test = $( '#' + el.attr( 'aria-owns' ) );
|
||||
|
||||
if ( test.length > 0 ) {
|
||||
el = test;
|
||||
}
|
||||
}
|
||||
|
||||
if ( el.hasClass( 'open' ) || el.hasClass( 'current-panel' ) || el.hasClass( 'current-section' ) ) {
|
||||
if ( '' !== width ) {
|
||||
$( document ).find( 'form#customize-controls' ).attr(
|
||||
'style',
|
||||
'width:' + width + ';'
|
||||
);
|
||||
$( document ).find( '.wp-full-overlay' ).attr(
|
||||
'style',
|
||||
'margin-left:' + width + ';'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
id = el.attr( 'id' );
|
||||
parentId = $( '*[aria-owns="' + id + '"]' ).parents( '.redux-panel:first' ).attr( 'id' );
|
||||
width = $( '*[aria-owns="' + parentId + '"]' ).attr( 'data-width' );
|
||||
|
||||
if ( ! width ) {
|
||||
$( document ).find( 'form#customize-controls' ).removeAttr( 'style' );
|
||||
$( document ).find( '.wp-full-overlay' ).removeAttr( 'style' );
|
||||
} else {
|
||||
$( document ).find( 'form#customize-controls' ).attr(
|
||||
'style',
|
||||
'width:' + width + ';'
|
||||
);
|
||||
$( document ).find( '.wp-full-overlay' ).attr(
|
||||
'style',
|
||||
'margin-left:' + width + ';'
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
redux.customizer.save = function ( $obj ) {
|
||||
var $parent = $obj.hasClass( 'redux-field' ) ? $obj : $obj.parents( '.redux-field-container:first' );
|
||||
redux.customizer.inputSave( $parent );
|
||||
};
|
||||
|
||||
redux.customizer.inputSave = function ( $parent ) {
|
||||
var $id;
|
||||
var $nData;
|
||||
var $key;
|
||||
var $control;
|
||||
|
||||
if ( ! $parent.hasClass( 'redux-field-container' ) ) {
|
||||
$parent = $parent.parents( '[class^="redux-field-container"]' );
|
||||
}
|
||||
|
||||
$id = $parent.parent().find( '.redux-customizer-input' ).data( 'id' );
|
||||
|
||||
if ( ! $id ) {
|
||||
$parent = $parent.parents( '.redux-container-repeater:first' );
|
||||
$id = $parent.parent().find( '.redux-customizer-input' ).data( 'id' );
|
||||
}
|
||||
|
||||
$nData = $parent.find( ':input' ).serializeJSON();
|
||||
|
||||
$.each(
|
||||
$nData,
|
||||
function ( $k, $v ) {
|
||||
$k = null;
|
||||
$nData = $v;
|
||||
}
|
||||
);
|
||||
|
||||
$key = $parent.parent().find( '.redux-customizer-input' ).data( 'key' );
|
||||
if ( $nData[$key] ) {
|
||||
$nData = $nData[$key];
|
||||
}
|
||||
|
||||
$control = wp.customize.control( $id );
|
||||
|
||||
// Customizer hack since they didn't code it to save order...
|
||||
if ( JSON.stringify( $control.setting._value ) !== JSON.stringify( $nData ) ) {
|
||||
$control.setting._value = null;
|
||||
}
|
||||
|
||||
$control.setting.set( $nData );
|
||||
};
|
||||
})( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
!function(n){"use strict";redux.customizer=redux.customizer||{},n(document).ready(function(){redux.customizer.init()}),redux.customizer.init=function(){var t,e;n("body").addClass(redux.customizer.body_class),n(".accordion-section.redux-section, .accordion-section.redux-panel, .accordion-section-title").on("click",function(){n.redux.initFields()}),n(".accordion-section.redux-section h3, .accordion-section.redux-panel h3").on("click",function(){redux.customizer.resize(n(this).parent())}),void 0===redux.optName?console.log("Redux customizer extension failure"):(n(".control-panel-back, .customize-panel-back").on("click",function(){n(document).find("form#customize-controls").removeAttr("style"),n(document).find(".wp-full-overlay").removeAttr("style"),redux.customizer.width=0}),n(".control-section-back, .customize-section-back").on("click",function(){redux.customizer.resize(n(this).parent().parent().parent())}),redux.customizer&&n("#customize-save-button-wrapper #save").on("click",function(){setTimeout(function(){var e=n(document.getElementById("customize-controls")).serialize(),t=n(".redux-customizer-nonce").data("nonce");n.ajax({type:"post",dataType:"json",url:ajaxurl,data:{action:redux.optName.args.opt_name+"_customizer_save",nonce:t,opt_name:redux.optName.args.opt_name,data:e},error:function(e){!0===redux.optName.args.dev_mode&&console.log(e.responseText)},success:function(e){"success"===e.status?(console.log(e),n(".redux-action_bar .spinner").removeClass("is-active"),redux.optName.options=e.options,redux.optName.errors=e.errors,redux.optName.warnings=e.warnings,redux.optName.sanitize=e.sanitize,null===e.errors&&null===e.warnings||n.redux.notices(),null!==e.sanitize&&n.redux.sanitize()):console.log(e.responseText)}})},1e3)}),redux.optName.args.disable_save_warn=!0,t=redux_change,redux_change=function(e){e=n(e),t.apply(this,arguments),redux.customizer.save(e)},e=n.redux.initFields,n.redux.initFiles=function(){e()})},redux.customizer.resize=function(e){e.attr("data-width")&&(redux.customizer.width=e.attr("data-width"));var t,r=redux.customizer.width;(e=""!==(r=n("body").width()<640?"":r)&&0<(t=n("#"+e.attr("aria-owns"))).length?t:e).hasClass("open")||e.hasClass("current-panel")||e.hasClass("current-section")?""!==r&&(n(document).find("form#customize-controls").attr("style","width:"+r+";"),n(document).find(".wp-full-overlay").attr("style","margin-left:"+r+";")):(t=e.attr("id"),e=n('*[aria-owns="'+t+'"]').parents(".redux-panel:first").attr("id"),(r=n('*[aria-owns="'+e+'"]').attr("data-width"))?(n(document).find("form#customize-controls").attr("style","width:"+r+";"),n(document).find(".wp-full-overlay").attr("style","margin-left:"+r+";")):(n(document).find("form#customize-controls").removeAttr("style"),n(document).find(".wp-full-overlay").removeAttr("style")))},redux.customizer.save=function(e){e=e.hasClass("redux-field")?e:e.parents(".redux-field-container:first");redux.customizer.inputSave(e)},redux.customizer.inputSave=function(e){var t=(t=(e=e.hasClass("redux-field-container")?e:e.parents('[class^="redux-field-container"]')).parent().find(".redux-customizer-input").data("id"))||(e=e.parents(".redux-container-repeater:first")).parent().find(".redux-customizer-input").data("id"),r=e.find(":input").serializeJSON();n.each(r,function(e,t){r=t}),e=e.parent().find(".redux-customizer-input").data("key"),r[e]&&(r=r[e]),e=wp.customize.control(t),JSON.stringify(e.setting._value)!==JSON.stringify(r)&&(e.setting._value=null),e.setting.set(r)}}(jQuery);
|
||||
@@ -0,0 +1,130 @@
|
||||
.wp-customizer {
|
||||
.redux-container {
|
||||
overflow: visible;
|
||||
.redux-main {
|
||||
input {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
input.spinner-input {
|
||||
margin-right: 30px !important;
|
||||
margin-left: 30px !important;
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.redux-container-editor {
|
||||
.wp-editor-area {
|
||||
color:#000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-section.open .redux-group-tab {
|
||||
display: block !important;
|
||||
|
||||
&.hide {
|
||||
display:none!important;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-section {
|
||||
p.customize-section-description {
|
||||
margin-top: 22px;
|
||||
word-break: break-word;
|
||||
&.legacy {
|
||||
margin-top: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.control-section-themes .accordion-section-title {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#customize-controls {
|
||||
.description {
|
||||
display: block;
|
||||
}
|
||||
.customize-info {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.redux-section .accordion-section-content {
|
||||
background: #fcfcfc;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-section .accordion-section-title i,
|
||||
.redux-field .accordion-field-title i,
|
||||
.redux-panel .accordion-section-title i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.accordion-section.redux-main {
|
||||
background: inherit;
|
||||
margin-left: inherit;
|
||||
border-left: inherit;
|
||||
-moz-box-shadow: inherit;
|
||||
-webkit-box-shadow: inherit;
|
||||
padding: inherit;
|
||||
box-shadow: inherit;
|
||||
}
|
||||
|
||||
.redux_field_th {
|
||||
padding: 13px 0 0 0;
|
||||
}
|
||||
|
||||
.redux-main {
|
||||
.redux-field-container {
|
||||
padding: 10px 0;
|
||||
}
|
||||
.select_wrapper {
|
||||
float: none;
|
||||
width: 100%;
|
||||
display: inline-block;
|
||||
}
|
||||
.select2-container {
|
||||
margin-right: 0 !important;
|
||||
margin-bottom: 5px !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
.select_wrapper:nth-child(odd) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.redux-option-image {
|
||||
max-width: 42% !important;
|
||||
margin-right: 3%;
|
||||
}
|
||||
.customize-control {
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
.customize-control:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.upload {
|
||||
width: 100% !important;
|
||||
}
|
||||
h3 {
|
||||
margin-top: inherit;
|
||||
}
|
||||
.redux-container-raw {
|
||||
margin-top: 22px;
|
||||
word-break: break-word;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.redux-container-password input {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.select2-drop,
|
||||
.select2-container {
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.customize-control-redux-raw {
|
||||
list-style: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Date/Time Extension Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Extension_Datetime
|
||||
*
|
||||
* @version 4.3.15
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Extension_Datetime', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Extension_Datetime
|
||||
*/
|
||||
class Redux_Extension_Datetime extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.3.15';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension_name = 'Date/Time';
|
||||
|
||||
/**
|
||||
* Redux_Extension_Datetime constructor.
|
||||
*
|
||||
* @param object $redux ReduxFramework pointer.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
$this->add_field( 'datetime' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Date/Time Field Class
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Datetime
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Datetime', false ) ) {
|
||||
|
||||
/**
|
||||
* Class Redux_Datetime
|
||||
*/
|
||||
class Redux_Datetime extends Redux_Field {
|
||||
|
||||
/**
|
||||
* Set field defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
$defaults = array(
|
||||
'date-format' => 'mm-dd-yy',
|
||||
'time-format' => 'hh:mm TT z',
|
||||
'split' => false,
|
||||
'separator' => ' ',
|
||||
'date-picker' => true,
|
||||
'time-picker' => true,
|
||||
'control-type' => 'slider',
|
||||
'num-of-months' => 1,
|
||||
|
||||
// DO NOT CHANGE THESE!!!!
|
||||
// It will make this file's javascript sister
|
||||
// cry like a deflowered virgin on prom night.
|
||||
'timezone-list' => null,
|
||||
'timezone' => '0',
|
||||
'hour-min' => 0,
|
||||
'hour-max' => 23,
|
||||
'minute-min' => 0,
|
||||
'minute-max' => 59,
|
||||
'date-min' => - 1,
|
||||
'date-max' => - 1,
|
||||
);
|
||||
|
||||
$this->field = wp_parse_args( $this->field, $defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Field Render Function.
|
||||
* Takes the vars and outputs the HTML for the field in the settings
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
$num_of_months = $this->field['num-of-months'];
|
||||
if ( 0 === $num_of_months ) {
|
||||
$num_of_months = 1;
|
||||
}
|
||||
|
||||
// Validate min/max values.
|
||||
$hour_min = $this->field['hour-min'];
|
||||
$hour_max = $this->field['hour-max'];
|
||||
$min_min = $this->field['minute-min'];
|
||||
$min_max = $this->field['minute-max'];
|
||||
|
||||
if ( $hour_min < 0 || $hour_min > 23 ) {
|
||||
$hour_min = 0;
|
||||
}
|
||||
|
||||
if ( $hour_max < 0 || $hour_max > 23 ) {
|
||||
$hour_max = 23;
|
||||
}
|
||||
|
||||
if ( $min_min < 0 || $min_min > 59 ) {
|
||||
$min_min = 0;
|
||||
}
|
||||
|
||||
if ( $min_max < 0 || $min_max > 59 ) {
|
||||
$min_max = 59;
|
||||
}
|
||||
|
||||
// Validate min date month.
|
||||
if ( is_array( $this->field['date-min'] ) ) {
|
||||
if ( isset( $this->field['date-min']['month'] ) ) {
|
||||
if ( $this->field['date-min']['month'] < 1 || $this->field['date-min']['month'] > 12 ) {
|
||||
$this->field['date-min']['month'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $this->field['date-min']['day'] ) ) {
|
||||
if ( $this->field['date-min']['day'] < 1 || $this->field['date-min']['day'] > 31 ) {
|
||||
$this->field['date-min']['day'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate max date month.
|
||||
if ( is_array( $this->field['date-max'] ) ) {
|
||||
if ( isset( $this->field['date-max']['month'] ) ) {
|
||||
if ( $this->field['date-max']['month'] < 1 || $this->field['date-max']['month'] > 12 ) {
|
||||
$this->field['date-max']['month'] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate max date day (imperfect, so we'll just use 31).
|
||||
if ( isset( $this->field['date-max']['day'] ) ) {
|
||||
if ( $this->field['date-max']['day'] < 1 || $this->field['date-max']['day'] > 31 ) {
|
||||
$this->field['date-max']['day'] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assignment, make it easier to read.
|
||||
$field_id = $this->field['id'];
|
||||
$field_name = $this->field['name'];
|
||||
$split = $this->field['split'];
|
||||
$control_type = $this->field['control-type'];
|
||||
|
||||
// Sanitize width
|
||||
// Sanitize default value.
|
||||
if ( true === $split ) {
|
||||
if ( ! is_array( $this->value ) ) {
|
||||
$this->value = array();
|
||||
$this->value['time'] = '';
|
||||
$this->value['date'] = '';
|
||||
}
|
||||
} elseif ( is_array( $this->value ) ) {
|
||||
$this->value = '';
|
||||
}
|
||||
|
||||
// Dummy check, in case something other than select or slider
|
||||
// is entered.
|
||||
switch ( $control_type ) {
|
||||
case 'select':
|
||||
case 'slider':
|
||||
break;
|
||||
default:
|
||||
$control_type = 'slider';
|
||||
}
|
||||
|
||||
// Set placeholder based on mode.
|
||||
if ( true === $split ) {
|
||||
$date_placeholder = $this->field['placeholder']['date'] ?? __( 'Date', 'your-domain-here' );
|
||||
$time_placeholder = $this->field['placeholder']['time'] ?? __( 'Time', 'your-domain-here' );
|
||||
} else {
|
||||
$date_placeholder = $this->field['placeholder'] ?? __( 'Date / Time', 'your-domain-here' );
|
||||
}
|
||||
|
||||
// Output defaults to div, so JS can read it.
|
||||
// Broken up for readability; coz I'm the one who has to debug it!
|
||||
echo '<div id="' . esc_attr( $field_id ) . '" class="redux-datetime-container"
|
||||
data-dev-mode="' . esc_attr( $this->parent->args['dev_mode'] ) . '"
|
||||
data-version="' . esc_attr( Redux_Extension_Datetime::$version ) . '"
|
||||
data-id="' . esc_attr( $field_id ) . '"
|
||||
data-mode="' . esc_attr( $split ) . '"
|
||||
data-separator="' . esc_attr( $this->field['separator'] ) . '"
|
||||
data-control-type="' . esc_attr( $control_type ) . '"
|
||||
data-rtl="' . esc_attr( is_rtl() ) . '"
|
||||
data-num-of-months="' . esc_attr( $num_of_months ) . '"
|
||||
data-hour-min="' . esc_attr( $hour_min ) . '"
|
||||
data-hour-max="' . esc_attr( $hour_max ) . '"
|
||||
data-minute-min="' . esc_attr( $min_min ) . '"
|
||||
data-minute-max="' . esc_attr( $min_max ) . '"
|
||||
data-date-min="' . rawurlencode( wp_json_encode( $this->field['date-min'] ) ) . '"
|
||||
data-date-max="' . rawurlencode( wp_json_encode( $this->field['date-max'] ) ) . '"
|
||||
data-timezone="' . esc_attr( $this->field['timezone'] ) . '"
|
||||
data-timezone-list="' . rawurlencode( wp_json_encode( $this->field['timezone-list'] ) ) . '"
|
||||
data-date-picker="' . esc_attr( $this->field['date-picker'] ) . '"
|
||||
data-time-picker="' . esc_attr( $this->field['time-picker'] ) . '"
|
||||
data-time-format="' . esc_attr( $this->field['time-format'] ) . '"
|
||||
data-date-format="' . esc_attr( $this->field['date-format'] ) . '">';
|
||||
|
||||
// If split mode is on, output two text boxes.
|
||||
if ( true === $split ) {
|
||||
echo '<div class="redux-date-input input_wrapper">';
|
||||
echo '<label for="' . esc_attr( $field_id ) . '-date" class="redux-date-input-label">' . esc_html( $date_placeholder ) . '</label>';
|
||||
echo ' <input
|
||||
data-id="' . esc_attr( $field_id ) . '"
|
||||
type="text"
|
||||
id="' . esc_attr( $field_id ) . '-date"
|
||||
name="' . esc_attr( $field_name ) . '[date]"
|
||||
placeholder="' . esc_attr( $date_placeholder ) . '"
|
||||
value="' . esc_attr( $this->value['date'] ) . '"
|
||||
class="redux-date-picker ' . esc_attr( $this->field['class'] ) . '" /> ';
|
||||
|
||||
echo '</div>';
|
||||
|
||||
echo '<div class="redux-time-input input_wrapper">';
|
||||
echo '<label for="' . esc_attr( $field_id ) . '-time" class="redux-time-input-label">' . esc_html( $time_placeholder ) . '</label>';
|
||||
echo ' <input
|
||||
data-id="' . esc_attr( $field_id ) . '"
|
||||
type="text"
|
||||
id="' . esc_attr( $field_id ) . '-time"
|
||||
name="' . esc_attr( $field_name ) . '[time]"
|
||||
placeholder="' . esc_attr( $time_placeholder ) . '"
|
||||
value="' . esc_attr( $this->value['time'] ) . '"
|
||||
class="redux-time-picker ' . esc_attr( $this->field['class'] ) . '" />';
|
||||
|
||||
// Otherwise, just one.
|
||||
} else {
|
||||
echo '<div class="redux-datetime-input single_wrapper">';
|
||||
echo '<label for="' . esc_attr( $field_id ) . '-date" class="redux-datetime-input-label">' . esc_attr( $date_placeholder ) . '</label>';
|
||||
echo ' <input
|
||||
data-id="' . esc_attr( $field_id ) . '"
|
||||
type="text"
|
||||
id="' . esc_attr( $field_id ) . '-date"
|
||||
name="' . esc_attr( $field_name ) . '"
|
||||
placeholder="' . esc_attr( $date_placeholder ) . '"
|
||||
value="' . esc_attr( $this->value ) . '"
|
||||
class="redux-date-picker ' . esc_attr( $this->field['class'] ) . '" />';
|
||||
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
// Close da div, main!
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Function.
|
||||
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
$min = Redux_Functions::is_min();
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-datetime-slider',
|
||||
$this->url . 'vendor/jquery-ui-sliderAccess' . $min . '.js',
|
||||
array( 'jquery' ),
|
||||
'0.3',
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-datetime',
|
||||
$this->url . 'vendor/jquery-ui-timepicker-addon' . $min . '.js',
|
||||
array(
|
||||
'jquery',
|
||||
'jquery-ui-datepicker',
|
||||
'jquery-ui-widget',
|
||||
'jquery-ui-slider',
|
||||
'redux-datetime-slider',
|
||||
),
|
||||
'1.6.3',
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-field-datetime',
|
||||
$this->url . 'redux-datetime' . $min . '.js',
|
||||
array( 'jquery', 'redux-datetime', 'redux-js' ),
|
||||
Redux_Extension_Datetime::$version,
|
||||
true
|
||||
);
|
||||
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-datetime',
|
||||
$this->url . 'redux-datetime.css',
|
||||
array(),
|
||||
Redux_Extension_Datetime::$version,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,177 @@
|
||||
/* global redux, jQuery */
|
||||
|
||||
( function( $ ) {
|
||||
'use strict';
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.datetime = redux.field_objects.datetime || {};
|
||||
|
||||
redux.field_objects.datetime.init = function( selector ) {
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-datetime:visible' );
|
||||
}
|
||||
|
||||
$( selector ).each(
|
||||
function() {
|
||||
var el = $( this );
|
||||
var parent = el;
|
||||
|
||||
if ( ! el.hasClass( 'redux-field-container' ) ) {
|
||||
parent = el.parents( '.redux-field-container:first' );
|
||||
}
|
||||
|
||||
if ( parent.is( ':hidden' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( parent.hasClass( 'redux-field-init' ) ) {
|
||||
parent.removeClass( 'redux-field-init' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
el.find( '.redux-date-picker' ).each(
|
||||
function() {
|
||||
var dateFormat;
|
||||
var timeFormat;
|
||||
var separator;
|
||||
var rtl;
|
||||
var numOfMonths;
|
||||
var hourMin;
|
||||
var hourMax;
|
||||
var minuteMin;
|
||||
var minuteMax;
|
||||
var controlType;
|
||||
var datePicker;
|
||||
var timePicker;
|
||||
var timeOnly = false;
|
||||
var timezoneList;
|
||||
var dateMin;
|
||||
var minDate;
|
||||
var dateMax;
|
||||
var maxDate;
|
||||
var timezone;
|
||||
var split;
|
||||
var altField = '';
|
||||
var timePickerID;
|
||||
|
||||
var mainID = $( this ).parents( '.redux-datetime-container:first' ).attr( 'id' );
|
||||
var id = $( '#' + mainID );
|
||||
|
||||
dateFormat = id.data( 'date-format' );
|
||||
dateFormat = String( ( '' === dateFormat ) ? 'mm-dd-yy' : dateFormat );
|
||||
|
||||
timeFormat = id.data( 'time-format' );
|
||||
timeFormat = String( ( '' === timeFormat ) ? 'h:mm TT' : timeFormat );
|
||||
|
||||
separator = id.data( 'separator' );
|
||||
separator = String( ( '' === separator ) ? ' ' : separator );
|
||||
|
||||
rtl = id.data( 'rtl' );
|
||||
rtl = Boolean( ( '' === rtl ) ? false : rtl );
|
||||
|
||||
numOfMonths = id.data( 'num-of-months' );
|
||||
hourMin = id.data( 'hour-min' );
|
||||
hourMax = id.data( 'hour-max' );
|
||||
minuteMin = id.data( 'minute-min' );
|
||||
minuteMax = id.data( 'minute-max' );
|
||||
|
||||
controlType = id.data( 'control-type' );
|
||||
controlType = String( ( '' === controlType ) ? 'slider' : controlType );
|
||||
|
||||
datePicker = id.data( 'date-picker' );
|
||||
datePicker = Boolean( ( '' === datePicker ) ? false : datePicker );
|
||||
|
||||
timePicker = id.data( 'time-picker' );
|
||||
timePicker = Boolean( ( '' === timePicker ) ? false : timePicker );
|
||||
|
||||
if ( false === datePicker ) {
|
||||
timeOnly = true;
|
||||
}
|
||||
|
||||
timezoneList = id.data( 'timezone-list' );
|
||||
timezoneList = decodeURIComponent( timezoneList );
|
||||
timezoneList = JSON.parse( timezoneList );
|
||||
|
||||
dateMin = id.data( 'date-min' );
|
||||
dateMin = decodeURIComponent( dateMin );
|
||||
dateMin = JSON.parse( dateMin );
|
||||
|
||||
if ( dateMin === - 1 ) {
|
||||
minDate = null;
|
||||
} else if ( 'object' === typeof dateMin ) {
|
||||
minDate = new Date( dateMin.year, dateMin.month, dateMin.day );
|
||||
} else {
|
||||
minDate = dateMin;
|
||||
}
|
||||
|
||||
dateMax = id.data( 'date-max' );
|
||||
dateMax = decodeURIComponent( dateMax );
|
||||
dateMax = JSON.parse( dateMax );
|
||||
|
||||
if ( dateMax === - 1 ) {
|
||||
maxDate = null;
|
||||
} else if ( 'object' === typeof dateMax ) {
|
||||
maxDate = new Date( dateMax.year, dateMax.month, dateMax.day );
|
||||
} else {
|
||||
maxDate = dateMax;
|
||||
}
|
||||
|
||||
timezone = id.data( 'timezone' );
|
||||
|
||||
split = id.data( 'mode' );
|
||||
split = Boolean( ( '' === split ) ? false : split );
|
||||
|
||||
if ( true === split ) {
|
||||
timePickerID = el.find( 'input.redux-time-picker' ).data( 'id' );
|
||||
altField = '#' + timePickerID + '-time'; // '.redux-time-picker';
|
||||
}
|
||||
|
||||
$( this ).datetimepicker(
|
||||
{
|
||||
beforeShow: function( input, instance ) {
|
||||
var el = $( '#ui-datepicker-div' );
|
||||
var popover = instance.dpDiv;
|
||||
|
||||
$( '.redux-container:first' ).append( el );
|
||||
el.hide();
|
||||
|
||||
setTimeout(
|
||||
function() {
|
||||
popover.position(
|
||||
{
|
||||
my: 'left top',
|
||||
at: 'left bottom',
|
||||
collision: 'none',
|
||||
of: input
|
||||
}
|
||||
);
|
||||
},
|
||||
1
|
||||
);
|
||||
},
|
||||
altField: altField,
|
||||
dateFormat: dateFormat,
|
||||
timeFormat: timeFormat,
|
||||
separator: separator,
|
||||
showTimepicker: timePicker,
|
||||
timeOnly: timeOnly,
|
||||
controlType: controlType,
|
||||
isRTL: rtl,
|
||||
timezoneList: timezoneList,
|
||||
timezone: timezone,
|
||||
hourMin: hourMin,
|
||||
hourMax: hourMax,
|
||||
minuteMin: minuteMin,
|
||||
minuteMax: minuteMax,
|
||||
minDate: minDate,
|
||||
maxDate: maxDate,
|
||||
numberOfMonths: numOfMonths
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
.redux-container-datetime .redux-datetime-container .input_wrapper,.redux-container-datetime .redux-datetime-container single_wrapper{display:block;position:relative;margin:0 4px 0 5px;padding:0;width:25%;max-width:25%;min-width:70px;float:left;clear:none;height:57px;-webkit-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box;vertical-align:baseline}.redux-container-datetime .redux-datetime-container .single_wrapper{width:50% !important;max-width:50% !important}.redux-container-datetime .redux-datetime-container label{display:block;position:relative;font-size:12px !important;text-align:left;color:#999;margin:4px 0 2px 0 !important;cursor:default}.redux-container-datetime .redux-datetime-container .redux-date-picker{width:100%}.redux-container-datetime .redux-datetime-container .redux-time-picker{width:100%}.ui-tpicker-grid-label{background:0;border:0;margin:0;padding:0}.ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div dl{text-align:left}.ui-timepicker-div dl dt{float:left;clear:left;padding:0 0 0 5px}.ui-timepicker-div dl dd{margin:0 10px 10px 40%}.ui-timepicker-div td{font-size:90%}.ui-timepicker-div .ui_tpicker_unit_hide{display:none}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input{background:0;color:inherit;border:0;outline:0;border-bottom:solid 1px #555;width:95%}.ui-timepicker-div .ui_tpicker_time .ui_tpicker_time_input:focus{border-bottom-color:#aaa}.ui-timepicker-div.ui-timepicker-oneLine{padding-right:2px}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time,.ui-timepicker-div.ui-timepicker-oneLine dt{display:none}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_time_label{display:block;padding-top:2px}.ui-timepicker-div.ui-timepicker-oneLine dl{text-align:right}.ui-timepicker-div.ui-timepicker-oneLine dl dd,.ui-timepicker-div.ui-timepicker-oneLine dl dd>div{display:inline-block;margin:0}.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_millisec:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_microsec:before{content:'.';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine dd.ui_tpicker_minute:before,.ui-timepicker-div.ui-timepicker-oneLine dl dd.ui_tpicker_second:before{content:':';display:inline-block}.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide,.ui-timepicker-div.ui-timepicker-oneLine .ui_tpicker_unit_hide:before{display:none}.ui-timepicker-div .ui-widget-header{margin-bottom:8px}.ui-timepicker-div .ui-slider{position:relative;text-align:left}.ui-timepicker-div .ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-timepicker-div .ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-timepicker-div .ui-slider.ui-state-disabled .ui-slider-handle,.ui-timepicker-div .ui-slider.ui-state-disabled .ui-slider-range{-webkit-filter:inherit;filter:inherit}.ui-timepicker-div .ui-slider-horizontal{height:.8em}.ui-timepicker-div .ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-timepicker-div .ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-timepicker-div .ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-timepicker-div .ui-slider-horizontal .ui-slider-range-min{left:0}.ui-timepicker-div .ui-slider-horizontal .ui-slider-range-max{right:0}.ui-timepicker-div .ui-slider-vertical{width:.8em;height:100px}.ui-timepicker-div .ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-timepicker-div .ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-timepicker-div .ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-timepicker-div .ui-slider-vertical .ui-slider-range-max{top:0}.ui-timepicker-rtl{direction:rtl}.ui-timepicker-rtl dl{text-align:right;padding:0 5px 0 0}.ui-timepicker-rtl dl dt{float:right;clear:right}.ui-timepicker-rtl dl dd{margin:0 40% 10px 10px}
|
||||
@@ -0,0 +1 @@
|
||||
!function(j){"use strict";redux.field_objects=redux.field_objects||{},redux.field_objects.datetime=redux.field_objects.datetime||{},redux.field_objects.datetime.init=function(e){e=e||j(document).find(".redux-group-tab:visible").find(".redux-container-datetime:visible"),j(e).each(function(){var y=j(this),e=y;(e=y.hasClass("redux-field-container")?e:y.parents(".redux-field-container:first")).is(":hidden")||e.hasClass("redux-field-init")&&(e.removeClass("redux-field-init"),y.find(".redux-date-picker").each(function(){var e,t,a,i,d,n,o,r,m,s,u,c,l,f,p=!1,x="",h=j(this).parents(".redux-datetime-container:first").attr("id"),h=j("#"+h),b=h.data("date-format");b=String(""===b?"mm-dd-yy":b),e=h.data("time-format"),e=String(""===e?"h:mm TT":e),t=h.data("separator"),t=String(""===t?" ":t),a=h.data("rtl"),a=Boolean(""!==a&&a),i=h.data("num-of-months"),d=h.data("hour-min"),n=h.data("hour-max"),o=h.data("minute-min"),r=h.data("minute-max"),m=h.data("control-type"),m=String(""===m?"slider":m),u=h.data("date-picker"),u=Boolean(""!==u&&u),s=h.data("time-picker"),s=Boolean(""!==s&&s),!1===u&&(p=!0),u=h.data("timezone-list"),u=decodeURIComponent(u),u=JSON.parse(u),c=h.data("date-min"),c=decodeURIComponent(c),c=-1===(c=JSON.parse(c))?null:"object"==typeof c?new Date(c.year,c.month,c.day):c,l=h.data("date-max"),l=decodeURIComponent(l),l=-1===(l=JSON.parse(l))?null:"object"==typeof l?new Date(l.year,l.month,l.day):l,f=h.data("timezone"),h=h.data("mode"),!0===Boolean(""!==h&&h)&&(x="#"+y.find("input.redux-time-picker").data("id")+"-time"),j(this).datetimepicker({beforeShow:function(e,t){var a=j("#ui-datepicker-div"),i=t.dpDiv;j(".redux-container:first").append(a),a.hide(),setTimeout(function(){i.position({my:"left top",at:"left bottom",collision:"none",of:e})},1)},altField:x,dateFormat:b,timeFormat:e,separator:t,showTimepicker:s,timeOnly:p,controlType:m,isRTL:a,timezoneList:u,timezone:f,hourMin:d,hourMax:n,minuteMin:o,minuteMax:r,minDate:c,maxDate:l,numberOfMonths:i})}))})}}(jQuery);
|
||||
@@ -0,0 +1,234 @@
|
||||
.redux-container-datetime {
|
||||
.redux-datetime-container {
|
||||
.input_wrapper,
|
||||
.single_wrapper {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0 4px 0 5px;
|
||||
padding: 0;
|
||||
width: 25%;
|
||||
max-width: 25%;
|
||||
min-width: 70px;
|
||||
float: left;
|
||||
clear: none;
|
||||
height: 57px;
|
||||
box-sizing: border-box;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.single_wrapper {
|
||||
width: 50%!important;
|
||||
max-width: 50%!important;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
position: relative;
|
||||
font-size: 12px !important;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
margin: 4px 0 2px 0 !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.redux-date-picker {
|
||||
width: 100%
|
||||
}
|
||||
|
||||
.redux-time-picker {
|
||||
width: 100%
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.ui-tpicker-grid-label {
|
||||
background: none;
|
||||
border: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ui-timepicker-div {
|
||||
.ui-widget-header {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
dl {
|
||||
text-align: left;
|
||||
|
||||
dt {
|
||||
float: left;
|
||||
clear:left;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 10px 10px 40%;
|
||||
}
|
||||
}
|
||||
|
||||
td {
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
.ui_tpicker_unit_hide{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ui_tpicker_time .ui_tpicker_time_input {
|
||||
background: none;
|
||||
color: inherit;
|
||||
border: none;
|
||||
outline: none;
|
||||
border-bottom: solid 1px #555;
|
||||
width: 95%;
|
||||
|
||||
&:focus {
|
||||
border-bottom-color: #aaa;
|
||||
}
|
||||
}
|
||||
|
||||
&.ui-timepicker-oneLine {
|
||||
padding-right: 2px;
|
||||
|
||||
.ui_tpicker_time,
|
||||
dt {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ui_tpicker_time_label {
|
||||
display: block; padding-top: 2px;
|
||||
}
|
||||
|
||||
dl {
|
||||
text-align: right;
|
||||
|
||||
dd,
|
||||
dd > div {
|
||||
display:inline-block;
|
||||
margin:0;
|
||||
}
|
||||
|
||||
dd.ui_tpicker_millisec:before,
|
||||
dd.ui_tpicker_microsec:before {
|
||||
content:'.';
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
dd.ui_tpicker_minute:before,
|
||||
dl dd.ui_tpicker_second:before {
|
||||
content:':';
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.ui_tpicker_unit_hide,
|
||||
.ui_tpicker_unit_hide:before{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-widget-header {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.ui-slider {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
|
||||
.ui-slider-handle {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
width: 1.2em;
|
||||
height: 1.2em;
|
||||
cursor: default;
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.ui-slider-range {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
font-size: .7em;
|
||||
display: block;
|
||||
border: 0;
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
&.ui-state-disabled .ui-slider-handle,
|
||||
&.ui-state-disabled .ui-slider-range {
|
||||
filter: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-slider-horizontal {
|
||||
height: .8em;
|
||||
|
||||
.ui-slider-handle {
|
||||
top: -.3em;
|
||||
margin-left: -.6em;
|
||||
}
|
||||
|
||||
.ui-slider-handle {
|
||||
top: -.3em;
|
||||
margin-left: -.6em;
|
||||
}
|
||||
|
||||
.ui-slider-range {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.ui-slider-range-min {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.ui-slider-range-max {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-slider-vertical {
|
||||
width: .8em;
|
||||
height: 100px;
|
||||
|
||||
.ui-slider-handle {
|
||||
left: -.3em;
|
||||
margin-left: 0;
|
||||
margin-bottom: -.6em;
|
||||
}
|
||||
|
||||
.ui-slider-range {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ui-slider-range-min {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.ui-slider-range-max {
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui-timepicker-rtl{
|
||||
direction: rtl;
|
||||
|
||||
dl {
|
||||
text-align: right;
|
||||
padding: 0 5px 0 0;
|
||||
|
||||
dt{
|
||||
float: right;
|
||||
clear: right;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin: 0 40% 10px 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Google Maps Extension Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Extension_Google_Maps
|
||||
* @version 4.4.0
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Extension_Google_Maps' ) ) {
|
||||
|
||||
/**
|
||||
* Class ReduxFramework_extension_google_maps
|
||||
*/
|
||||
class Redux_Extension_Google_Maps extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.4.0';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $extension_name = 'Google Maps';
|
||||
|
||||
/**
|
||||
* ReduxFramework_extension_google_maps constructor.
|
||||
*
|
||||
* @param ReduxFramework $redux ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
$this->add_field( 'google_maps' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Google Maps Field Class
|
||||
*
|
||||
* @package Redux
|
||||
* @author Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Google_Maps
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'Redux_Google_Maps' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_google_maps class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Google_Maps extends Redux_Field {
|
||||
|
||||
/**
|
||||
* API Key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Get field defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
$field = array(
|
||||
'api_key' => '',
|
||||
'map_version' => 'weekly',
|
||||
);
|
||||
|
||||
$this->field = wp_parse_args( $this->field, $field );
|
||||
|
||||
$this->api_key = null;
|
||||
|
||||
$this->field['api_key'] = $this->field['api_key'] ?? '';
|
||||
|
||||
if ( empty( $this->field['api_key'] ) ) {
|
||||
$redux = get_option( $this->parent->args['opt_name'] );
|
||||
$this->api_key = $redux['google_map_api_key'] ?? '';
|
||||
} else {
|
||||
$this->api_key = $this->field['api_key'];
|
||||
}
|
||||
|
||||
// Necessary, in case the user doesn't fill out a default array.
|
||||
$def_street_number = $this->field['default']['street_number'] ?? '';
|
||||
$def_route = $this->field['default']['route'] ?? '';
|
||||
$def_locality = $this->field['default']['locality'] ?? '';
|
||||
$def_state = $this->field['default']['administrative_area_level_1'] ?? '';
|
||||
$def_postal = $this->field['default']['postal_code'] ?? '';
|
||||
$def_country = $this->field['default']['country'] ?? '';
|
||||
$def_lat = $this->field['default']['latitude'] ?? '';
|
||||
$def_long = $this->field['default']['longitude'] ?? '';
|
||||
$def_marker_info = $this->field['default']['marker_info'] ?? '';
|
||||
$def_zoom = $this->field['default']['zoom'] ?? '';
|
||||
|
||||
$defaults = array(
|
||||
'latitude' => $def_lat,
|
||||
'longitude' => $def_long,
|
||||
'street_number' => $def_street_number,
|
||||
'route' => $def_route,
|
||||
'locality' => $def_locality,
|
||||
'administrative_area_level_1' => $def_state, // <-dickheads at google. lol, srsly...wtf?
|
||||
// level_1 huh? maybe It's for multiple planets one day.
|
||||
'postal_code' => $def_postal,
|
||||
'country' => $def_country,
|
||||
'marker_info' => $def_marker_info,
|
||||
'zoom' => $def_zoom,
|
||||
);
|
||||
|
||||
$this->value = wp_parse_args( $this->value, $defaults );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Field Render Function.
|
||||
* Takes the vars and outputs the HTML for the field in the settings
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function render() {
|
||||
|
||||
// Set default or saved zoom
|
||||
// USA: 39.11676722061108,-100.47761000000003
|
||||
// Zoom far: 3
|
||||
// zoom close 17.
|
||||
if ( empty( $this->value['zoom'] ) ) {
|
||||
if ( $this->value['street_number'] ) {
|
||||
$the_zoom = 17; // make it close if the street is included.
|
||||
} else {
|
||||
$the_zoom = 3; // make it far if it's not.
|
||||
}
|
||||
} else {
|
||||
$the_zoom = $this->value['zoom'];
|
||||
}
|
||||
|
||||
// Make full address.
|
||||
$locality = ! empty( $this->value['locality'] ) ? $this->value['locality'] . ', ' : '';
|
||||
$route = ! empty( $this->value['route'] ) ? $this->value['route'] . ', ' : '';
|
||||
$country = ! empty( $this->value['country'] ) ? ', ' . $this->value['country'] : '';
|
||||
|
||||
$full = $this->value['street_number'] . ' ' . $route . ' ' . $locality . $this->value['administrative_area_level_1'] . ' ' . $this->value['postal_code'] . $country;
|
||||
$data_full = rawurlencode( $full );
|
||||
|
||||
// Hide/show various input fields.
|
||||
$show_address = $this->field['show_address'] ?? true;
|
||||
$show_city = $this->field['show_city'] ?? true;
|
||||
$show_state = $this->field['show_state'] ?? true;
|
||||
$show_postal = $this->field['show_postal'] ?? true;
|
||||
$show_country = $this->field['show_country'] ?? true;
|
||||
$show_lat = $this->field['show_latitude'] ?? true;
|
||||
$show_long = $this->field['show_longitude'] ?? true;
|
||||
$show_marker_info = $this->field['show_marker_info'] ?? true;
|
||||
$show_controls = $this->field['show_controls'] ?? true;
|
||||
|
||||
$this->field['placeholder'] = $this->field['placeholder'] ?? esc_html__( 'Enter your address', 'redux-framework' );
|
||||
$this->field['marker_tooltip'] = $this->field['marker_tooltip'] ?? esc_html__( 'Left mouse down on top of me to move me!', 'redux-framework' );
|
||||
$this->field['no_geometry_alert'] = $this->field['no_geometry_alert'] ?? esc_html__( 'The returned place contains no geometric data.', 'redux-framework' );
|
||||
$this->field['delay_render'] = $this->field['delay_render'] ?? false;
|
||||
$this->field['class'] = $this->field['class'] ?? '';
|
||||
$this->field['show_api_key'] = $this->field['show_api_key'] ?? true;
|
||||
$this->field['street_view_control'] = $this->field['street_view_control'] ?? true;
|
||||
$this->field['map_type_control'] = $this->field['map_type_control'] ?? true;
|
||||
$this->field['scroll_wheel'] = $this->field['scroll_wheel'] ?? false;
|
||||
$this->field['map_height'] = $this->field['map_height'] ?? '';
|
||||
|
||||
$map_height = '';
|
||||
|
||||
if ( ! empty( $this->field['map_height'] ) ) {
|
||||
$map_height = 'style="height:' . esc_attr( $this->field['map_height'] ) . ';"';
|
||||
}
|
||||
|
||||
$geo_alert = rawurlencode( $this->field['no_geometry_alert'] );
|
||||
|
||||
// admin defined.
|
||||
$the_lat = $this->value['latitude'];
|
||||
$the_long = $this->value['longitude'];
|
||||
$marker_tooltip = rawurlencode( $this->field['marker_tooltip'] );
|
||||
|
||||
if ( ! empty( $the_lat ) && ! empty( $the_long ) ) {
|
||||
$full = '';
|
||||
}
|
||||
|
||||
$hidden_style = ' style="display: none!important;" ';
|
||||
?>
|
||||
<div
|
||||
class="redux_framework_google_maps <?php echo esc_attr( $this->field['class'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
data-idx=""
|
||||
data-delay-render="<?php echo esc_attr( $this->field['delay_render'] ); ?>"
|
||||
data-scroll-wheel="<?php echo esc_attr( $this->field['scroll_wheel'] ); ?>"
|
||||
data-street-view="<?php echo esc_attr( $this->field['street_view_control'] ); ?>"
|
||||
data-map-type="<?php echo esc_attr( $this->field['map_type_control'] ); ?>"
|
||||
data-marker-tooltip="<?php echo esc_attr( $marker_tooltip ); ?>"
|
||||
data-geo-alert="<?php echo $geo_alert; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>"
|
||||
data-address="<?php echo $data_full; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>">
|
||||
|
||||
<input
|
||||
type="hidden"
|
||||
class="google_m_zoom_input"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[zoom]"
|
||||
value="<?php echo esc_attr( $the_zoom ); ?>"
|
||||
/>
|
||||
|
||||
<?php $is_hidden = $show_controls ? '' : 'hidden'; ?>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_autocomplete"></label>
|
||||
<input
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_autocomplete"
|
||||
class="google_m_controls google_m_autocomplete <?php echo esc_attr( $is_hidden ); ?>" type="text"
|
||||
value="<?php echo esc_attr( trim( $full ) ); ?>"
|
||||
placeholder="<?php echo esc_attr( $this->field['placeholder'] ); ?>"/>
|
||||
|
||||
<div
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_type_selector"
|
||||
class="google_m_controls <?php echo esc_attr( $is_hidden ); ?>">
|
||||
|
||||
<input class="noUpdate" type="radio" name="type" id="changetype-all-<?php echo esc_attr( $this->field['id'] ); ?>" checked="checked"/>
|
||||
<label for="changetype-all-<?php echo esc_attr( $this->field['id'] ); ?>"><?php esc_html_e( 'All', 'redux-framework' ); ?></label>
|
||||
|
||||
<input class="noUpdate" type="radio" name="type" id="changetype-establishment-<?php echo esc_attr( $this->field['id'] ); ?>"/>
|
||||
<label for="changetype-establishment-<?php echo esc_attr( $this->field['id'] ); ?>"><?php esc_html_e( 'Place', 'redux-framework' ); ?></label>
|
||||
|
||||
<input class="noUpdate" type="radio" name="type" id="changetype-address-<?php echo esc_attr( $this->field['id'] ); ?>"/>
|
||||
<label for="changetype-address-<?php echo esc_attr( $this->field['id'] ); ?>"><?php esc_html_e( 'Address', 'redux-framework' ); ?></label>
|
||||
|
||||
<input class="noUpdate" type="radio" name="type" id="changetype-geocode-<?php echo esc_attr( $this->field['id'] ); ?>"/>
|
||||
<label for="changetype-geocode-<?php echo esc_attr( $this->field['id'] ); ?>"><?php esc_html_e( 'Geo', 'redux-framework' ); ?></label>
|
||||
</div>
|
||||
|
||||
<div
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_map_canvas"
|
||||
class="google_m_canvas"
|
||||
data-default-long="<?php echo esc_attr( $the_long ); ?>"
|
||||
data-default-lat="<?php echo esc_attr( $the_lat ); ?>"
|
||||
data-default-zoom="<?php echo esc_attr( $the_zoom ); ?>"
|
||||
<?php echo $map_height; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
</div>
|
||||
|
||||
<div class="google_maps_address_results">
|
||||
<?php $is_hidden = $show_address ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper street-address" <?php echo $is_hidden; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_street_number"><?php esc_html_e( 'Address', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_street_number"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[street_number]"
|
||||
value="<?php echo esc_attr( $this->value['street_number'] ); ?>"
|
||||
class="slimField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['street_number'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div class="input_wrapper route" <?php echo $is_hidden; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_route"><?php esc_html_e( 'Street', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_route"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[route]"
|
||||
value="<?php echo esc_attr( $this->value['route'] ); ?>"
|
||||
class="wideField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['route'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_city ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper city" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_locality"><?php esc_html_e( 'City', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_locality"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[locality]"
|
||||
value="<?php echo esc_attr( $this->value['locality'] ); ?>"
|
||||
class="wideField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['locality'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_state ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper state" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_administrative_area_level_1"><?php esc_html_e( 'State', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_administrative_area_level_1"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[administrative_area_level_1]"
|
||||
value="<?php echo esc_attr( $this->value['administrative_area_level_1'] ); ?>"
|
||||
class="slimField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['administrative_area_level_1'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_postal ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper zip-code" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_postal_code"><?php esc_html_e( 'ZIP Code', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_postal_code"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[postal_code]"
|
||||
value="<?php echo esc_attr( $this->value['postal_code'] ); ?>"
|
||||
class="slimField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['postal_code'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_country ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper country" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_country"><?php esc_html_e( 'Country', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_country"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[country]"
|
||||
value="<?php echo esc_attr( $this->value['country'] ); ?>"
|
||||
class="wideField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['country'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_lat ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper latitude" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_latitude"><?php esc_html_e( 'Latitude', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_latitude"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[latitude]"
|
||||
value="<?php echo esc_attr( $this->value['latitude'] ); ?>"
|
||||
class="wideField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['latitude'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_long ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper longitude" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_longitude"><?php esc_html_e( 'Longitude', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_longitude"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[longitude]"
|
||||
value="<?php echo esc_attr( $this->value['longitude'] ); ?>"
|
||||
class="wideField field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['longitude'] ); ?>"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<?php $is_hidden = $show_marker_info ? '' : $hidden_style; ?>
|
||||
<div class="input_wrapper marker-info" <?php echo( $is_hidden ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
|
||||
<label for="<?php echo esc_attr( $this->field['id'] ); ?>_marker_info"><?php esc_html_e( 'Marker Info', 'redux-framework' ); ?></label>
|
||||
<textarea
|
||||
data-id="<?php echo esc_attr( $this->field['id'] ); ?>"
|
||||
id="<?php echo esc_attr( $this->field['id'] ); ?>_marker_info"
|
||||
name="<?php echo esc_attr( $this->field['name'] . $this->field['name_suffix'] ); ?>[marker_info]"
|
||||
class="field"
|
||||
data-default-value="<?php echo esc_attr( $this->value['marker_info'] ); ?>"
|
||||
rows="3"
|
||||
type="text"><?php echo esc_textarea( $this->value['marker_info'] ); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<?php if ( $this->field['show_api_key'] ) { ?>
|
||||
<div class="input google_m_api_key">
|
||||
<a href="javascript:void(0);" class="button button-secondary google_m_api_key_button"><?php esc_html_e( 'Google Map API Key', 'redux-framework' ); ?></a>
|
||||
<div class="google_m_api_key_wrapper">
|
||||
<p class="description" id="google_m_api_key_description">
|
||||
<?php
|
||||
$api_key_site = ' ' . sprintf( '<a href="https://console.developers.google.com/flows/enableapi?apiid=maps_backend&keyType=CLIENT_SIDE&reusekey=true" target="_blank">%s</a>', esc_html__( 'Get an API Key', 'redux-framework' ) ) . ' ';
|
||||
$usage_limit_site = ' ' . sprintf( '<a href="https://developers.google.com/maps/documentation/javascript/usage" target="_blank">%s</a>', esc_html__( 'Google Map Usage Limits', 'redux-framework' ) ) . ' ';
|
||||
|
||||
// translators: %1$s: Google Maps API Key url. %2$s: Google Maps Usage URL.
|
||||
echo sprintf( esc_html__( 'Google Maps supports 25,000 free map loads per 24 hours for 90 consecutive days. In the events you run a high volume site, you may need to obtain an API Key to continue using Google Map output beyond the free quota. To sign up for an API Key, please visit the %1$s site. For more information about Google Map usage limits, please visit the %2$s guide.', 'redux-framework' ), $api_key_site, $usage_limit_site ) . '<br><br>' . esc_html__( 'Once you have obtained an API Key, please enter it in the text box below and save the options panel.', 'redux-framework' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
</p>
|
||||
<label for="google_m_api_key_input"><?php esc_html_e( 'API Key', 'redux-framework' ); ?></label>
|
||||
<input
|
||||
type="text"
|
||||
value="<?php echo esc_attr( $this->api_key ); ?>"
|
||||
name="<?php echo esc_attr( $this->parent->args['opt_name'] ); ?>[google_map_api_key]"
|
||||
id="google_m_api_key_input" class="large-text"/>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Function.
|
||||
* If this field requires any scripts, or css define this function and register/enqueue the scripts/css
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function enqueue() {
|
||||
$min = Redux_Functions::isMin();
|
||||
|
||||
$api_key = '';
|
||||
if ( ! empty( $this->api_key ) ) {
|
||||
$api_key = $this->api_key;
|
||||
}
|
||||
|
||||
wp_register_script(
|
||||
'redux-field-google-maps',
|
||||
$this->url . 'redux-google-maps' . $min . '.js',
|
||||
array( 'jquery', 'redux-js' ),
|
||||
Redux_Extension_Google_Maps::$version,
|
||||
true
|
||||
);
|
||||
|
||||
if ( ! wp_script_is( 'redux-field-google-maps' ) ) {
|
||||
$script = '(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})({
|
||||
key:"' . $api_key . '",
|
||||
v:"' . $this->field['map_version'] . '",
|
||||
libraries:"places",
|
||||
callback:"initMap"
|
||||
});';
|
||||
|
||||
wp_add_inline_script( 'redux-field-google-maps', $script );
|
||||
}
|
||||
|
||||
wp_enqueue_script( 'redux-field-google-maps' );
|
||||
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-google-maps',
|
||||
$this->url . 'redux-google-maps.css',
|
||||
array(),
|
||||
Redux_Extension_Google_Maps::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
@@ -0,0 +1,45 @@
|
||||
.redux-main .redux-container-google_maps .google_m_api_key { padding-bottom: 10px; clear: left; padding-top: 20px; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper { display: none; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper label { display: block !important; position: relative; font-size: 12px !important; text-align: left; color: #999999; margin: 4px 0 2px 0 !important; cursor: default; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper .description { margin-bottom: 7px; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results { padding-top: 20px; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results .latitude { clear: left; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results .marker-info { clear: left !important; height: 75px !important; width: 100% !important; margin-bottom: 10px !important; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results label { display: block !important; position: relative; font-size: 12px !important; text-align: left; color: #999999; margin: 4px 0 2px 0 !important; cursor: default; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper { display: block; position: relative; float: left; clear: none; margin: 0 10px 0 0; height: 57px; -webkit-box-sizing: border-box; box-sizing: border-box; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper:nth-child(odd) { margin-right: 10px !important; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper:nth-child(even) { margin-right: 10px !important; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_canvas { margin: 0; padding: 0; height: 250px; width: 100%; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_canvas img { max-width: initial !important; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_autocomplete { background-color: #fff; color: #B5B5B5; font-family: Roboto, system-ui; font-size: 15px; font-weight: 300; margin-left: 12px; padding: 0 11px 0 13px; text-overflow: ellipsis; width: 50%; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_m_autocomplete:focus { border-color: #4d90fe; }
|
||||
|
||||
.redux-main .redux-container-google_maps .google_map_address_results { border: 1px solid #CBCBCB; background-color: #EDEDED; width: 100%; padding: 5px; }
|
||||
|
||||
.redux-main .redux-container-google_maps .field { width: 99%; }
|
||||
|
||||
.redux-main .redux-container-google_maps .slimField { width: 80px; }
|
||||
|
||||
.redux-main .redux-container-google_maps .wideField { width: 150px !important; }
|
||||
|
||||
.redux-main .google_m_controls { color: #fff; background-color: #4d90fe; padding: 5px 11px 0 11px; width: 50%; margin-top: 7px; border: 1px solid transparent; border-radius: 2px 0 0 2px; -webkit-box-sizing: border-box; box-sizing: border-box; height: 32px; outline: none; -webkit-box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); }
|
||||
|
||||
.redux-main .google_m_controls label { margin-left: -5px !important; margin-right: 7px !important; font-size: 12px; }
|
||||
|
||||
/*# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVkdXgtZ29vZ2xlLW1hcHMuY3NzIiwic291cmNlcyI6WyJyZWR1eC1nb29nbGUtbWFwcy5zY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLEFBRVEsV0FGRyxDQUNQLDRCQUE0QixDQUN4QixpQkFBaUIsQ0FBQyxFQUNkLGNBQWMsRUFBRSxJQUFJLEVBQ3BCLEtBQUssRUFBRSxJQUFJLEVBQ1gsV0FBVyxFQUFFLElBQUksR0FtQnBCOztBQXhCVCxBQU9ZLFdBUEQsQ0FDUCw0QkFBNEIsQ0FDeEIsaUJBQWlCLENBS2IseUJBQXlCLENBQUMsRUFDdEIsT0FBTyxFQUFFLElBQUksR0FlaEI7O0FBdkJiLEFBVWdCLFdBVkwsQ0FDUCw0QkFBNEIsQ0FDeEIsaUJBQWlCLENBS2IseUJBQXlCLENBR3JCLEtBQUssQ0FBQyxFQUNGLE9BQU8sRUFBRSxnQkFBZ0IsRUFDekIsUUFBUSxFQUFFLFFBQVEsRUFDbEIsU0FBUyxFQUFFLGVBQWUsRUFDMUIsVUFBVSxFQUFFLElBQUksRUFDaEIsS0FBSyxFQUFFLE9BQU8sRUFDZCxNQUFNLEVBQUUsc0JBQXNCLEVBQzlCLE1BQU0sRUFBRSxPQUFPLEdBQ2xCOztBQWxCakIsQUFvQmdCLFdBcEJMLENBQ1AsNEJBQTRCLENBQ3hCLGlCQUFpQixDQUtiLHlCQUF5QixDQWFyQixZQUFZLENBQUMsRUFDVCxhQUFhLEVBQUUsR0FBRyxHQUNyQjs7QUF0QmpCLEFBMEJRLFdBMUJHLENBQ1AsNEJBQTRCLENBeUJ4Qiw0QkFBNEIsQ0FBQyxFQUN6QixXQUFXLEVBQUUsSUFBSSxHQXdDcEI7O0FBbkVULEFBNkJZLFdBN0JELENBQ1AsNEJBQTRCLENBeUJ4Qiw0QkFBNEIsQ0FHeEIsU0FBUyxDQUFDLEVBQ04sS0FBSyxFQUFFLElBQUksR0FDZDs7QUEvQmIsQUFpQ1ksV0FqQ0QsQ0FDUCw0QkFBNEIsQ0F5QnhCLDRCQUE0QixDQU94QixZQUFZLENBQUMsRUFDVCxLQUFLLEVBQUUsSUFBSSxDQUFBLFVBQVUsRUFDckIsTUFBTSxFQUFFLElBQUksQ0FBQSxVQUFVLEVBQ3RCLEtBQUssRUFBRSxJQUFJLENBQUEsVUFBVSxFQUNyQixhQUFhLEVBQUUsSUFBSSxDQUFBLFVBQVUsR0FDaEM7O0FBdENiLEFBd0NZLFdBeENELENBQ1AsNEJBQTRCLENBeUJ4Qiw0QkFBNEIsQ0FjeEIsS0FBSyxDQUFDLEVBQ0YsT0FBTyxFQUFFLEtBQUssQ0FBQSxVQUFVLEVBQ3hCLFFBQVEsRUFBRSxRQUFRLEVBQ2xCLFNBQVMsRUFBRSxlQUFlLEVBQzFCLFVBQVUsRUFBRSxJQUFJLEVBQ2hCLEtBQUssRUFBRSxPQUFPLEVBQ2QsTUFBTSxFQUFFLHNCQUFzQixFQUM5QixNQUFNLEVBQUUsT0FBTyxHQUNsQjs7QUFoRGIsQUFrRFksV0FsREQsQ0FDUCw0QkFBNEIsQ0F5QnhCLDRCQUE0QixDQXdCeEIsY0FBYyxDQUFDLEVBQ1gsT0FBTyxFQUFFLEtBQUssRUFDZCxRQUFRLEVBQUUsUUFBUSxFQUNsQixLQUFLLEVBQUUsSUFBSSxFQUNYLEtBQUssRUFBRSxJQUFJLEVBQ1gsTUFBTSxFQUFFLFVBQVUsRUFDbEIsTUFBTSxFQUFFLElBQUksRUFDWixVQUFVLEVBQUUsVUFBVSxHQVN6Qjs7QUFsRWIsQUEyRGdCLFdBM0RMLENBQ1AsNEJBQTRCLENBeUJ4Qiw0QkFBNEIsQ0F3QnhCLGNBQWMsQUFTVCxVQUFXLENBQUEsR0FBRyxFQUFFLEVBQ2IsWUFBWSxFQUFFLGVBQWUsR0FDaEM7O0FBN0RqQixBQStEZ0IsV0EvREwsQ0FDUCw0QkFBNEIsQ0F5QnhCLDRCQUE0QixDQXdCeEIsY0FBYyxBQWFULFVBQVcsQ0FBQSxJQUFJLEVBQUUsRUFDZCxZQUFZLEVBQUUsZUFBZSxHQUNoQzs7QUFqRWpCLEFBcUVRLFdBckVHLENBQ1AsNEJBQTRCLENBb0V4QixnQkFBZ0IsQ0FBQyxFQUNiLE1BQU0sRUFBRSxDQUFDLEVBQ1QsT0FBTyxFQUFFLENBQUMsRUFDVixNQUFNLEVBQUUsS0FBSyxFQUNiLEtBQUssRUFBRSxJQUFJLEdBS2Q7O0FBOUVULEFBMkVZLFdBM0VELENBQ1AsNEJBQTRCLENBb0V4QixnQkFBZ0IsQ0FNWixHQUFHLENBQUMsRUFDQSxTQUFTLEVBQUUsa0JBQWtCLEdBQ2hDOztBQTdFYixBQWdGUSxXQWhGRyxDQUNQLDRCQUE0QixDQStFeEIsc0JBQXNCLENBQUMsRUFDbkIsZ0JBQWdCLEVBQUUsSUFBSSxFQUN0QixLQUFLLEVBQUUsT0FBTyxFQUNkLFdBQVcsRUFBRSxpQkFBaUIsRUFDOUIsU0FBUyxFQUFFLElBQUksRUFDZixXQUFXLEVBQUUsR0FBRyxFQUNoQixXQUFXLEVBQUUsSUFBSSxFQUNqQixPQUFPLEVBQUUsYUFBYSxFQUN0QixhQUFhLEVBQUUsUUFBUSxFQUN2QixLQUFLLEVBQUUsR0FBRyxHQUtiOztBQTlGVCxBQTJGWSxXQTNGRCxDQUNQLDRCQUE0QixDQStFeEIsc0JBQXNCLEFBV2pCLE1BQU0sQ0FBQyxFQUNKLFlBQVksRUFBRSxPQUFPLEdBQ3hCOztBQTdGYixBQWdHUSxXQWhHRyxDQUNQLDRCQUE0QixDQStGeEIsMkJBQTJCLENBQUMsRUFDeEIsTUFBTSxFQUFFLGlCQUFpQixFQUN6QixnQkFBZ0IsRUFBRSxPQUFPLEVBQ3pCLEtBQUssRUFBRSxJQUFJLEVBQ1gsT0FBTyxFQUFFLEdBQUcsR0FDZjs7QUFyR1QsQUF1R1EsV0F2R0csQ0FDUCw0QkFBNEIsQ0FzR3hCLE1BQU0sQ0FBQyxFQUNILEtBQUssRUFBRSxHQUFHLEdBQ2I7O0FBekdULEFBMkdRLFdBM0dHLENBQ1AsNEJBQTRCLENBMEd4QixVQUFVLENBQUMsRUFDUCxLQUFLLEVBQUUsSUFBSSxHQUNkOztBQTdHVCxBQStHUSxXQS9HRyxDQUNQLDRCQUE0QixDQThHeEIsVUFBVSxDQUFDLEVBQ1AsS0FBSyxFQUFFLEtBQUssQ0FBQSxVQUFVLEdBQ3pCOztBQWpIVCxBQW9ISSxXQXBITyxDQW9IUCxrQkFBa0IsQ0FBQyxFQUNmLEtBQUssRUFBRSxJQUFJLEVBQ1gsZ0JBQWdCLEVBQUUsT0FBTyxFQUN6QixPQUFPLEVBQUUsZUFBZSxFQUN4QixLQUFLLEVBQUUsR0FBRyxFQUNWLFVBQVUsRUFBRSxHQUFHLEVBQ2YsTUFBTSxFQUFFLHFCQUFxQixFQUM3QixhQUFhLEVBQUUsV0FBVyxFQUMxQixVQUFVLEVBQUUsVUFBVSxFQUN0QixNQUFNLEVBQUUsSUFBSSxFQUNaLE9BQU8sRUFBRSxJQUFJLEVBQ2IsVUFBVSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLGtCQUFrQixHQU8zQzs7QUF0SUwsQUFpSVEsV0FqSUcsQ0FvSFAsa0JBQWtCLENBYWQsS0FBSyxDQUFDLEVBQ0YsV0FBVyxFQUFHLElBQUcsQ0FBQSxVQUFVLEVBQzNCLFlBQVksRUFBRSxHQUFHLENBQUEsVUFBVSxFQUMzQixTQUFTLEVBQUUsSUFBSSxHQUNsQiJ9 */
|
||||
|
||||
/*# sourceMappingURL=redux-google-maps.css.map */
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,550 @@
|
||||
/**
|
||||
* Field Google Map
|
||||
*/
|
||||
|
||||
/* global jQuery, document, redux_change, redux, google */
|
||||
|
||||
(function( $ ) {
|
||||
'use strict';
|
||||
|
||||
var g_map;
|
||||
var g_marker;
|
||||
var g_autoComplete;
|
||||
var g_LatLng;
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.google_maps = redux.field_objects.google_maps || {};
|
||||
|
||||
/* LIBRARY INIT */
|
||||
redux.field_objects.google_maps.init = function( selector ) {
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-google_maps:visible' );
|
||||
}
|
||||
|
||||
$( selector ).each(
|
||||
function( i ) {
|
||||
var containerID;
|
||||
var delayRender;
|
||||
|
||||
var el = $( this );
|
||||
var parent = el;
|
||||
|
||||
if ( ! el.hasClass( 'redux-field-container' ) ) {
|
||||
parent = el.parents( '.redux-field-container:first' );
|
||||
}
|
||||
|
||||
if ( parent.is( ':hidden' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( parent.hasClass( 'redux-field-init' ) ) {
|
||||
parent.removeClass( 'redux-field-init' );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get container ID.
|
||||
containerID = el.find( '.redux_framework_google_maps' ).attr( 'id' );
|
||||
|
||||
// Check for delay render, which is useful for calling a map
|
||||
// render after javascript load.
|
||||
delayRender = Boolean( el.find( '.redux_framework_google_maps' ).data( 'delay-render' ) );
|
||||
|
||||
// API Key button.
|
||||
redux.field_objects.google_maps.clickHandler( el );
|
||||
|
||||
// Init our maps.
|
||||
redux.field_objects.google_maps.initMap( el, i, containerID, delayRender );
|
||||
|
||||
// Fucking radio button won't check on its own, for some reason.
|
||||
setTimeout(
|
||||
function() {
|
||||
$( '#changetype-all' ).prop( 'checked', true );
|
||||
},
|
||||
1
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/* API BUTTON CLICK HANDLER */
|
||||
redux.field_objects.google_maps.clickHandler = function( el ) {
|
||||
|
||||
// Find the API Key button and react on click.
|
||||
el.find( '.google_m_api_key_button' ).on(
|
||||
'click',
|
||||
function() {
|
||||
|
||||
// Find message wrapper.
|
||||
var wrapper = el.find( '.google_m_api_key_wrapper' );
|
||||
|
||||
if ( wrapper.is( ':visible' ) ) {
|
||||
|
||||
// If wrapper is visible, close it.
|
||||
wrapper.slideUp(
|
||||
'fast',
|
||||
function() {
|
||||
el.find( '#google_m_api_key_input' ).trigger( 'focus' );
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
||||
// If wrapper is visible, open it.
|
||||
wrapper.slideDown(
|
||||
'medium',
|
||||
function() {
|
||||
el.find( '#google_m_api_key_input' ).trigger( 'focus' );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Auto select autocomplete contents,
|
||||
// since Google doesn't do this inherently.
|
||||
el.find( '.google_m_autocomplete' ).on(
|
||||
'click',
|
||||
function( e ) {
|
||||
this.trigger( 'focus' );
|
||||
this.trigger( 'select' );
|
||||
e.preventDefault();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/* MAP RENDER FUNCTION */
|
||||
redux.field_objects.google_maps.renderMap = async function( el, mapClass ) {
|
||||
var scrollWheel;
|
||||
var streetView;
|
||||
var mapType;
|
||||
var address;
|
||||
var defLat;
|
||||
var defLong;
|
||||
var defaultZoom;
|
||||
var mapOptions;
|
||||
var geocoder;
|
||||
|
||||
var noLatLng = false;
|
||||
var containerID = el.find( '.redux_framework_google_maps' ).attr( 'id' );
|
||||
|
||||
// Set IDs to variables.
|
||||
var autocomplete = containerID + '_autocomplete';
|
||||
var canvas = containerID + '_map_canvas';
|
||||
var canvasId = $( '#' + canvas );
|
||||
var ac;
|
||||
|
||||
// Create the autocomplete object, restricting the search
|
||||
// to geographical location types.
|
||||
g_autoComplete = await google.maps.importLibrary( 'places' );
|
||||
|
||||
ac = new g_autoComplete.Autocomplete(
|
||||
( document.getElementById( autocomplete ) ),
|
||||
{
|
||||
types: ['geocode']
|
||||
}
|
||||
);
|
||||
|
||||
// Data bindings.
|
||||
scrollWheel = Boolean( mapClass.data( 'scroll-wheel' ) );
|
||||
streetView = Boolean( mapClass.data( 'street-view' ) );
|
||||
mapType = Boolean( mapClass.data( 'map-type' ) );
|
||||
|
||||
address = mapClass.data( 'address' );
|
||||
address = decodeURIComponent( address );
|
||||
address = address.trim();
|
||||
|
||||
// Set default Lat/lng.
|
||||
defLat = canvasId.data( 'default-lat' );
|
||||
defLong = canvasId.data( 'default-long' );
|
||||
defaultZoom = canvasId.data( 'default-zoom' );
|
||||
|
||||
// Eval whether to set maps based on lat/lng or address.
|
||||
if ( '' !== address ) {
|
||||
if ( '' === defLat || '' === defLong ) {
|
||||
noLatLng = true;
|
||||
}
|
||||
} else {
|
||||
noLatLng = false;
|
||||
}
|
||||
|
||||
// Can't have empty values, or the map API will complain.
|
||||
// Set default for middle of the United States.
|
||||
defLat = defLat ? defLat : 39.11676722061108;
|
||||
defLong = defLong ? defLong : - 100.47761000000003;
|
||||
|
||||
if ( noLatLng ) {
|
||||
|
||||
// If displaying map based on an address.
|
||||
geocoder = new google.maps.Geocoder();
|
||||
|
||||
// Set up Geocode and pass address.
|
||||
geocoder.geocode(
|
||||
{ 'address': address },
|
||||
function( results, status ) {
|
||||
var latitude;
|
||||
var longitude;
|
||||
|
||||
// Function results.
|
||||
if ( status === google.maps.GeocoderStatus.OK ) {
|
||||
|
||||
// A good address was passed.
|
||||
g_LatLng = results[0].geometry.location;
|
||||
|
||||
// Set map options.
|
||||
mapOptions = {
|
||||
center: g_LatLng,
|
||||
zoom: defaultZoom,
|
||||
streetViewControl: streetView,
|
||||
mapTypeControl: mapType,
|
||||
scrollwheel: scrollWheel,
|
||||
mapTypeControlOptions: {
|
||||
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
|
||||
position: google.maps.ControlPosition.LEFT_BOTTOM
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Create map.
|
||||
g_map = new google.maps.Map( document.getElementById( canvas ), mapOptions );
|
||||
|
||||
// Render map controls.
|
||||
redux.field_objects.google_maps.renderControls( el, autocomplete, mapClass );
|
||||
|
||||
// Get and set lat/long data.
|
||||
latitude = el.find( '#' + containerID + '_latitude' );
|
||||
latitude.val( results[0].geometry.location.lat() );
|
||||
|
||||
longitude = el.find( '#' + containerID + '_longitude' );
|
||||
longitude.val( results[0].geometry.location.lng() );
|
||||
} else {
|
||||
|
||||
// No data found, alert the user.
|
||||
alert( 'Geocode was not successful for the following reason: ' + status );
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
|
||||
// If displaying map based on an lat/lng.
|
||||
g_LatLng = new google.maps.LatLng( defLat, defLong );
|
||||
|
||||
// Set map options.
|
||||
mapOptions = {
|
||||
center: g_LatLng,
|
||||
zoom: defaultZoom, // Start off far unless an item is selected, set by php.
|
||||
streetViewControl: streetView,
|
||||
mapTypeControl: mapType,
|
||||
scrollwheel: scrollWheel,
|
||||
mapTypeControlOptions: {
|
||||
style: google.maps.MapTypeControlStyle.HORIZONTAL_BAR,
|
||||
position: google.maps.ControlPosition.LEFT_BOTTOM
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// Create the map.
|
||||
g_map = new google.maps.Map( document.getElementById( canvas ), mapOptions );
|
||||
|
||||
// Render map controls.
|
||||
redux.field_objects.google_maps.renderControls( el, autocomplete, mapClass );
|
||||
}
|
||||
};
|
||||
|
||||
/* INIT MAP FUNCTION */
|
||||
redux.field_objects.google_maps.initMap = function( el, idx, containerID, delayRender ) {
|
||||
var delayed;
|
||||
|
||||
// Pull the map class.
|
||||
var mapClass = el.find( '.redux_framework_google_maps' );
|
||||
|
||||
// Add map index to data attr. Why, say we want to use delay_render,
|
||||
// and want to init the map later on. You'd need the index number in the
|
||||
// event of multiple map instances. This allows one to retrieve it
|
||||
// later.
|
||||
$( mapClass ).attr( 'data-idx', idx );
|
||||
if ( true === delayRender ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Map has been rendered, no need to process again.
|
||||
if ( $( '#' + containerID ).hasClass( 'rendered' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If map is set to delay render and has been initiated
|
||||
// from another scrip, add the 'render' class so rendering
|
||||
// does not occur. it messes things up.
|
||||
delayed = Boolean( mapClass.data( 'delay-render' ) );
|
||||
if ( true === delayed ) {
|
||||
mapClass.addClass( 'rendered' );
|
||||
}
|
||||
|
||||
// Render the map.
|
||||
redux.field_objects.google_maps.renderMap( el, mapClass );
|
||||
};
|
||||
|
||||
/* RENDER CONTROLS FUNCTION */
|
||||
redux.field_objects.google_maps.renderControls = function( el, autoComplete, mapClass ) {
|
||||
var markerTooltip;
|
||||
var infoWindow;
|
||||
|
||||
// Set variables.
|
||||
var containerID = el.find( '.redux_framework_google_maps' ).attr( 'id' );
|
||||
var controls = containerID + '_type_selector';
|
||||
|
||||
// Get HTML.
|
||||
var input = document.getElementById( autoComplete );
|
||||
var types = document.getElementById( controls );
|
||||
|
||||
// Set objects into the map.
|
||||
g_map.controls[google.maps.ControlPosition.TOP_LEFT].push( input );
|
||||
g_map.controls[google.maps.ControlPosition.TOP_LEFT].push( types );
|
||||
|
||||
// Bind objects to the map.
|
||||
g_autoComplete = new google.maps.places.Autocomplete( input );
|
||||
g_autoComplete.bindTo( 'bounds', g_map );
|
||||
|
||||
// Get the marker tooltip data.
|
||||
markerTooltip = mapClass.data( 'marker-tooltip' );
|
||||
markerTooltip = decodeURIComponent( markerTooltip );
|
||||
|
||||
// Create infoWindow.
|
||||
infoWindow = new google.maps.InfoWindow();
|
||||
|
||||
// Create marker.
|
||||
g_marker = new google.maps.Marker(
|
||||
{
|
||||
position: g_LatLng,
|
||||
map: g_map,
|
||||
anchorPoint: new google.maps.Point( 0, - 29 ),
|
||||
draggable: true,
|
||||
title: markerTooltip,
|
||||
animation: google.maps.Animation.DROP
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
// Add Event Listeners.
|
||||
redux.field_objects.google_maps.addListeners( el, mapClass, g_marker, infoWindow );
|
||||
};
|
||||
|
||||
/* ADD LISTENERS FUNCTION */
|
||||
redux.field_objects.google_maps.addListeners = function( el, mapClass, marker ) {
|
||||
var infoWindow;
|
||||
|
||||
// Set variables.
|
||||
var containerID = el.find( '.redux_framework_google_maps' ).attr( 'id' );
|
||||
var latitude = containerID + '_latitude';
|
||||
var longitude = containerID + '_longitude';
|
||||
var marker_info = containerID + '_marker_info';
|
||||
var geoAlert = mapClass.data( 'geo-alert' );
|
||||
geoAlert = decodeURIComponent( geoAlert );
|
||||
|
||||
// Place change.
|
||||
google.maps.event.addListener(
|
||||
g_autoComplete,
|
||||
'place_changed',
|
||||
function() {
|
||||
var place;
|
||||
var address;
|
||||
|
||||
infoWindow.close();
|
||||
marker.setVisible( false );
|
||||
|
||||
// Get place data.
|
||||
place = g_autoComplete.getPlace();
|
||||
|
||||
// Display alert if something went wrong.
|
||||
if ( ! place.geometry ) {
|
||||
window.alert( geoAlert );
|
||||
return;
|
||||
}
|
||||
|
||||
// If the place has a geometry, then present it on a map.
|
||||
if ( place.geometry.viewport ) {
|
||||
g_map.fitBounds( place.geometry.viewport );
|
||||
} else {
|
||||
g_map.setCenter( place.geometry.location );
|
||||
g_map.setZoom( 17 ); // Why 17? Because it looks good.
|
||||
}
|
||||
|
||||
// Set the marker icon.
|
||||
marker.setIcon(
|
||||
({
|
||||
url: place.icon,
|
||||
size: new google.maps.Size( 71, 71 ),
|
||||
origin: new google.maps.Point( 0, 0 ),
|
||||
anchor: new google.maps.Point( 17, 34 ),
|
||||
scaledSize: new google.maps.Size( 35, 35 )
|
||||
})
|
||||
);
|
||||
|
||||
// Set marker position and display.
|
||||
marker.setPosition( place.geometry.location );
|
||||
marker.setVisible( true );
|
||||
|
||||
// Form array of address components.
|
||||
address = '';
|
||||
if ( place.address_components ) {
|
||||
address = [( place.address_components[0] && place.address_components[0].short_name || '' ),
|
||||
( place.address_components[1] && place.address_components[1].short_name || '' ),
|
||||
( place.address_components[2] && place.address_components[2].short_name || '' )].join( ' ' );
|
||||
}
|
||||
|
||||
// Set the default marker info window with address data.
|
||||
infoWindow.setContent( '<div><strong>' + place.name + '</strong><br>' + address );
|
||||
infoWindow.open( g_map, marker );
|
||||
|
||||
// Run Geolocation.
|
||||
redux.field_objects.google_maps.geoLocate();
|
||||
|
||||
// Fill in address inputs.
|
||||
redux.field_objects.google_maps.fillInAddress( el, latitude, longitude );
|
||||
}
|
||||
);
|
||||
|
||||
// Search radio buttons.
|
||||
redux.field_objects.google_maps.setupClickListener( 'changetype-all-' + containerID, [] );
|
||||
redux.field_objects.google_maps.setupClickListener( 'changetype-address-' + containerID, ['address'] );
|
||||
redux.field_objects.google_maps.setupClickListener( 'changetype-establishment-' + containerID, ['establishment'] );
|
||||
redux.field_objects.google_maps.setupClickListener( 'changetype-geocode-' + containerID, ['geocode'] );
|
||||
|
||||
// Marker drag.
|
||||
google.maps.event.addListener(
|
||||
marker,
|
||||
'drag',
|
||||
function( event ) {
|
||||
document.getElementById( latitude ).value = event.latLng.lat();
|
||||
document.getElementById( longitude ).value = event.latLng.lng();
|
||||
}
|
||||
);
|
||||
|
||||
// End marker drag.
|
||||
google.maps.event.addListener(
|
||||
marker,
|
||||
'dragend',
|
||||
function() {
|
||||
redux_change( el.find( '.redux_framework_google_maps' ) );
|
||||
}
|
||||
);
|
||||
|
||||
// Zoom Changed.
|
||||
g_map.addListener(
|
||||
'zoom_changed',
|
||||
function() {
|
||||
el.find( '.google_m_zoom_input' ).val( g_map.getZoom() );
|
||||
}
|
||||
);
|
||||
|
||||
// Marker Info Window.
|
||||
infoWindow = new google.maps.InfoWindow();
|
||||
|
||||
google.maps.event.addListener(
|
||||
marker,
|
||||
'click',
|
||||
function() {
|
||||
var infoValue = document.getElementById( marker_info ).value;
|
||||
|
||||
if ( '' !== infoValue ) {
|
||||
infoWindow.setContent( infoValue );
|
||||
infoWindow.open( g_map, g_marker );
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/* FILL IN ADDRESS FUNCTION */
|
||||
redux.field_objects.google_maps.fillInAddress = function( el, latitude, longitude ) {
|
||||
|
||||
// Set variables.
|
||||
var containerID = el.find( '.redux_framework_google_maps' ).attr( 'id' );
|
||||
|
||||
// What if someone only wants city, or state, ect...
|
||||
// gotta do it this way to check for the address!
|
||||
// need to check each of the returned components to see what is returned.
|
||||
var componentForm = {
|
||||
street_number: 'short_name',
|
||||
route: 'long_name',
|
||||
locality: 'long_name',
|
||||
administrative_area_level_1: 'short_name',
|
||||
country: 'long_name',
|
||||
postal_code: 'short_name'
|
||||
};
|
||||
|
||||
// Get the place details from the autocomplete object.
|
||||
var place = g_autoComplete.getPlace();
|
||||
|
||||
var component;
|
||||
var i;
|
||||
var addressType;
|
||||
var _d_addressType;
|
||||
var val;
|
||||
var len;
|
||||
|
||||
document.getElementById( latitude ).value = place.geometry.location.lat();
|
||||
document.getElementById( longitude ).value = place.geometry.location.lng();
|
||||
|
||||
for ( component in componentForm ) {
|
||||
if ( componentForm.hasOwnProperty( component ) ) {
|
||||
|
||||
// Push in the dynamic form element ID again.
|
||||
component = containerID + '_' + component;
|
||||
|
||||
// Assign to proper place.
|
||||
document.getElementById( component ).value = '';
|
||||
document.getElementById( component ).disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get each component of the address from the place details
|
||||
// and fill the corresponding field on the form.
|
||||
len = place.address_components.length;
|
||||
|
||||
for ( i = 0; i < len; i += 1 ) {
|
||||
addressType = place.address_components[i].types[0];
|
||||
|
||||
if ( componentForm[addressType] ) {
|
||||
|
||||
// Push in the dynamic form element ID again.
|
||||
_d_addressType = containerID + '_' + addressType;
|
||||
|
||||
// Get the original.
|
||||
val = place.address_components[i][componentForm[addressType]];
|
||||
|
||||
// Assign to proper place.
|
||||
document.getElementById( _d_addressType ).value = val;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
redux.field_objects.google_maps.setupClickListener = function( id, types ) {
|
||||
var radioButton = document.getElementById( id );
|
||||
|
||||
google.maps.event.addListener(
|
||||
radioButton,
|
||||
'click',
|
||||
function() {
|
||||
g_autoComplete.setTypes( types );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.google_maps.geoLocate = function() {
|
||||
if ( navigator.geolocation ) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
function( position ) {
|
||||
var geolocation = new google.maps.LatLng( position.coords.latitude, position.coords.longitude );
|
||||
|
||||
var circle = new google.maps.Circle(
|
||||
{
|
||||
center: geolocation,
|
||||
radius: position.coords.accuracy
|
||||
}
|
||||
);
|
||||
|
||||
g_autoComplete.setBounds( circle.getBounds() );
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
.redux-main .redux-container-google_maps .google_m_api_key{padding-bottom:10px;clear:left;padding-top:20px}.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper{display:none}.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper label{display:block !important;position:relative;font-size:12px !important;text-align:left;color:#999;margin:4px 0 2px 0 !important;cursor:default}.redux-main .redux-container-google_maps .google_m_api_key .google_m_api_key_wrapper .description{margin-bottom:7px}.redux-main .redux-container-google_maps .google_maps_address_results{padding-top:20px}.redux-main .redux-container-google_maps .google_maps_address_results .latitude{clear:left}.redux-main .redux-container-google_maps .google_maps_address_results .marker-info{clear:left !important;height:75px !important;width:100% !important;margin-bottom:10px !important}.redux-main .redux-container-google_maps .google_maps_address_results label{display:block !important;position:relative;font-size:12px !important;text-align:left;color:#999;margin:4px 0 2px 0 !important;cursor:default}.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper{display:block;position:relative;float:left;clear:none;margin:0 10px 0 0;height:57px;-webkit-box-sizing:border-box;-o-box-sizing:border-box;box-sizing:border-box}.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper:nth-child(odd){margin-right:10px !important}.redux-main .redux-container-google_maps .google_maps_address_results .input_wrapper:nth-child(even){margin-right:10px !important}.redux-main .redux-container-google_maps .google_m_canvas{margin:0;padding:0;height:250px;width:100%}.redux-main .redux-container-google_maps .google_m_canvas img{max-width:initial !important}.redux-main .redux-container-google_maps .google_m_autocomplete{background-color:#fff;color:#b5b5b5;font-family:Roboto;font-size:15px;font-weight:300;margin-left:12px;padding:0 11px 0 13px;text-overflow:ellipsis;width:50%}.redux-main .redux-container-google_maps .google_m_autocomplete:focus{border-color:#4d90fe}.redux-main .redux-container-google_maps .google_map_address_results{border:1px solid #cbcbcb;background-color:#ededed;width:100%;padding:5px}.redux-main .redux-container-google_maps .field{width:99%}.redux-main .redux-container-google_maps .slimField{width:80px}.redux-main .redux-container-google_maps .wideField{width:150px !important}.redux-main .google_m_controls{color:#fff;background-color:#4d90fe;padding:5px 11px 0 11px;width:50%;margin-top:7px;border:1px solid transparent;border-radius:2px 0 0 2px;-webkit-box-sizing:border-box;box-sizing:border-box;-moz-box-sizing:border-box;height:32px;outline:0;-webkit-box-shadow:0 2px 6px rgba(0,0,0,0.3);box-shadow:0 2px 6px rgba(0,0,0,0.3)}.redux-main .google_m_controls label{margin-left:-5px !important;margin-right:7px !important;font-size:12px}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,136 @@
|
||||
.redux-main {
|
||||
.redux-container-google_maps {
|
||||
.google_m_api_key {
|
||||
padding-bottom: 10px;
|
||||
clear: left;
|
||||
padding-top: 20px;
|
||||
|
||||
.google_m_api_key_wrapper {
|
||||
display: none;
|
||||
|
||||
label {
|
||||
display: block !important;
|
||||
position: relative;
|
||||
font-size: 12px !important;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
margin: 4px 0 2px 0 !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.description {
|
||||
margin-bottom: 7px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.google_maps_address_results {
|
||||
padding-top: 20px;
|
||||
|
||||
.latitude {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.marker-info {
|
||||
clear: left!important;
|
||||
height: 75px!important;
|
||||
width: 100%!important;
|
||||
margin-bottom: 10px!important;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block!important;
|
||||
position: relative;
|
||||
font-size: 12px !important;
|
||||
text-align: left;
|
||||
color: #999999;
|
||||
margin: 4px 0 2px 0 !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.input_wrapper {
|
||||
display: block;
|
||||
position: relative;
|
||||
float: left;
|
||||
clear: none;
|
||||
margin: 0 10px 0 0;
|
||||
height: 57px;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:nth-child(odd) {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
|
||||
&:nth-child(even) {
|
||||
margin-right: 10px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.google_m_canvas {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 250px;
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
max-width: initial !important;
|
||||
}
|
||||
}
|
||||
|
||||
.google_m_autocomplete {
|
||||
background-color: #fff;
|
||||
color: #B5B5B5;
|
||||
font-family: Roboto, system-ui;
|
||||
font-size: 15px;
|
||||
font-weight: 300;
|
||||
margin-left: 12px;
|
||||
padding: 0 11px 0 13px;
|
||||
text-overflow: ellipsis;
|
||||
width: 50%;
|
||||
|
||||
&:focus {
|
||||
border-color: #4d90fe;
|
||||
}
|
||||
}
|
||||
|
||||
.google_map_address_results {
|
||||
border: 1px solid #CBCBCB;
|
||||
background-color: #EDEDED;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.field {
|
||||
width: 99%;
|
||||
}
|
||||
|
||||
.slimField {
|
||||
width: 80px;
|
||||
}
|
||||
|
||||
.wideField {
|
||||
width: 150px!important;
|
||||
}
|
||||
}
|
||||
|
||||
.google_m_controls {
|
||||
color: #fff;
|
||||
background-color: #4d90fe;
|
||||
padding: 5px 11px 0 11px;
|
||||
width: 50%;
|
||||
margin-top: 7px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 2px 0 0 2px;
|
||||
box-sizing: border-box;
|
||||
height: 32px;
|
||||
outline: none;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
|
||||
|
||||
label {
|
||||
margin-left: -5px!important;
|
||||
margin-right: 7px!important;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user