active_widgetlayer_pageid() ) { return; } wp_enqueue_style( 'aamla_widgetlayer_style', get_template_directory_uri() . '/add-on/widgetlayer/assets/widgetlayer.css', array(), AAMLA_THEME_VERSION, 'all' ); $inline_style = $this->generate_custom_css(); wp_add_inline_style( 'aamla_widgetlayer_style', $inline_style ); } /** * Extend the default WordPress body classes. * * @since 1.0.4 * * @param array $classes Classes for the body element. * @return array */ public function body_classes( $classes ) { if ( $this->active_widgetlayer_pageid() ) { $classes[] = 'widgetlayer-page'; } return $classes; } /** * Call available breadcrumb display function. * * @since 1.0.4 */ public function breadcrumb() { if ( ! $this->active_widgetlayer_pageid() ) { return; } remove_action( 'aamla_inside_main_content', 'aamla_breadcrumb' ); aamla_breadcrumb(); } /** * Conditionally display skip link. * * @since 1.0.2 */ public function skip_link() { if ( ! $this->active_widgetlayer_pageid() ) { return; } // Remove default action hook to display skip link. remove_action( 'aamla_inside_header', 'aamla_skip_link', 0 ); // Display revised skip link. printf( '', esc_html__( 'Skip to content', 'aamla' ) ); } /** * Enqueue scripts and styles to admin. * * @since 1.0.1 */ public function enqueue_admin() { $screen = get_current_screen(); if ( ! in_array( $screen->id, [ 'page', 'widgets', 'customize' ], true ) ) { return; } wp_enqueue_media(); wp_enqueue_style( 'aamla_widgetlayer_admin_style', get_template_directory_uri() . '/add-on/widgetlayer/admin/widgetlayer.css', [], AAMLA_THEME_VERSION, 'all' ); wp_enqueue_script( 'aamla_widgetlayer_admin_js', get_template_directory_uri() . '/add-on/widgetlayer/admin/widgetlayer.js', [ 'jquery' ], AAMLA_THEME_VERSION, true ); // Theme localize scripts data. $l10n = apply_filters( 'aamla_localize_script_data', [ 'uploader_title' => esc_html__( 'Set Text Widget Featured Image', 'aamla' ), 'uploader_button_text' => esc_html__( 'Select', 'aamla' ), 'set_featured_img' => esc_html__( 'Set Featured Image', 'aamla' ), ] ); wp_localize_script( 'aamla_widgetlayer_admin_js', 'aamlaImageUploadText', $l10n ); } /** * Generate inline css for current page. * * @since 1.0.1 * * @return string Verified css string or empty string. */ public function generate_custom_css() { // We will put inline css to individual widgets separately in customize preview. if ( is_customize_preview() ) { return ''; } $page_id = $this->active_widgetlayer_pageid(); if ( ! $page_id ) { return ''; } $css_array = []; $sidebars_widgets = get_option( 'sidebars_widgets', [] ); foreach ( $sidebars_widgets[ 'widgetlayer-page-' . $page_id ] as $widget ) { $widget_data = $this->get_widget_data_from_id( $page_id, $widget ); if ( false === $widget_data ) { continue; } $css_array = array_merge_recursive( $css_array, $this->get_widget_css( $widget_data ) ); } $final_css = $css_array ? $this->widget_css_array_to_string( $css_array ) : ''; return $final_css; } /** * Get dynamically generated inline css from widget id. * * @since 1.0.1 * * @param array $widget_data { * Current widget's data to generate customized output. * @type str $widget_id Widget ID. * @type int $widget_pos Widget position in widgetlayer widget-area. * @type array $instance Current widget instance settings. * @type str $id_base Widget ID base. * } * @return string Verified css string or empty string. */ public function get_widget_css( $widget_data ) { if ( ! $widget_data || ! is_array( $widget_data ) ) { return []; } $widget_css = []; $widget_id = $widget_data[0]; $widget_pos = $widget_data[1]; $instance = $widget_data[2]; $id_base = $widget_data[3]; $widget_css['common'][] = 'order:' . 2 * $widget_pos; $wid_settings = array_intersect_key( $instance, $this->get_widget_options() ); if ( ! empty( $wid_settings ) ) { foreach ( $this->get_widget_options() as $key => $args ) { if ( ! isset( $instance[ $key ] ) || '' === $instance[ $key ] ) { continue; } $val = $instance[ $key ]; switch ( $key ) { case 'aamla_width': if ( '' !== $instance['aamla_width_tablet'] ) { $widget_css['desktop'][] = sprintf( 'flex: 0 0 %s%%', absint( $val ) ); } else { $widget_css['tablet'][] = sprintf( 'flex: 0 0 %s%%', absint( $val ) ); } break; case 'aamla_width_tablet': $widget_css['tablet'][] = sprintf( 'flex: 0 0 %s%%', absint( $val ) ); break; case 'aamla_vert_align': $widget_css['tablet'][] = 'display:flex'; $widget_css['tablet'][] = 'flex-direction:column'; $widget_css['tablet'][] = ( 'middle' === $val ) ? 'justify-content:center' : 'justify-content:flex-end'; break; case 'aamla_text_align': $widget_css['common'][] = ( 'center' === $val ) ? 'text-align:center' : 'text-align:right'; break; case 'aamla_show_mobile': $widget_css['mobile_only'][] = 'display:none'; break; case 'aamla_push_down': $widget_css['mobile_only'][] = 'order:' . ( 2 * ( $widget_pos + 1 ) + 1 ); break; case 'aamla_push_down_tablet': $widget_css['tablet_only'][] = 'order:' . ( 2 * ( $widget_pos + 1 ) + 1 ); break; default: break; } } } $widget_css = apply_filters( 'aamla_widget_custom_css', $widget_css, $widget_data ); if ( ! empty( $widget_css ) ) { foreach ( $widget_css as $key => $rules ) { $widget_css[ $key ] = (array) sprintf( '.widgetlayer .%s{%s}', $widget_id, implode( ';', $rules ) ); } } return $widget_css; } /** * Properly format Widget CSS array to css string. * * @since 1.0.1 * * @param array $css_arr Array of css strings. * @return string Formatted css string. */ public function widget_css_array_to_string( $css_arr ) { if ( empty( $css_arr ) ) { return ''; } $css_str = ''; if ( isset( $css_arr['common'] ) ) { $css_str .= implode( '', $css_arr['common'] ); } if ( isset( $css_arr['mobile_only'] ) ) { $css_str .= sprintf( '@media only screen and (max-width: %s) {%s}', '767px', implode( '', $css_arr['mobile_only'] ) ); } if ( isset( $css_arr['tablet'] ) ) { $css_str .= sprintf( '@media only screen and (min-width: %s) {%s}', '768px', implode( '', $css_arr['tablet'] ) ); } if ( isset( $css_arr['tablet_only'] ) ) { $css_str .= sprintf( '@media only screen and (min-width: %s) and (max-width: %s) {%s}', '768px', '1024px', implode( '', $css_arr['tablet_only'] ) ); } if ( isset( $css_arr['desktop'] ) ) { $css_str .= sprintf( '@media only screen and (min-width: %s) {%s}', '1025px', implode( '', $css_arr['desktop'] ) ); } if ( ! $css_str ) { return ''; } return aamla_prepare_css( $css_str ); } /** * Get dynamically generated Widget html classes. * * @since 1.0.1 * * @param array $widget_data { * Current widget's data to generate customized output. * @type str $widget_id Widget ID. * @type int $widget_pos Widget position in widgetlayer widget-area. * @type array $instance Current widget instance settings. * @type str $id_base Widget ID base. * } * @return array Verified class string or empty string. */ public function get_widget_classes( $widget_data ) { if ( ! $widget_data || ! is_array( $widget_data ) ) { return ''; } $classes = []; $classes[] = 'brick-' . $widget_data[1]; $widget_classes = apply_filters( 'aamla_widget_custom_classes', $classes, $widget_data ); $widget_classes = array_map( 'esc_attr', $widget_classes ); $widget_classes = array_unique( $widget_classes ); return join( ' ', $widget_classes ); } /** * Adds widget specific css to front end. * * @since 1.0.1 * * @param array $classes Array of css rules. * @param array $widget_data { * Current widget's data to generate customized output. * @type str $widget_id Widget ID. * @type int $widget_pos Widget position in widgetlayer widget-area. * @type array $instance Current widget instance settings. * @type str $id_base Widget ID base. * } * @return array */ public function widget_classes( $classes, $widget_data ) { $instance = $widget_data[2]; $id_base = $widget_data[3]; if ( 'text' === $id_base ) { if ( isset( $instance['text'] ) && empty( $instance['text'] ) ) { $classes[] = 'only-title'; } if ( isset( $instance['aamla_text_featured_image'] ) && $instance['aamla_text_featured_image'] ) { $classes[] = 'has-featured-image'; } } return $classes; } /** * Register widget area. * * @since 1.0.1 * * @link https://developer.wordpress.org/themes/functionality/sidebars/#registering-a-sidebar * * @param array $widgets Array of arguments for the sidebar being registered. * @return array Array of arguments for the sidebar being registered. */ public function register_widget_areas( $widgets ) { foreach ( $this->get_pages_with_custom_widget() as $id => $title ) { array_push( $widgets, [ 'name' => esc_html__( 'Page - ', 'aamla' ) . esc_html( $title ), 'id' => 'widgetlayer-page-' . absint( $id ), 'before_widget' => '
', ] ); } return $widgets; } /** * Display widgets. * * @since 1.0.1 * * @param string $calledby Hook by which this function is called. */ public function display_widget_areas( $calledby ) { $page_id = $this->active_widgetlayer_pageid(); if ( ! $page_id ) { return; } aamla_widgets( 'page-widget-area-top', 'page-widget-area-top widgetlayer wrapper', esc_html__( 'Page Content Below Site Header', 'aamla' ), 'widgetlayer-page-' . $page_id, false ); } /** * Get array of all pages having custom widget enabaled. * * @since 1.0.1 */ public function get_pages_with_custom_widget() { if ( ! empty( $this->pages_with_custom_widget ) ) { return $this->pages_with_custom_widget; } $pages = get_option( 'aamla_pages_with_custom_widget' ); if ( false !== $pages ) { $this->pages_with_custom_widget = $pages; return $pages; } $pages = []; $args = [ 'meta_key' => 'aamla_custom_widget_meta', 'meta_value' => 'yes', ]; $query = get_pages( $args ); foreach ( $query as $page ) { $pages[ $page->ID ] = esc_html( $page->post_title ); } update_option( 'aamla_pages_with_custom_widget', $pages ); $this->pages_with_custom_widget = $pages; return $pages; } /** * Get array of all widget options. * * @since 1.0.1 */ public function get_widget_options() { if ( ! empty( $this->widget_options ) ) { return $this->widget_options; } $this->widget_options = apply_filters( 'aamla_widgetlayer_widget_options', [ 'aamla_width' => [ 'setting' => 'aamla_width', 'label' => esc_html__( 'Width on desktop (in %)', 'aamla' ), 'default' => 100, 'type' => 'number', 'input_attrs' => [ 'min' => 0, 'max' => 100, 'step' => 0.01, ], ], 'aamla_width_tablet' => [ 'setting' => 'aamla_width_tablet', 'label' => esc_html__( 'Width on tablet (in %)', 'aamla' ), 'default' => '', 'type' => 'number', 'input_attrs' => [ 'min' => 0, 'max' => 100, 'step' => 0.01, 'placeholder' => esc_attr_x( 'Same as desktop', 'Placeholder text for a number input field', 'aamla' ), ], ], 'aamla_vert_align' => [ 'setting' => 'aamla_vert_align', 'label' => esc_html__( 'Content Vertical Alignment', 'aamla' ), 'default' => esc_html__( 'Top', 'aamla' ), 'type' => 'select', 'choices' => [ 'middle' => esc_html__( 'Middle', 'aamla' ), 'bottom' => esc_html__( 'Bottom', 'aamla' ), ], ], 'aamla_text_align' => [ 'setting' => 'aamla_text_align', 'label' => esc_html__( 'Text Alignment', 'aamla' ), 'default' => esc_html__( 'Left', 'aamla' ), 'type' => 'select', 'choices' => [ 'center' => esc_html__( 'Center', 'aamla' ), 'right' => esc_html__( 'Right', 'aamla' ), ], ], 'aamla_show_mobile' => [ 'setting' => 'aamla_show_mobile', 'label' => esc_html__( 'Hide widget on mobile', 'aamla' ), 'type' => 'checkbox', ], 'aamla_push_down_tablet' => [ 'setting' => 'aamla_push_down_tablet', 'label' => esc_html__( 'Move below next widget on tablet', 'aamla' ), 'type' => 'checkbox', ], 'aamla_push_down' => [ 'setting' => 'aamla_push_down', 'label' => esc_html__( 'Move below next widget on mobile', 'aamla' ), 'type' => 'checkbox', ], 'aamla_text_featured_image' => [ 'setting' => 'aamla_text_featured_image', 'label' => esc_html__( 'Text Widget Featured Image', 'aamla' ), 'type' => 'custom', 'id_base' => 'text', ], ] ); return $this->widget_options; } /** * Adds a text filed to widgets for adding classes. * * @since 1.0.1 * * @param object $widget The widget instance (passed by reference). * @param null $return Return null if new fields are added. * @param array $instance An array of the widget's settings. */ public function extend_widget_form( $widget, $return, $instance ) { $fields = []; foreach ( $this->get_widget_options() as $option => $value ) { $setting = $value['setting']; $id = esc_attr( $widget->get_field_id( $setting ) ); $name = esc_attr( $widget->get_field_name( $setting ) ); $instance = wp_parse_args( $instance, [ $setting => '' ] ); $value = wp_parse_args( $value, [ 'default' => '', 'description' => '', 'id_base' => 'all', 'premium_option' => false, ] ); $input_attrs = isset( $value['input_attrs'] ) ? (array) $value['input_attrs'] : []; $description = $value['description'] ? sprintf( '%s', esc_attr( $value['setting'] ) . '-desc', esc_html( $value['description'] ) ) : ''; // Check if current Widget Option to be shown for this widget type. if ( 'all' !== $value['id_base'] && $widget->id_base !== $value['id_base'] ) { continue; } // Prepare markup for custom widget options. switch ( $value['type'] ) { case 'select': $field = ''; $field .= $description; // Select option field. $field .= sprintf( ''; $field = sprintf( '

%s

', esc_attr( $setting ), $field ); break; case 'checkbox': $field = sprintf( '', $name, $id, checked( $instance[ $setting ], 'yes' ) ); $field .= ''; $field .= $description; $field = sprintf( '

%s

', esc_attr( $setting ), $field ); break; case 'custom': $field = ''; $field .= $description; $field .= apply_filters( 'aamla_custom_widget_form', '', $setting, $id, $name, $instance[ $setting ] ); $field = sprintf( '

%s

', esc_attr( $setting ), $field ); break; default: $field = ''; $field .= $description; $field .= sprintf( ' $val ) { $field .= esc_html( $attr ) . '="' . esc_attr( $val ) . '" '; } if ( ! isset( $input_attrs['value'] ) ) { $field .= sprintf( 'value=%s', ( '' !== $instance[ $setting ] ) ? $instance[ $setting ] : $value['default'] ); } $field .= ' />'; $field = sprintf( '

%s

', esc_attr( $setting ), $field ); break; } if ( false === $value['premium_option'] ) { $fields['basic'][] = $field; } else { $fields['premium'][] = $field; } } if ( ! empty( $fields ) ) { // Add widget options title. $title = sprintf( '

%s

', esc_html__( 'Theme specific styling options', 'aamla' ) ); // Add widget Options Content. $content = sprintf( '
%s
', implode( '', $fields['basic'] ) ); // Display Widget Options. printf( '
%s%s
', $title, $content ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } } /** * Image upload option markup. * * @since 1.0.2 * * @param str $markup Widget form image upload markup. * @param str $setting Setting Name. * @param str $id Field ID. * @param str $name Field Name. * @param int $value Uploaded image id. * @return str Widget form image upload markup. */ public function image_upload( $markup, $setting, $id, $name, $value ) { if ( 'aamla_text_featured_image' !== $setting ) { return $markup; } $value = absint( $value ); $uploader_class = ''; $class = 'aamla-hidden'; if ( $value ) { $image_src = wp_get_attachment_image_src( $value, 'aamla-medium' ); if ( $image_src ) { $featured_markup = sprintf( '', esc_url( $image_src[0] ) ); $class = ''; $uploader_class = 'has-image'; } else { $featured_markup = esc_html__( 'Set Featured Image', 'aamla' ); } } else { $featured_markup = esc_html__( 'Set Featured Image', 'aamla' ); } $markup = sprintf( '%s', $uploader_class, $featured_markup ); $markup .= sprintf( '%s', $class, esc_html__( 'Click the image to edit/update', 'aamla' ) ); $markup .= sprintf( '%s', $class, esc_html__( 'Remove Featured Image', 'aamla' ) ); $markup .= sprintf( '', $name, $id, $value ); return $markup; } /** * Update settings for current widget instance. * * @since 1.0.1 * * @param array $instance The current widget instance's settings. * @param array $new_instance Array of new widget settings. * @return false|array */ public function update_settings( $instance, $new_instance ) { foreach ( $this->get_widget_options() as $option => $value ) { $setting = $value['setting']; $new_instance = wp_parse_args( $new_instance, [ $setting => '' ] ); switch ( $value['type'] ) { case 'select': $instance[ $setting ] = array_key_exists( $new_instance[ $setting ], $value['choices'] ) ? $new_instance[ $setting ] : ''; break; case 'checkbox': $instance[ $setting ] = ( 'yes' === $new_instance[ $setting ] ) ? 'yes' : ''; break; case 'text': $instance[ $setting ] = sanitize_text_field( $new_instance[ $setting ] ); break; case 'url': $instance[ $setting ] = esc_url_raw( $new_instance[ $setting ] ); break; case 'number': $number = $new_instance[ $setting ]; $attr = isset( $value['input_attrs'] ) ? (array) $value['input_attrs'] : array(); if ( '' !== $number ) { if ( isset( $attr['max'] ) ) { $number = $number > $attr['max'] ? $attr['max'] : $number; } if ( isset( $attr['min'] ) ) { $number = $number < $attr['min'] ? $attr['min'] : $number; } if ( isset( $attr['step'] ) && is_float( $attr['step'] ) ) { $number = abs( floatval( $number ) ); } else { $number = absint( $number ); } } $instance[ $setting ] = ( '' !== $number ) ? $number : ''; break; case 'custom': if ( 'aamla_text_featured_image' === $setting ) { $img_id = absint( $new_instance[ $setting ] ); $img_url = wp_get_attachment_image_src( $img_id ); $instance[ $setting ] = $img_url ? $img_id : ''; } else { $instance[ $setting ] = ''; } $instance[ $setting ] = apply_filters( 'aamla_custom_widget_form_update', $instance[ $setting ], $setting, $new_instance ); break; default: $instance[ $setting ] = ''; break; } } return $instance; } /** * Adds the classes to the widget in the front-end. * * @since 1.0.1 * * @param array $params Parameters passed to a widget's display callback. * @return false|array */ public function add_widget_customizations( $params ) { if ( is_admin() ) { return $params; } $page_id = $this->active_widgetlayer_pageid(); if ( ! $page_id ) { return $params; } $widget_data = $this->get_widget_data_from_id( $page_id, $params[0]['widget_id'] ); if ( false === $widget_data ) { return $params; } $custom_classes = $this->get_widget_classes( $widget_data ); $custom_classes = $custom_classes ? esc_attr( $params[0]['widget_id'] ) . ' ' . $custom_classes : esc_attr( $params[0]['widget_id'] ); // Add class(es) to widget front end. $params[0]['before_widget'] = str_replace( 'brick', 'brick ' . $custom_classes, $params[0]['before_widget'] ); // Change markup for Blank Widget. if ( false !== strpos( $params[0]['widget_id'], 'aamla_blank_widget' ) ) { $params[0]['before_widget'] = str_replace( '