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,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Icon Select Extension Class
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Dovy Paukstys <dovy@reduxframework.com> & Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Extension_Icon_Select
|
||||
* @version 4.4.2
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Extension_Icon_Select' ) ) {
|
||||
|
||||
|
||||
/**
|
||||
* Main ReduxFramework icon_select extension class
|
||||
*
|
||||
* @since 3.1.6
|
||||
*/
|
||||
class Redux_Extension_Icon_Select extends Redux_Extension_Abstract {
|
||||
|
||||
/**
|
||||
* Extension version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public static $version = '4.4.2';
|
||||
|
||||
/**
|
||||
* Extension friendly name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $ext_name = 'Icon Select';
|
||||
|
||||
/**
|
||||
* ReduxFramework_Extension_Icon_Select constructor.
|
||||
*
|
||||
* @param ReduxFramework $redux ReduxFramework object.
|
||||
*/
|
||||
public function __construct( $redux ) {
|
||||
parent::__construct( $redux, __FILE__ );
|
||||
|
||||
$this->add_field( 'icon_select' );
|
||||
|
||||
add_action( 'wp_ajax_redux_get_icons', array( $this, 'get_icons' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add icons to modal.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_icons() {
|
||||
$nonce = ( ! empty( $_POST['nonce'] ) ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
|
||||
$icon_set = ( ! empty( $_POST['icon_set'] ) ) ? sanitize_text_field( wp_unslash( $_POST['icon_set'] ) ) : '';
|
||||
$select_text = ( ! empty( $_POST['select_text'] ) ) ? sanitize_text_field( wp_unslash( $_POST['select_text'] ) ) : '';
|
||||
|
||||
if ( ! wp_verify_nonce( $nonce, 'redux_icon_nonce' ) ) {
|
||||
wp_send_json_error( array( 'error' => esc_html__( 'Error: Invalid nonce verification.', 'redux-framework' ) ) );
|
||||
}
|
||||
|
||||
ob_start();
|
||||
|
||||
$class = '';
|
||||
|
||||
if ( 'font-awesome' === $icon_set ) {
|
||||
require_once Redux_Core::$dir . 'inc/lib/font-awesome-6-free.php';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$icon_lists = apply_filters( 'redux/extensions/icon_select/fontawesome/icons', redux_icon_select_fa_6_free() );
|
||||
} elseif ( 'dashicons' === $icon_set ) {
|
||||
require_once Redux_Core::$dir . 'inc/lib/dashicons.php';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$icon_lists = apply_filters( 'redux/extensions/icon_select/dashicons/icons', redux_get_dashicons() );
|
||||
} elseif ( 'elusive' === $icon_set ) {
|
||||
require_once Redux_Core::$dir . 'inc/lib/elusive-icons.php';
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$icon_lists = apply_filters( 'redux/extensions/icon_select/elusive/icons', redux_get_font_icons() );
|
||||
} else {
|
||||
$data = ( ! empty( $_POST['data'] ) ) ? ( wp_unslash( $_POST['data'] ) ) : ''; // phpcs:ignore WordPress.Security
|
||||
$data = json_decode( rawurldecode( $data ), true );
|
||||
$icons = '';
|
||||
|
||||
foreach ( $data as $arr_data ) {
|
||||
if ( $arr_data['title'] === $select_text ) {
|
||||
$icons = $arr_data['icons'];
|
||||
|
||||
$class = ( ! empty( $arr_data['class'] ) ? $arr_data['class'] . ' ' : '' );
|
||||
}
|
||||
}
|
||||
|
||||
// phpcs:ignore WordPress.NamingConventions.ValidHookName
|
||||
$icon_lists = apply_filters( 'redux/extensions/icon_select/custom/icons', $icons );
|
||||
}
|
||||
|
||||
if ( ! empty( $icon_lists ) ) {
|
||||
foreach ( $icon_lists as $list ) {
|
||||
|
||||
/**
|
||||
* Icon output.
|
||||
* Custom output for icon libraries that support different standards.
|
||||
*
|
||||
* @param string $default Original output.
|
||||
* @param string $title Title of the icon.
|
||||
* @param string $class Class of the icon.
|
||||
* @param string $icon_Set Selected Icon set.
|
||||
*
|
||||
* @since 4.4.2
|
||||
*/
|
||||
echo apply_filters( 'redux/extension/icon_select/' . $this->parent->args['opt_name'] . '/output', '<i title="' . esc_attr( $list ) . '" class="' . esc_attr( $class . ' ' . $list ) . '" /></i>', $list, $class, $select_text ); // phpcs:ignore WordPress.NamingConventions.ValidHookName, WordPress.Security.EscapeOutput
|
||||
}
|
||||
} else {
|
||||
echo '<div class="redux-error-text">' . esc_html__( 'No data available.', 'redux-framework' ) . '</div>';
|
||||
}
|
||||
|
||||
$content = ob_get_clean();
|
||||
|
||||
wp_send_json_success( array( 'content' => $content ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class_alias( 'Redux_Extension_Icon_Select', 'ReduxFramework_extension_icon_select' );
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,459 @@
|
||||
<?php
|
||||
/**
|
||||
* Redux Icon Select Field Class
|
||||
*
|
||||
* @package Redux Extentions
|
||||
* @author Dovy Paukstys <dovy@reduxframework.com> & Kevin Provance <kevin.provance@gmail.com>
|
||||
* @class Redux_Icon_Select
|
||||
* @version 4.4.2
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
// Don't duplicate me!
|
||||
if ( ! class_exists( 'Redux_Icon_Select' ) ) {
|
||||
|
||||
/**
|
||||
* Main ReduxFramework_icon_select class
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Redux_Icon_Select extends Redux_Field {
|
||||
|
||||
/**
|
||||
* Stylesheet URL array, for enqueue.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $stylesheet_url = array();
|
||||
|
||||
/**
|
||||
* Stylesheet data array.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $stylesheet_data = array();
|
||||
|
||||
/**
|
||||
* Error flag to prevent render and enqueue.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $is_error = false;
|
||||
/**
|
||||
* ReduxFramework_Icon_Select constructor.
|
||||
*
|
||||
* @param array $field Field array.
|
||||
* @param string $value Value.
|
||||
* @param ReduxFramework $redux ReduxFramework object.
|
||||
*
|
||||
* @throws ReflectionException Exception.
|
||||
*/
|
||||
public function __construct( $field = array(), $value = '', $redux = object ) {
|
||||
parent::__construct( $field, $value, $redux );
|
||||
|
||||
if ( empty( $field ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! is_array( $this->field['stylesheet'] ) ) {
|
||||
if ( '' !== $this->field['stylesheet'] ) {
|
||||
$this->stylesheet_data[] = array(
|
||||
'url' => $this->field['stylesheet'],
|
||||
'class' => $this->field['prefix'],
|
||||
'title' => basename( $this->field['stylesheet'] ),
|
||||
'icons' => $this->field['options'],
|
||||
'exclude' => $this->field['exclude_icons'],
|
||||
);
|
||||
|
||||
unset( $this->field['exclude_icons'] );
|
||||
unset( $this->field['options'] );
|
||||
unset( $this->field['stylesheet'] );
|
||||
unset( $this->field['prefix'] );
|
||||
}
|
||||
} else {
|
||||
$arr = $this->field['stylesheet'];
|
||||
|
||||
if ( isset( $arr['url'] ) || isset( $arr['title'] ) ) {
|
||||
$arr = array( $arr );
|
||||
}
|
||||
|
||||
foreach ( $arr as $idx => $val ) {
|
||||
$val['url'] = ! empty( $val['url'] ) ? $val['url'] : '';
|
||||
$val['title'] = ! empty( $val['title'] ) ? $val['title'] : basename( $val['url'] );
|
||||
$val['class'] = ! empty( $val['prefix'] ) ? $val['prefix'] : '';
|
||||
$val['icons'] = ! empty( $val['icons'] ) ? $val['icons'] : array();
|
||||
$val['exclude'] = ! empty( $val['exclude'] ) ? $val['exclude'] : '';
|
||||
$val['regex'] = ! empty( $val['regex'] ) ? $val['regex'] : '';
|
||||
|
||||
$arr[ $idx ] = $val;
|
||||
}
|
||||
|
||||
$this->stylesheet_data = $arr;
|
||||
}
|
||||
|
||||
if ( ! empty( $this->stylesheet_data ) ) {
|
||||
foreach ( $this->stylesheet_data as $idx => $sub_arr ) {
|
||||
if ( false === stripos( $sub_arr['url'], '//' ) ) {
|
||||
$this->stylesheet_url[] = '';
|
||||
} else {
|
||||
$this->stylesheet_url[] = $sub_arr['url'];
|
||||
}
|
||||
|
||||
if ( empty( $sub_arr['icons'] ) && ! empty( $sub_arr ) ) {
|
||||
if ( false === stripos( $sub_arr['url'], '//' ) ) {
|
||||
$to_parse = '';
|
||||
} else {
|
||||
$to_parse = wp_remote_get( $sub_arr['url'] );
|
||||
|
||||
if ( is_wp_error( $to_parse ) ) {
|
||||
$data = array(
|
||||
'parent' => $this->parent,
|
||||
'type' => 'error',
|
||||
'msg' => 'Icon Select: ' . esc_html__( 'Error retrieving stylesheet ', 'redux-framework' ) . ' "' . $sub_arr['url'] . '". (' . esc_html( $to_parse->get_error_code() ) . ' - ' . esc_html( $to_parse->get_error_message() ) . ')',
|
||||
'id' => 'Icon_Select_notice_',
|
||||
'dismiss' => false,
|
||||
);
|
||||
|
||||
Redux_Admin_Notices::set_notice( $data );
|
||||
|
||||
$this->is_error = true;
|
||||
|
||||
return;
|
||||
} elseif ( 200 !== wp_remote_retrieve_response_code( $to_parse ) ) {
|
||||
$data = array(
|
||||
'parent' => $this->parent,
|
||||
'type' => 'error',
|
||||
'msg' => 'Icon Select: ' . esc_html__( 'Error retrieving stylesheet ', 'redux-framework' ) . ' "' . $sub_arr['url'] . '". (' . wp_remote_retrieve_response_code( $to_parse ) . ' - ' . esc_html( wp_remote_retrieve_response_message( $to_parse ) ) . ')',
|
||||
'id' => 'Icon_Select_notice_',
|
||||
'dismiss' => false,
|
||||
);
|
||||
|
||||
Redux_Admin_Notices::set_notice( $data );
|
||||
|
||||
$this->is_error = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$to_parse = $to_parse['body'];
|
||||
}
|
||||
|
||||
// Remove whitespace.
|
||||
$to_parse = preg_replace( '/\s+/', ' ', $to_parse );
|
||||
|
||||
$regex_arr = array( '/.([\w-]+):{2}before{content/mi', '/.([\w-]+):{2}before { content/mi', '/.([\w-]+):{1}before{content:/mi', '/.([\w-]+):{1}before { content:/mi' );
|
||||
|
||||
if ( ! is_array( $sub_arr['exclude'] ) ) {
|
||||
if ( empty( $sub_arr['exclude'] ) ) {
|
||||
$sub_arr['exclude'] = array();
|
||||
} else {
|
||||
$sub_arr['exclude'] = array( $sub_arr['exclude'] );
|
||||
}
|
||||
}
|
||||
|
||||
$regex_arr = $this->array_merge( $sub_arr['exclude'], $regex_arr );
|
||||
|
||||
$str = array();
|
||||
|
||||
foreach ( $regex_arr as $regex ) {
|
||||
preg_match_all( $regex, $to_parse, $output_array );
|
||||
|
||||
$str = $this->array_merge( $str, $output_array[1] );
|
||||
}
|
||||
|
||||
if ( ! empty( $sub_arr['exclude'] ) && is_array( $sub_arr['exclude'] ) ) {
|
||||
$str = $this->array_delete( $str, $sub_arr['exclude'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $str ) ) {
|
||||
$sub_arr['icons'] = $str;
|
||||
|
||||
$this->stylesheet_data[ $idx ]['icons'] = $str;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $this->is_multi_array( $sub_arr['icons'] ) ) {
|
||||
$new_array = array();
|
||||
|
||||
if ( ! isset( $sub_arr['icons'][0] ) ) {
|
||||
foreach ( $sub_arr['icons'] as $class_name => $class ) {
|
||||
$new_array[] = $class . ' ' . $class_name;
|
||||
}
|
||||
|
||||
$this->stylesheet_data[ $idx ]['icons'] = $new_array;
|
||||
} else {
|
||||
$this->stylesheet_data[ $idx ]['icons'] = $sub_arr['icons'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine the array with null check.
|
||||
*
|
||||
* @param mixed $array1 First array.
|
||||
* @param mixed $array2 Second array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function array_merge( $array1, $array2 ): array {
|
||||
if ( ! is_array( $array1 ) ) {
|
||||
$array1 = array();
|
||||
}
|
||||
|
||||
if ( ! is_array( $array2 ) ) {
|
||||
$array2 = array();
|
||||
}
|
||||
|
||||
return array_merge( $array1, $array2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the array is multidimensional.
|
||||
*
|
||||
* @param array $my_array Array to evaluate.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function is_multi_array( array $my_array ): bool {
|
||||
if ( count( $my_array ) === count( $my_array, COUNT_RECURSIVE ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set field defaults.
|
||||
*/
|
||||
public function set_defaults() {
|
||||
$defaults = array(
|
||||
'options' => array(),
|
||||
'stylesheet' => '',
|
||||
'output' => true,
|
||||
'prefix' => '',
|
||||
'selector' => '',
|
||||
'height' => '',
|
||||
'enqueue' => true,
|
||||
'enqueue_frontend' => true,
|
||||
'class' => '',
|
||||
'button_title' => esc_html__( 'Add Icon', 'redux-framework' ),
|
||||
'remove_title' => esc_html__( 'Remove Icon', 'redux-framework' ),
|
||||
'elusive' => true,
|
||||
'fontawesome' => true,
|
||||
'dashicons' => true,
|
||||
'exclude_icons' => '',
|
||||
);
|
||||
|
||||
$this->field = wp_parse_args( $this->field, $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() {
|
||||
if ( $this->is_error ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$icon_sets = array();
|
||||
|
||||
if ( true === $this->field['fontawesome'] ) {
|
||||
$icon_sets['font-awesome'] = 'Font Awesome';
|
||||
}
|
||||
|
||||
if ( true === $this->field['dashicons'] ) {
|
||||
$icon_sets['dashicons'] = 'Dashicons';
|
||||
}
|
||||
|
||||
if ( true === $this->field['elusive'] ) {
|
||||
$icon_sets['elusive'] = 'Elusive';
|
||||
}
|
||||
|
||||
// Custom icon sets for <select>.
|
||||
foreach ( $this->stylesheet_data as $value ) {
|
||||
$icon_sets[ strtolower( str_replace( array( '.', ' ' ), '-', $value['title'] ) ) ] = $value['title'];
|
||||
}
|
||||
|
||||
$icon_sets = rawurlencode( wp_json_encode( $icon_sets ) );
|
||||
|
||||
// Data to send to AJAX.
|
||||
$ajax_data = array();
|
||||
$temp = array();
|
||||
|
||||
foreach ( $this->stylesheet_data as $value ) {
|
||||
$temp['title'] = $value['title'];
|
||||
$temp['class'] = $value['class'];
|
||||
$temp['icons'] = $value['icons'];
|
||||
|
||||
$ajax_data[] = $temp;
|
||||
}
|
||||
|
||||
$options_json = '';
|
||||
if ( ! empty( $ajax_data ) ) {
|
||||
$options_json = ' data-options=' . rawurlencode( wp_json_encode( $ajax_data ) );
|
||||
}
|
||||
|
||||
$nonce = wp_create_nonce( 'redux_icon_nonce' );
|
||||
$hidden = ( empty( $this->value ) ) ? ' hidden' : '';
|
||||
|
||||
echo '<div class="redux-icon-select" data-icon-sets="' . esc_attr( $icon_sets ) . '"' . esc_html( $options_json ) . '>';
|
||||
echo '<span class="redux-icon-select-preview' . esc_attr( $hidden ) . '"><i class="' . esc_attr( $this->value ) . '"></i></span>';
|
||||
echo '<a href="#" class="button button-primary redux-icon-add" data-nonce="' . esc_attr( $nonce ) . '">' . esc_html( $this->field['button_title'] ) . '</a>';
|
||||
echo '<a href="#" class="button redux-warning-primary redux-icon-remove' . esc_attr( $hidden ) . '">' . esc_html( $this->field['remove_title'] ) . '</a>';
|
||||
echo '<input type="hidden" name="' . esc_attr( $this->field['name'] . $this->field['name_suffix'] ) . '" value="' . esc_attr( $this->value ) . '" class="redux-icon-value" id="' . esc_attr( $this->field['id'] ) . '" />';
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render modal icon popup in the footer.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function add_footer_modal_icon() {
|
||||
?>
|
||||
<div id="redux-modal-icon" class="redux-modal redux-modal-icon hidden">
|
||||
<div class="redux-modal-table">
|
||||
<div class="redux-modal-table-cell">
|
||||
<div class="redux-modal-overlay"></div>
|
||||
<div class="redux-modal-inner">
|
||||
<div class="redux-modal-title">
|
||||
<?php esc_html_e( 'Add Icon', 'redux-framework' ); ?>
|
||||
<div class="redux-modal-close redux-icon-close"></div>
|
||||
</div>
|
||||
<div class="redux-modal-header">
|
||||
<label for="redux-icon-select-font">
|
||||
<select class="redux-icon-select-font" id="redux-icon-select-font"></select>
|
||||
</label>
|
||||
<label for="redux-icon-search">
|
||||
<input type="text" placeholder="<?php esc_html_e( 'Search...', 'redux-framework' ); ?>" class="redux-icon-search" id="redux-icon-search"/>
|
||||
</label>
|
||||
<div class="redux-modal-loading">
|
||||
<div class="redux-loading"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="redux-modal-content">
|
||||
<div class="redux-modal-load"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Do enqueue for all instances of the field.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function always_enqueue() {
|
||||
if ( isset( $this->stylesheet_url ) && is_array( $this->stylesheet_url ) && isset( $this->field['enqueue'] ) && $this->field['enqueue'] ) {
|
||||
foreach ( $this->stylesheet_url as $idx => $stylesheet_url ) {
|
||||
wp_enqueue_style(
|
||||
$this->field['id'] . '-webfont-' . $idx,
|
||||
$stylesheet_url,
|
||||
array(),
|
||||
Redux_Core::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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() {
|
||||
if ( $this->is_error || '' === $this->url ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_action( 'admin_footer', array( $this, 'add_footer_modal_icon' ) );
|
||||
add_action( 'customize_controls_print_footer_scripts', array( $this, 'add_footer_modal_icon' ) );
|
||||
|
||||
$min = Redux_Functions::isMin();
|
||||
|
||||
wp_enqueue_script(
|
||||
'redux-field-icon-select',
|
||||
$this->url . 'redux-icon-select' . $min . '.js',
|
||||
array( 'jquery', 'redux-js', 'wp-util' ),
|
||||
Redux_Extension_Icon_Select::$version,
|
||||
true
|
||||
);
|
||||
|
||||
if ( $this->parent->args['dev_mode'] ) {
|
||||
wp_enqueue_style(
|
||||
'redux-field-icon-select',
|
||||
$this->url . 'redux-icon-select.css',
|
||||
array(),
|
||||
Redux_Extension_Icon_Select::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is unused, but necessary to trigger output.
|
||||
*
|
||||
* @param mixed $data CSS data.
|
||||
*
|
||||
* @return mixed|string|void
|
||||
*/
|
||||
public function css_style( $data ) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to enqueue to Webfont to the front-end
|
||||
*
|
||||
* @param string|null|array $style CSS style.
|
||||
*/
|
||||
public function output( $style = '' ) {
|
||||
if ( $this->is_error ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( true === $this->field['elusive'] ) {
|
||||
Redux_Functions_Ex::enqueue_elusive_font();
|
||||
}
|
||||
|
||||
if ( true === $this->field['fontawesome'] ) {
|
||||
Redux_Functions_Ex::enqueue_font_awesome();
|
||||
}
|
||||
|
||||
if ( isset( $this->stylesheet_url ) && is_array( $this->stylesheet_url ) && $this->field['enqueue_frontend'] ) {
|
||||
foreach ( $this->stylesheet_url as $idx => $stylesheet_url ) {
|
||||
wp_enqueue_style(
|
||||
$this->field['id'] . '-webfont-' . $idx,
|
||||
$stylesheet_url,
|
||||
array(),
|
||||
Redux_Core::$version
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove items from an array.
|
||||
*
|
||||
* @param array $my_array The array to manage.
|
||||
* @param mixed $element An array or a string of the item to remove.
|
||||
*
|
||||
* @return array The cleaned array with reset keys.
|
||||
*/
|
||||
private function array_delete( array $my_array, $element ): array {
|
||||
return ( is_array( $element ) ) ? array_values( array_diff( $my_array, $element ) ) : array_values( array_diff( $my_array, array( $element ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,225 @@
|
||||
/* global redux, jQuery */
|
||||
|
||||
( function( $ ) {
|
||||
'use strict';
|
||||
|
||||
redux.field_objects = redux.field_objects || {};
|
||||
redux.field_objects.icon_select = redux.field_objects.icon_select || {};
|
||||
|
||||
redux.field_objects.icon_select.getIconArray = function( el ) {
|
||||
var iconSelect = el.find( '.redux-icon-select' );
|
||||
|
||||
return iconSelect.data( 'options' );
|
||||
};
|
||||
|
||||
redux.field_objects.icon_select.reloadIcons = function( el, button, modal, value, text ) {
|
||||
window.wp.ajax.post(
|
||||
'redux_get_icons',
|
||||
{
|
||||
icon_set: value,
|
||||
select_text: text,
|
||||
nonce: button.data( 'nonce' ),
|
||||
data: redux.field_objects.icon_select.getIconArray( el )
|
||||
}
|
||||
).done(
|
||||
function( response ) {
|
||||
modal.find( '.redux-modal-loading' ).hide();
|
||||
|
||||
modal.find( '.redux-modal-load' ).html( response.content );
|
||||
}
|
||||
).fail(
|
||||
function( response, status, error ) {
|
||||
modal.find( '.redux-modal-loading' ).hide();
|
||||
modal.find( '.redux-modal-load' ).html( error );
|
||||
|
||||
modal.on(
|
||||
'click',
|
||||
function() {
|
||||
modal.addClass( 'hidden' );
|
||||
modal.off( 'click' );
|
||||
|
||||
$( '.redux-icon-select-font' ).empty();
|
||||
modal.find( '.redux-modal-load' ).empty();
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
redux.field_objects.icon_select.init = function( selector ) {
|
||||
if ( ! selector ) {
|
||||
selector = $( document ).find( '.redux-group-tab:visible' ).find( '.redux-container-icon_select: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-icon-add' ).on(
|
||||
'click',
|
||||
function( e ) {
|
||||
var iconModalLoaded = false;
|
||||
var button = $( this );
|
||||
var modal = $( '#redux-modal-icon' );
|
||||
var select = modal.find( '.redux-icon-select-font' );
|
||||
var selectVal;
|
||||
var selectText;
|
||||
var iconSets;
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
// Extract icon set data.
|
||||
iconSets = el.find( '.redux-icon-select' ).data( 'icon-sets' );
|
||||
iconSets = JSON.parse( decodeURIComponent( iconSets ) );
|
||||
|
||||
// Fill <select> with icon set options.
|
||||
$.each(
|
||||
iconSets,
|
||||
function ( i, item ) {
|
||||
select.append(
|
||||
$( '<option>', { value: i, text : item } )
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
modal.removeClass( 'hidden' );
|
||||
|
||||
selectVal = select.val();
|
||||
selectText = select.find( ':selected' ).text();
|
||||
|
||||
if ( ! iconModalLoaded ) {
|
||||
modal.find( '.redux-modal-loading' ).show();
|
||||
|
||||
window.wp.ajax.post(
|
||||
'redux_get_icons',
|
||||
{
|
||||
icon_set: selectVal,
|
||||
select_text: selectText,
|
||||
nonce: button.data( 'nonce' ),
|
||||
data: redux.field_objects.icon_select.getIconArray( el )
|
||||
}
|
||||
).done(
|
||||
function( response ) {
|
||||
modal.find( '.redux-modal-loading' ).hide();
|
||||
|
||||
iconModalLoaded = true;
|
||||
|
||||
var load = modal.find( '.redux-modal-load' ).html( response.content );
|
||||
|
||||
load.off( 'click' );
|
||||
|
||||
load.on(
|
||||
'click',
|
||||
'i',
|
||||
function( e ) {
|
||||
e.preventDefault();
|
||||
|
||||
var icon = $( this ).attr( 'title' );
|
||||
|
||||
el.find( '.redux-icon-select-preview i' ).removeAttr( 'class' ).addClass( icon );
|
||||
el.find( '.redux-icon-select-preview' ).removeClass( 'hidden' );
|
||||
el.find( '.redux-icon-remove' ).removeClass( 'hidden' );
|
||||
el.find( 'input' ).val( icon ).trigger( 'change' );
|
||||
|
||||
modal.addClass( 'hidden' );
|
||||
|
||||
select.empty();
|
||||
load.empty();
|
||||
}
|
||||
);
|
||||
|
||||
modal.off( 'change' );
|
||||
|
||||
modal.on(
|
||||
'change',
|
||||
'.redux-icon-select-font',
|
||||
function() {
|
||||
var value = $( this ).val();
|
||||
var text = $( this ).find( ':selected' ).text();
|
||||
|
||||
modal.find( '.redux-modal-loading' ).show();
|
||||
|
||||
redux.field_objects.icon_select.reloadIcons( el, button, modal, value, text );
|
||||
}
|
||||
);
|
||||
|
||||
modal.on(
|
||||
'change keyup',
|
||||
'.redux-icon-search',
|
||||
function() {
|
||||
var value = $( this ).val();
|
||||
var icons = load.find( 'i' );
|
||||
|
||||
icons.each(
|
||||
function() {
|
||||
var elem = $( this );
|
||||
|
||||
if ( elem.attr( 'title' ).search( new RegExp( value, 'i' ) ) < 0 ) {
|
||||
elem.hide();
|
||||
} else {
|
||||
elem.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
modal.on(
|
||||
'click',
|
||||
'.redux-modal-close, .redux-modal-overlay',
|
||||
function() {
|
||||
modal.addClass( 'hidden' );
|
||||
|
||||
select.empty();
|
||||
load.empty();
|
||||
}
|
||||
);
|
||||
}
|
||||
).fail(
|
||||
function( response, status, error ) {
|
||||
modal.find( '.redux-modal-loading' ).hide();
|
||||
modal.find( '.redux-modal-load' ).html( error );
|
||||
|
||||
modal.on(
|
||||
'click',
|
||||
function() {
|
||||
select.empty();
|
||||
el.find( '.redux-modal-load' ).empty();
|
||||
|
||||
modal.off( 'click' );
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
el.find( '.redux-icon-remove' ).on(
|
||||
'click',
|
||||
function( e ) {
|
||||
e.preventDefault();
|
||||
el.find( '.redux-icon-select-preview' ).addClass( 'hidden' );
|
||||
el.find( 'input' ).val( '' ).trigger( 'change' );
|
||||
$( this ).addClass( 'hidden' );
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
} )( jQuery );
|
||||
@@ -0,0 +1 @@
|
||||
.redux-container-icon_select .redux-icon-container{position:relative;overflow-y:auto;border:2px solid #eee;padding:5px;text-align:center}.redux-container-icon_select .redux-icon-select{margin:0 !important}.redux-container-icon_select .redux-icon-select input[type='radio']{display:none}.redux-container-icon_select .redux-icon-select i{border-color:transparent;color:#555}.redux-container-icon_select .redux-icon-select i:hover{border-color:#ddd;color:#111}.redux-container-icon_select ul.redux-icon-select li{margin:10px;display:block;float:left;padding:5px}.redux-container-icon_select .redux-icon-select i,.redux-container-icon_select .redux-icon-select-selected i{border-width:4px;border-style:solid;font-size:30px;padding:5px}.redux-container-icon_select .redux-icon-select-selected i,.redux-container-icon_select .redux-icon-select-selected i:hover{border-color:#7a7a7a;color:#269ad6}
|
||||
@@ -0,0 +1 @@
|
||||
!function(a){"use strict";redux.field_objects=redux.field_objects||{},redux.field_objects.icon_select=redux.field_objects.icon_select||{},redux.field_objects.icon_select.getIconArray=function(e){return e.find(".redux-icon-select").data("options")},redux.field_objects.icon_select.reloadIcons=function(e,d,i,n,o){window.wp.ajax.post("redux_get_icons",{icon_set:n,select_text:o,nonce:d.data("nonce"),data:redux.field_objects.icon_select.getIconArray(e)}).done(function(e){i.find(".redux-modal-loading").hide(),i.find(".redux-modal-load").html(e.content)}).fail(function(e,d,n){i.find(".redux-modal-loading").hide(),i.find(".redux-modal-load").html(n),i.on("click",function(){i.addClass("hidden"),i.off("click"),a(".redux-icon-select-font").empty(),i.find(".redux-modal-load").empty()})})},redux.field_objects.icon_select.init=function(e){e=e||a(document).find(".redux-group-tab:visible").find(".redux-container-icon_select:visible"),a(e).each(function(){var c=a(this),e=c;(e=c.hasClass("redux-field-container")?e:c.parents(".redux-field-container:first")).is(":hidden")||e.hasClass("redux-field-init")&&(e.removeClass("redux-field-init"),c.find(".redux-icon-add").on("click",function(e){var d,i=a(this),o=a("#redux-modal-icon"),t=o.find(".redux-icon-select-font");e.preventDefault(),e=c.find(".redux-icon-select").data("icon-sets"),e=JSON.parse(decodeURIComponent(e)),a.each(e,function(e,d){t.append(a("<option>",{value:e,text:d}))}),o.removeClass("hidden"),e=t.val(),d=t.find(":selected").text(),o.find(".redux-modal-loading").show(),window.wp.ajax.post("redux_get_icons",{icon_set:e,select_text:d,nonce:i.data("nonce"),data:redux.field_objects.icon_select.getIconArray(c)}).done(function(e){o.find(".redux-modal-loading").hide();var n=o.find(".redux-modal-load").html(e.content);n.off("click"),n.on("click","i",function(e){e.preventDefault();e=a(this).attr("title");c.find(".redux-icon-select-preview i").removeAttr("class").addClass(e),c.find(".redux-icon-select-preview").removeClass("hidden"),c.find(".redux-icon-remove").removeClass("hidden"),c.find("input").val(e).trigger("change"),o.addClass("hidden"),t.empty(),n.empty()}),o.off("change"),o.on("change",".redux-icon-select-font",function(){var e=a(this).val(),d=a(this).find(":selected").text();o.find(".redux-modal-loading").show(),redux.field_objects.icon_select.reloadIcons(c,i,o,e,d)}),o.on("change keyup",".redux-icon-search",function(){var d=a(this).val();n.find("i").each(function(){var e=a(this);e.attr("title").search(new RegExp(d,"i"))<0?e.hide():e.show()})}),o.on("click",".redux-modal-close, .redux-modal-overlay",function(){o.addClass("hidden"),t.empty(),n.empty()})}).fail(function(e,d,n){o.find(".redux-modal-loading").hide(),o.find(".redux-modal-load").html(n),o.on("click",function(){t.empty(),c.find(".redux-modal-load").empty(),o.off("click")})})}),c.find(".redux-icon-remove").on("click",function(e){e.preventDefault(),c.find(".redux-icon-select-preview").addClass("hidden"),c.find("input").val("").trigger("change"),a(this).addClass("hidden")}))})}}(jQuery);
|
||||
@@ -0,0 +1,335 @@
|
||||
.redux-container-icon_select {
|
||||
.redux-icon-select {
|
||||
display: flex;
|
||||
grid-gap: 5px;
|
||||
}
|
||||
|
||||
.redux-icon-select-preview {
|
||||
.dashicons {
|
||||
height:initial!important;
|
||||
}
|
||||
|
||||
&:not(.hidden) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
i {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 30px;
|
||||
font-size: 14px;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
color: #555;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
}
|
||||
|
||||
.redux-icon-container {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
border: 2px solid #eee;
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* .redux-icon-select {
|
||||
margin: 0 !important;
|
||||
|
||||
input[type='radio']{
|
||||
display:none;
|
||||
}
|
||||
|
||||
i {
|
||||
border-color:transparent;
|
||||
color: #555;
|
||||
|
||||
&:hover {
|
||||
border-color:#ddd;
|
||||
color: #111;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
ul{
|
||||
&.redux-icon-select li {
|
||||
margin: 10px;
|
||||
display:block;
|
||||
float: left;
|
||||
padding:5px;
|
||||
}
|
||||
}
|
||||
|
||||
/* .redux-icon-select i,
|
||||
.redux-icon-select-selected i {
|
||||
border-width:4px;
|
||||
border-style: solid;
|
||||
font-size: 30px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.redux-icon-select-selected {
|
||||
i,
|
||||
i:hover {
|
||||
border-color:#7a7a7a;
|
||||
color:#269ad6;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
.redux-modal{
|
||||
position: fixed;
|
||||
z-index: 100101;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
&.hidden{
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-modal-icon{
|
||||
z-index: 100102;
|
||||
|
||||
.redux-icon-title{
|
||||
padding: 15px 0;
|
||||
margin: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
border: 1px solid #eee;
|
||||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
.redux-modal-header{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.redux-icon-select-font{
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
top: -2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.redux-icon-search{
|
||||
width: 50%;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
}
|
||||
|
||||
i{
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
margin: 4px;
|
||||
width: 35px;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
font-size: 16px;
|
||||
color: #555;
|
||||
text-align: center;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #f7f7f7;
|
||||
border-radius: 2px;
|
||||
box-shadow: 1px 1px 0 rgba(0,0,0,0.05);
|
||||
|
||||
&:hover {
|
||||
color: #fff;
|
||||
border-color: #222;
|
||||
background-color: #222;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-modal-content{
|
||||
padding: 10px;
|
||||
height: 618px;
|
||||
}
|
||||
|
||||
.redux-error-text{
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-modal-table{
|
||||
display: table;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.redux-modal-table-cell{
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
margin: 100px 0;
|
||||
}
|
||||
|
||||
.redux-modal-overlay{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #000;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.redux-modal-inner{
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
width: 760px;
|
||||
height: 750px;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.redux-modal-content{
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
overflow-y: auto;
|
||||
height: 595px;
|
||||
|
||||
.redux-field{
|
||||
padding: 15px 30px 15px 15px;
|
||||
}
|
||||
|
||||
a{
|
||||
&:active,
|
||||
&:focus{
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
h4{
|
||||
font-size: 13px;
|
||||
|
||||
small{
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.redux-modal-title{
|
||||
position: relative;
|
||||
background-color: #fcfcfc;
|
||||
border-bottom: 1px solid #ddd;
|
||||
height: 36px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 36px;
|
||||
margin: 0;
|
||||
padding: 0 36px 0 16px;
|
||||
}
|
||||
|
||||
.redux-modal-header{
|
||||
width: 100%;
|
||||
padding: 14px 0;
|
||||
background-color: #f5f5f5;
|
||||
border-bottom: 1px solid #ddd;
|
||||
|
||||
.redux-modal-loading{
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 20px;
|
||||
top: 59px;
|
||||
}
|
||||
|
||||
select{
|
||||
display: block;
|
||||
width: 250px;
|
||||
margin: 0 auto;
|
||||
font-size: 13px;
|
||||
line-height: 1;
|
||||
height: 30px;
|
||||
min-height: 30px;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-modal-close{
|
||||
color: #666;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
text-align: center;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
||||
&:before{
|
||||
font: normal 20px/36px dashicons;
|
||||
content: "\f158";
|
||||
vertical-align: top;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
&:hover{
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.redux-loading{
|
||||
position: relative;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: #ccc;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.07);
|
||||
|
||||
&:after{
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
content: "";
|
||||
margin-top: -2px;
|
||||
margin-left: -2px;
|
||||
background-color: white;
|
||||
animation-duration: 0.5s;
|
||||
animation-iteration-count: infinite;
|
||||
animation-timing-function: linear;
|
||||
animation-name: reduxLoader;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 782px) {
|
||||
.redux-modal{
|
||||
.redux-modal-inner{
|
||||
width: 90%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-height: 750px) {
|
||||
.redux-modal{
|
||||
.redux-modal-inner{
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.redux-modal-content{
|
||||
height: calc(100vh - 200px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes reduxLoader {
|
||||
0% {
|
||||
transform: rotate(0deg) translateX(-6px) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg) translateX(-6px) rotate(-360deg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Silence is golden.
|
||||
*
|
||||
* @package Redux Framework
|
||||
*/
|
||||
|
||||
echo null;
|
||||
Reference in New Issue
Block a user