--- a/royal-elementor-addons/admin/notices/rating-notice.php
+++ b/royal-elementor-addons/admin/notices/rating-notice.php
@@ -34,9 +34,9 @@
$install_date = get_option('royal_elementor_addons_activation_time');
if ( false == get_option('wpr_maybe_later_time') && false !== $install_date && $this->past_date >= $install_date ) {
- add_action( 'admin_notices', [$this, 'render_rating_notice' ]);
+ add_action( 'admin_notices', [$this, 'render_rating_notice']);
} else if ( false != get_option('wpr_maybe_later_time') && $this->past_date >= get_option('wpr_maybe_later_time') ) {
- add_action( 'admin_notices', [$this, 'render_rating_notice' ]);
+ add_action( 'admin_notices', [$this, 'render_rating_notice']);
}
}
--- a/royal-elementor-addons/admin/plugin-options.php
+++ b/royal-elementor-addons/admin/plugin-options.php
@@ -80,6 +80,8 @@
register_setting( 'wpr-settings', 'wpr_recaptcha_v3_site_key' );
register_setting( 'wpr-settings', 'wpr_recaptcha_v3_secret_key' );
register_setting( 'wpr-settings', 'wpr_recaptcha_v3_score' );
+ register_setting( 'wpr-settings', 'wpr_recaptcha_v2_site_key' );
+ register_setting( 'wpr-settings', 'wpr_recaptcha_v2_secret_key' );
// Lightbox
register_setting( 'wpr-settings', 'wpr_lb_bg_color' );
@@ -128,6 +130,17 @@
register_setting( 'wpr-elements-settings', 'wpr-element-'. $slug, [ 'default' => 'on' ] );
}
+ // Pro widgets that appear in Elements tab (so their toggles are saved)
+ if ( defined( 'WPR_ADDONS_PRO_VERSION' ) && wpr_fs()->can_use_premium_code() ) {
+ $pro_element_slugs = [ 'breadcrumbs-pro' ];
+ if ( wpr_fs()->is_plan( 'expert' ) ) {
+ $pro_element_slugs = array_merge( $pro_element_slugs, [ 'category-grid-pro', 'advanced-filters-pro' ] );
+ }
+ foreach ( $pro_element_slugs as $slug ) {
+ register_setting( 'wpr-elements-settings', 'wpr-element-' . $slug, [ 'default' => 'on' ] );
+ }
+ }
+
// Theme Builder
foreach ( Utilities::get_theme_builder_modules() as $title => $data ) {
$slug = $data[0];
@@ -213,7 +226,7 @@
// Render Backup Plugin Popup
WPR_Templates_Loop::render_backup_plugin_popup();
-
+
?>
<!-- Tabs -->
@@ -819,6 +832,26 @@
<input type="number" name="wpr_recaptcha_v3_score" id="wpr_recaptcha_v3_score" placeholder="0.5" step="0.1" min="0" max="1" value="<?php echo esc_attr(get_option('wpr_recaptcha_v3_score')); ?>">
</div>
+
+ <div class="wpr-setting">
+ <h4>
+ <span><?php esc_html_e( 'reCAPTCHA v2 (Checkbox) Site Key', 'wpr-addons' ); ?></span>
+ <br>
+ <a href="https://www.google.com/recaptcha/admin" target="_blank"><?php esc_html_e( 'How to get reCAPTCHA keys?', 'wpr-addons' ); ?></a>
+ <p class="wpr-settings-group-description"><?php esc_html_e( 'Use reCAPTCHA v2 checkbox in Form Builder. Create a "reCAPTCHA v2" type key in Google reCAPTCHA admin.', 'wpr-addons' ); ?></p>
+ </h4>
+
+ <input type="text" name="wpr_recaptcha_v2_site_key" id="wpr_recaptcha_v2_site_key" value="<?php echo esc_attr(get_option('wpr_recaptcha_v2_site_key')); ?>">
+ </div>
+
+ <div class="wpr-setting">
+ <h4>
+ <span><?php esc_html_e( 'reCAPTCHA v2 Secret Key', 'wpr-addons' ); ?></span>
+ <br>
+ </h4>
+
+ <input type="text" name="wpr_recaptcha_v2_secret_key" id="wpr_recaptcha_v2_secret_key" value="<?php echo esc_attr(get_option('wpr_recaptcha_v2_secret_key')); ?>">
+ </div>
</div>
--- a/royal-elementor-addons/admin/templates/library/wpr-templates-data.php
+++ b/royal-elementor-addons/admin/templates/library/wpr-templates-data.php
@@ -411,6 +411,18 @@
'label' => 'new',
'priority' => 1,
],
+ 'v4' => [
+ 'name' => 'Landing Page - Business V4',
+ 'pages' => 'home,insight,business-plans,features,blog,single-blog,',
+ 'plugins' => '{}',
+ 'tags' => 'free digital product single-page landing page one page onepage landingpage agency digital app business corporate creative lead capture marketing startup',
+ 'theme-builder' => true,
+ 'woo-builder' => false,
+ 'off-canvas' => true,
+ 'price' => $is_pro_active ? 'free' : 'free',
+ 'label' => 'new',
+ 'priority' => 1,
+ ],
],
'landing-page-digital-product' => [
'v1' => [
@@ -686,6 +698,20 @@
'priority' => 4,
],
],
+ 'cosmetic' => [
+ 'v1' => [
+ 'name' => 'Cosmetic Shop V1',
+ 'pages' => 'home,shop,single-product,cart,checkout,about,faq,blog,single-blog,contact,',
+ 'plugins' => '{"woocommerce":'. $is_woo_active .'}',
+ 'tags' => 'free cosmetics store shop woo woocommerce estore ecommerce product estetic beauty skincare makeup haircare customers health essentials nail perfumes',
+ 'theme-builder' => true,
+ 'woo-builder' => true,
+ 'off-canvas' => false,
+ 'price' => $is_pro_active ? 'free' : 'free',
+ 'label' => 'new',
+ 'priority' => 15,
+ ],
+ ],
'woo-auto-parts' => [
'v1' => [
'name' => 'Auto Parts Store - Car V1',
@@ -2484,6 +2510,12 @@
'preview' => ['home','home-woo-food-v2','shop-woo-food-v1','about','contact','faq','blog'],
'price' => $is_pro_active ? 'free' : 'pro',
],
+ 'cosmetic-v1' => [
+ 'name' => 'Cosmetic Shop V1',
+ 'pages' => ['home','shop','cart','about','faq','blog','contact',],
+ 'preview' => ['home','shop','cart','about','faq','blog','contact',],
+ 'price' => $is_pro_active ? 'free' : 'free',
+ ],
'estore-v1' => [
'name' => 'Electronic Store - V1',
'pages' => ['home','shop','blog','faq','about','contact'],
--- a/royal-elementor-addons/classes/modules/forms/wpr-recaptcha-handler.php
+++ b/royal-elementor-addons/classes/modules/forms/wpr-recaptcha-handler.php
@@ -9,70 +9,122 @@
}
/**
- * WPR_Actions_Status setup
+ * WPR Recaptcha Handler - reCAPTCHA v2 and v3 verification
*
* @since 3.4.6
*/
- class WPR_Recaptcha_Handler {
- public function __construct() {
- add_action('wp_ajax_wpr_verify_recaptcha', [$this, 'wpr_verify_recaptcha']);
- add_action('wp_ajax_nopriv_wpr_verify_recaptcha', [$this, 'wpr_verify_recaptcha']);
- }
-
- // In your PHP file
- public function wpr_verify_recaptcha() {
- $recaptcha_response = $_POST['g-recaptcha-response'];
- $is_valid_recaptcha = $this->check_recaptcha($recaptcha_response);
-
- if ($is_valid_recaptcha[0] && $is_valid_recaptcha[1] >= get_option('wpr_recaptcha_v3_score')) {
- // Proceed with form processing
- wp_send_json_success(array(
+class WPR_Recaptcha_Handler {
+ public function __construct() {
+ add_action( 'wp_ajax_wpr_verify_recaptcha', [ $this, 'wpr_verify_recaptcha' ] );
+ add_action( 'wp_ajax_nopriv_wpr_verify_recaptcha', [ $this, 'wpr_verify_recaptcha' ] );
+ }
+
+ public function wpr_verify_recaptcha() {
+ $recaptcha_response = isset( $_POST['g-recaptcha-response'] ) ? sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ) ) : '';
+ $recaptcha_version = isset( $_POST['recaptcha_version'] ) ? sanitize_text_field( wp_unslash( $_POST['recaptcha_version'] ) ) : 'v3';
+
+ if ( empty( $recaptcha_response ) ) {
+ wp_send_json_error( [ 'message' => 'Recaptcha Error' ] );
+ return;
+ }
+
+ if ( 'v2' === $recaptcha_version ) {
+ $is_valid = $this->check_recaptcha_v2( $recaptcha_response );
+ if ( $is_valid ) {
+ wp_send_json_success( [ 'message' => 'Recaptcha Success' ] );
+ } else {
+ wp_send_json_error( [ 'message' => 'Recaptcha Error' ] );
+ }
+ return;
+ }
+
+ // v3
+ $result = $this->check_recaptcha_v3( $recaptcha_response );
+ $score = isset( $result['score'] ) ? $result['score'] : 0;
+ $score_threshold = (float) get_option( 'wpr_recaptcha_v3_score', 0.5 );
+
+ if ( $result['success'] && $score >= $score_threshold ) {
+ wp_send_json_success( [
'message' => 'Recaptcha Success',
- 'score' => $is_valid_recaptcha[1]
- ));
- } else {
- // Handle the invalid reCAPTCHA case
- wp_send_json_error(array(
+ 'score' => $score,
+ ] );
+ } else {
+ wp_send_json_error( [
'message' => 'Recaptcha Error',
- 'score' => $is_valid_recaptcha[1],
- 'results' => [
- $is_valid_recaptcha[0],
- $is_valid_recaptcha[1] >= get_option('wpr_recaptcha_v3_score')
- ]
- ));
- }
- }
-
- public function check_recaptcha($recaptcha_response) {
- $secret_key = get_option('wpr_recaptcha_v3_secret_key');
- $remote_ip = $_SERVER['REMOTE_ADDR'];
-
- $response = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', array(
- 'body' => array(
- 'secret' => $secret_key,
- 'response' => $recaptcha_response,
- 'remoteip' => $remote_ip
- )
- ));
-
- if (is_wp_error($response)) {
- // Handle the error accordingly
- return false;
- }
-
- $decoded_response = json_decode(wp_remote_retrieve_body($response), true);
-
- $score = $decoded_response['score'];
-
- if ($decoded_response['success'] === true) {
- // reCAPTCHA verification passed
- return [true, $score];
- } else {
- // reCAPTCHA verification failed
- return [false, $score];
- }
- }
- }
+ 'score' => $score,
+ ] );
+ }
+ }
+
+ /**
+ * Verify reCAPTCHA v2 (checkbox) response. No score returned.
+ *
+ * @param string $recaptcha_response Token from g-recaptcha-response.
+ * @return bool
+ */
+ public function check_recaptcha_v2( $recaptcha_response ) {
+ $secret_key = get_option( 'wpr_recaptcha_v2_secret_key' );
+ if ( empty( $secret_key ) ) {
+ return false;
+ }
+
+ $remote_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
+
+ $response = wp_remote_post(
+ 'https://www.google.com/recaptcha/api/siteverify',
+ [
+ 'body' => [
+ 'secret' => $secret_key,
+ 'response' => $recaptcha_response,
+ 'remoteip' => $remote_ip,
+ ],
+ ]
+ );
+
+ if ( is_wp_error( $response ) ) {
+ return false;
+ }
+
+ $decoded = json_decode( wp_remote_retrieve_body( $response ), true );
+ return ! empty( $decoded['success'] );
+ }
+
+ /**
+ * Verify reCAPTCHA v3 response. Returns success and score.
+ *
+ * @param string $recaptcha_response Token from g-recaptcha-response.
+ * @return array{ success: bool, score: float|null }
+ */
+ public function check_recaptcha_v3( $recaptcha_response ) {
+ $secret_key = get_option( 'wpr_recaptcha_v3_secret_key' );
+ if ( empty( $secret_key ) ) {
+ return [ 'success' => false, 'score' => null ];
+ }
+
+ $remote_ip = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
+
+ $response = wp_remote_post(
+ 'https://www.google.com/recaptcha/api/siteverify',
+ [
+ 'body' => [
+ 'secret' => $secret_key,
+ 'response' => $recaptcha_response,
+ 'remoteip' => $remote_ip,
+ ],
+ ]
+ );
+
+ if ( is_wp_error( $response ) ) {
+ return [ 'success' => false, 'score' => null ];
+ }
+
+ $decoded = json_decode( wp_remote_retrieve_body( $response ), true );
+ $success = ! empty( $decoded['success'] );
+ $score = isset( $decoded['score'] ) ? (float) $decoded['score'] : null;
+
+ return [ 'success' => $success, 'score' => $score ];
+ }
+}
- new WPR_Recaptcha_Handler();
No newline at end of file
+new WPR_Recaptcha_Handler();
--- a/royal-elementor-addons/classes/modules/forms/wpr-send-email.php
+++ b/royal-elementor-addons/classes/modules/forms/wpr-send-email.php
@@ -71,6 +71,7 @@
$all_fields_content = [];
foreach ($_POST['form_content'] as $key => $value) {
+ $value[2] = wp_unslash($value[2]);
$all_fields_content[] = is_array($value[1]) ? trim($value[2]) . ': ' . implode("n", $value[1]) : trim($value[2]) . ': ' . $value[1];
}
$all_fields_content = implode("n", $all_fields_content);
--- a/royal-elementor-addons/classes/modules/wpr-grid-helpers.php
+++ b/royal-elementor-addons/classes/modules/wpr-grid-helpers.php
@@ -173,6 +173,68 @@
}
}
+ /**
+ * Check if the current user is allowed to query the post type(s) in grid settings.
+ * Prevents unauthenticated disclosure of non-public post types (e.g. flamingo_inbound, shop_coupon).
+ *
+ * @param array $settings Grid settings (e.g. $_POST['grid_settings']).
+ * @return bool True if allowed, false otherwise.
+ */
+ public static function is_allowed_grid_query_post_type( $settings ) {
+ if ( empty( $settings ) || ! is_array( $settings ) ) {
+ return false;
+ }
+
+ $query_source = isset( $settings['query_source'] ) ? $settings['query_source'] : '';
+
+ // Resolve effective post type(s) to validate
+ if ( 'current' === $query_source && ! empty( $settings['current_query_source'] ) ) {
+ $post_types = (array) $settings['current_query_source'];
+ } elseif ( 'related' !== $query_source && '' !== $query_source ) {
+ $post_types = (array) $query_source;
+ } else {
+ // 'related' uses get_post_type(get_the_ID()) in get_main_query_args; no user-controlled type
+ return true;
+ }
+
+ $is_logged_in = is_user_logged_in();
+
+ // For unauthenticated requests, only allow post types that are publicly queryable
+ if ( ! $is_logged_in ) {
+ $allowed_types = get_post_types( array( 'publicly_queryable' => true ), 'names' );
+ foreach ( $post_types as $post_type ) {
+ $post_type = sanitize_key( $post_type );
+ if ( '' === $post_type ) {
+ continue;
+ }
+ if ( ! in_array( $post_type, $allowed_types, true ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ // Logged-in: allow if publicly_queryable OR user has capability to read that post type
+ foreach ( $post_types as $post_type ) {
+ $post_type = sanitize_key( $post_type );
+ if ( '' === $post_type ) {
+ continue;
+ }
+ $obj = get_post_type_object( $post_type );
+ if ( ! $obj ) {
+ return false;
+ }
+ if ( $obj->publicly_queryable ) {
+ continue;
+ }
+ $cap = isset( $obj->cap->read_private_posts ) ? $obj->cap->read_private_posts : 'read';
+ if ( ! current_user_can( $cap ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
// Main Query Args
public static function get_main_query_args($settings, $params) {
$author = ! empty( $settings[ 'query_author' ] ) ? implode( ',', $settings[ 'query_author' ] ) : '';
@@ -1883,6 +1945,12 @@
));
}
+ if ( ! empty( $_POST['grid_settings'] ) && ! WPR_Grid_Helpers::is_allowed_grid_query_post_type( $_POST['grid_settings'] ) ) {
+ wp_send_json_error(array(
+ 'message' => esc_html__('Security check failed.', 'wpr-addons'),
+ ));
+ }
+
if ( isset($_POST['wpr_url_params']) ) {
$results = [];
@@ -1923,9 +1991,15 @@
));
}
+ $settings = isset( $_POST['grid_settings'] ) && is_array( $_POST['grid_settings'] ) ? $_POST['grid_settings'] : array();
+ if ( ! WPR_Grid_Helpers::is_allowed_grid_query_post_type( $settings ) ) {
+ wp_send_json_error(array(
+ 'message' => esc_html__('Security check failed.', 'wpr-addons'),
+ ));
+ }
+
$start = microtime(true);
// Get Settings
- $settings = $_POST['grid_settings'];
// Create a unique cache key based on the settings
$cache_key = 'wpr_grid_filters_' . md5(serialize(WPR_Grid_Helpers::get_main_query_args($settings, [])));
--- a/royal-elementor-addons/classes/modules/wpr-woo-grid-helpers.php
+++ b/royal-elementor-addons/classes/modules/wpr-woo-grid-helpers.php
@@ -1892,6 +1892,7 @@
switch ( $type ) {
case 'title':
WPR_Woo_Grid_Helpers::render_product_title( $settings, $class, $general_settings );
+ do_action( 'wpr_woo_grid_after_title', $post_id );
break;
case 'excerpt':
--- a/royal-elementor-addons/includes/controls/wpr-ajax-select2/wpr-control-ajax-select2-api.php
+++ b/royal-elementor-addons/includes/controls/wpr-ajax-select2/wpr-control-ajax-select2-api.php
@@ -263,6 +263,24 @@
$merged_meta_keys = array_unique( array_merge( $merged_meta_keys, $array ) );
}
+ // Collect term meta keys from all public taxonomies
+ $taxonomies = get_taxonomies( [ 'public' => true ], 'names' );
+ foreach ( $taxonomies as $taxonomy ) {
+ $terms = get_terms( [ 'taxonomy' => $taxonomy, 'hide_empty' => false ] );
+ if ( ! is_wp_error( $terms ) && ! empty( $terms ) ) {
+ foreach ( $terms as $term ) {
+ $term_meta = get_term_meta( $term->term_id );
+ if ( is_array( $term_meta ) ) {
+ foreach ( array_keys( $term_meta ) as $meta_key ) {
+ if ( '_' !== substr( (string) $meta_key, 0, 1 ) ) {
+ $merged_meta_keys[] = $meta_key;
+ }
+ }
+ }
+ }
+ }
+ }
+
// Rekey
$merged_meta_keys = array_values($merged_meta_keys);
--- a/royal-elementor-addons/modules/button/widgets/wpr-button.php
+++ b/royal-elementor-addons/modules/button/widgets/wpr-button.php
@@ -537,6 +537,9 @@
'{{WRAPPER}} .wpr-button::after' => 'color: {{VALUE}}',
'{{WRAPPER}}.wpr-button-icon-style-inline .wpr-button:hover .wpr-button-icon' => 'color: {{VALUE}}',
'{{WRAPPER}}.wpr-button-icon-style-inline .wpr-button:hover .wpr-button-icon svg' => 'fill: {{VALUE}}',
+ '{{WRAPPER}} .wpr-button:focus .wpr-button-text' => 'color: {{VALUE}}',
+ '{{WRAPPER}}.wpr-button-icon-style-inline .wpr-button:focus .wpr-button-icon' => 'color: {{VALUE}}',
+ '{{WRAPPER}}.wpr-button-icon-style-inline .wpr-button:focus .wpr-button-icon svg' => 'fill: {{VALUE}}',
],
]
);
--- a/royal-elementor-addons/modules/dual-color-heading/widgets/wpr-dual-color-heading.php
+++ b/royal-elementor-addons/modules/dual-color-heading/widgets/wpr-dual-color-heading.php
@@ -50,6 +50,20 @@
// return 'https://royal-elementor-addons.com/contact/?ref=rea-plugin-panel-grid-help-btn';
return 'https://wordpress.org/support/plugin/royal-elementor-addons/';
}
+ public function add_control_text_shadow_type() {
+ $this->add_control(
+ 'text_shadow_type',
+ [
+ 'label' => esc_html__( 'Type', 'wpr-addons' ),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'default',
+ 'options' => [
+ 'default' => esc_html__( 'Default', 'wpr-addons' ),
+ 'lng-pro' => esc_html__( 'Long (Pro)', 'wpr-addons' ),
+ ],
+ ]
+ );
+ }
protected function register_controls() {
@@ -374,6 +388,7 @@
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 15,
+ 'unit' => 'px'
],
'range' => [
'px' => [
@@ -395,6 +410,7 @@
'type' => Controls_Manager::SLIDER,
'default' => [
'size' => 0,
+ 'unit' => 'px'
],
'range' => [
'px' => [
@@ -563,6 +579,94 @@
]
);
+ $this->add_control(
+ 'shadow_section',
+ [
+ 'label' => esc_html__( 'Shadow', 'wpr-addons' ),
+ 'type' => Controls_Manager::HEADING,
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control_text_shadow_type();
+
+ $this->add_group_control(
+ Group_Control_Text_Shadow::get_type(),
+ [
+ 'name' => 'text_shadow',
+ 'selector' => '{{WRAPPER}} .wpr-dual-title .second',
+ 'condition' => [
+ 'text_shadow_type' => 'default',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'text_long_shadow_color',
+ [
+ 'label' => esc_html__( 'Color', 'wpr-addons' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '#e8e8e8',
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-dual-title' => '--wpr-ls-color: {{VALUE}}',
+ ],
+ 'condition' => [
+ 'text_shadow_type' => 'long',
+ ],
+ 'render_type' => 'template',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'text_long_shadow_size',
+ [
+ 'label' => esc_html__( 'Size', 'wpr-addons' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => ['px'],
+ 'range' => [
+ 'px' => [
+ 'min' => 0,
+ 'max' => 100,
+ ],
+ ],
+ 'default' => [
+ 'unit' => 'px',
+ 'size' => 10,
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-dual-title' => '--wpr-ls-size: {{SIZE}}{{UNIT}}',
+ ],
+ 'render_type' => 'template',
+ 'condition' => [
+ 'text_shadow_type' => 'long',
+ ],
+ ]
+ );
+
+ $this->add_control(
+ 'text_long_shadow_direction',
+ [
+ 'label' => esc_html__( 'Direction', 'wpr-addons' ),
+ 'type' => Controls_Manager::SELECT,
+ 'default' => 'bottom-left',
+ 'options' => [
+ 'top-left' => esc_html__( 'Top Left', 'wpr-addons' ),
+ 'top-right' => esc_html__( 'Top Right', 'wpr-addons' ),
+ 'bottom-left' => esc_html__( 'Bottom Left', 'wpr-addons' ),
+ 'bottom-right' => esc_html__( 'Bottom Right', 'wpr-addons' ),
+ 'top' => esc_html__( 'Top', 'wpr-addons' ),
+ 'bottom' => esc_html__( 'Bottom', 'wpr-addons' ),
+ 'left' => esc_html__( 'Left', 'wpr-addons' ),
+ 'right' => esc_html__( 'Right', 'wpr-addons' ),
+ ],
+ 'prefix_class' => 'wpr-ls-dir-',
+ 'render_type' => 'template',
+ 'condition' => [
+ 'text_shadow_type' => 'long',
+ ],
+ ]
+ );
+
$this->end_controls_section();
$this->start_controls_section(
@@ -712,6 +816,12 @@
$this->add_inline_editing_attributes('title', 'none');
$this->add_inline_editing_attributes('description', 'basic');
$this->add_inline_editing_attributes('content', 'advanced');
+
+ $this->add_render_attribute( 'dual_title', 'class', 'wpr-dual-title' );
+
+ if ( 'long' === $settings['text_shadow_type'] ) {
+ $this->add_render_attribute( 'dual_title', 'class', 'wpr-shadow-long' );
+ }
$tags_whitelist = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', 'p'];
@@ -724,7 +834,7 @@
?>
<div class="wpr-dual-heading-wrap">
<div class="wpr-dual-title-wrap">
- <<?php echo esc_attr($dual_heading_tag); ?> class="wpr-dual-title">
+ <<?php echo esc_attr( $dual_heading_tag ); ?> <?php echo $this->get_render_attribute_string( 'dual_title' ); ?>>
<?php if (!empty($settings['primary_heading'])) : ?>
<span class="first"><?php echo esc_html($settings['primary_heading']); ?></span>
<?php endif; ?>
--- a/royal-elementor-addons/modules/form-builder/widgets/wpr-form-builder.php
+++ b/royal-elementor-addons/modules/form-builder/widgets/wpr-form-builder.php
@@ -527,6 +527,7 @@
'upload' => esc_html__( 'File Upload', 'wpr-addons' ),
'password' => esc_html__( 'Password', 'wpr-addons' ),
'html' => esc_html__( 'HTML', 'wpr-addons' ),
+ 'recaptcha-v2' => esc_html__( 'reCAPTCHA V2', 'wpr-addons' ),
'recaptcha-v3' => esc_html__( 'reCAPTCHA V3', 'wpr-addons'),
'hidden' => esc_html__( 'Hidden', 'wpr-addons' ),
'step' => esc_html__( 'Step', 'wpr-addons' ),
@@ -568,6 +569,20 @@
);
}
+ if ( '' == get_option( 'wpr_recaptcha_v2_site_key' ) ) {
+ $repeater->add_control(
+ 'recaptcha_v2_key_notice',
+ [
+ 'type' => Controls_Manager::RAW_HTML,
+ 'raw' => sprintf( __( 'Navigate to <strong><a href="%s" target="_blank">Dashboard > %s > Integrations</a></strong> to set up <strong>reCAPTCHA v2 Site Key</strong>.', 'wpr-addons' ), admin_url( 'admin.php?page=wpr-addons&tab=wpr_tab_settings' ), Utilities::get_plugin_name() ),
+ 'content_classes' => 'elementor-panel-alert elementor-panel-alert-info',
+ 'condition' => [
+ 'field_type' => 'recaptcha-v2'
+ ]
+ ]
+ );
+ }
+
$repeater->add_control(
'field_label',
[
@@ -577,6 +592,9 @@
'dynamic' => [
'active' => true,
],
+ 'condition' => [
+ 'field_type!' => 'recaptcha-v2'
+ ]
]
);
@@ -590,6 +608,9 @@
'dynamic' => [
'active' => true,
],
+ 'condition' => [
+ 'field_type!' => 'recaptcha-v2'
+ ]
]
);
@@ -759,6 +780,7 @@
'operator' => '!in',
'value' => [
'recaptcha',
+ 'recaptcha-v2',
'recaptcha-v3',
'hidden',
'html',
@@ -940,6 +962,7 @@
'value' => [
'hidden',
'recaptcha',
+ 'recaptcha-v2',
'recaptcha-v3',
'step',
],
@@ -979,7 +1002,7 @@
'terms' => [
[
'name' => 'field_type',
- 'value' => 'recaptcha',
+ 'value' => 'recaptcha-v2',
],
],
],
@@ -1000,7 +1023,7 @@
'terms' => [
[
'name' => 'field_type',
- 'value' => 'recaptcha',
+ 'value' => 'recaptcha-v2',
],
],
],
@@ -3731,7 +3754,7 @@
<?php $this->render_form_icon($instance); ?>
<?php endif; ?>
<?php if ( ! empty( $instance['button_text'] ) ) : ?>
- <span><?php echo $this->print_unescaped_setting( 'button_text' ); ?></span>
+ <span><?php echo esc_html__( $instance['button_text'] ); ?></span>
<?php endif; ?>
<?php if ( !empty( $instance['selected_button_icon'] ) && 'right' === $instance['button_icon_align'] ) : ?>
<?php $this->render_form_icon($instance); ?>
@@ -3958,8 +3981,8 @@
echo '<div class="wpr-step-tab wpr-step-tab-hidden">';
} else {
echo '<div class="wpr-stp-btns-wrap">';
- echo '<button type="button" class="wpr-step-prev">'. $item['previous_button_text'] .'</button>';
- echo '<button type="button" class="wpr-step-next">'. $item['next_button_text'] .'</button>';
+ echo '<button type="button" class="wpr-step-prev">'. esc_html__( $item['previous_button_text'] ) .'</button>';
+ echo '<button type="button" class="wpr-step-next">'. esc_html__( $item['next_button_text'] ) .'</button>';
echo '</div>';
echo '</div>';
echo '<div class="wpr-step-tab wpr-step-tab-hidden">';
@@ -3998,8 +4021,17 @@
// PHPCS - the method make_radio_checkbox_field is safe.
echo $this->make_radio_checkbox_field( $item, $item_index, $item['field_type'] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
break;
+ case 'recaptcha-v2':
+ $recaptcha_v2_id = 'wpr-recaptcha-v2-' . $this->get_id() . '-' . $item_index;
+ $recaptcha_size = isset( $item['recaptcha_size'] ) ? $item['recaptcha_size'] : 'normal';
+ $recaptcha_theme = isset( $item['recaptcha_style'] ) ? $item['recaptcha_style'] : 'light';
+ echo '<div class="wpr-recaptcha-v2-wrap">';
+ echo '<div id="' . esc_attr( $recaptcha_v2_id ) . '" class="wpr-recaptcha-v2-container" data-sitekey="' . esc_attr( get_option( 'wpr_recaptcha_v2_site_key' ) ) . '" data-size="' . esc_attr( $recaptcha_size ) . '" data-theme="' . esc_attr( $recaptcha_theme ) . '"></div>';
+ echo '</div>';
+ break;
case 'recaptcha-v3':
- echo '<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response" data-site-key="'. get_option('wpr_recaptcha_v3_site_key') .'" />';
+ echo '<input type="hidden" id="g-recaptcha-response" name="g-recaptcha-response" data-site-key="' . esc_attr( get_option( 'wpr_recaptcha_v3_site_key' ) ) . '" />';
+ break;
case 'text':
case 'email':
case 'url':
--- a/royal-elementor-addons/modules/grid/widgets/wpr-grid.php
+++ b/royal-elementor-addons/modules/grid/widgets/wpr-grid.php
@@ -1062,7 +1062,7 @@
'advanced_filters',
[
'label' => esc_html__( 'Enable Advanced Filters', 'wpr-addons' ),
- 'description' => esc_html__( 'Turn on Only with Advanced Filters widget.', 'wpr-addons' ),
+ 'description' => esc_html__( 'Turn on Only with Advanced Filters widget. Works with Load More and Infinite Scroll Pagination for now (Other Pagination Types will be applied in next updates as well).', 'wpr-addons' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'no',
'return_value' => 'yes',
--- a/royal-elementor-addons/modules/media-grid/widgets/wpr-media-grid.php
+++ b/royal-elementor-addons/modules/media-grid/widgets/wpr-media-grid.php
@@ -6660,7 +6660,10 @@
$attachments_count = count($attachments);
}
- for ( $i = 0; $i < $attachments_count; $i++ ) {
+ for ( $i = 0; $i < $attachments_count; $i++ ) {
+ if ( !isset( $settings['query_manual_attachment'][$i]['id'] ) ) {
+ continue;
+ }
array_push( $post_ids, $settings['query_manual_attachment'][$i]['id'] );
}
@@ -7504,9 +7507,15 @@
// Load More / Infinite Scroll
} else {
- echo '<a href="'. esc_url(get_pagenum_link( $paged + 1, true )) .'" class="wpr-load-more-btn" data-e-disable-page-transition >';
- echo esc_html($settings['pagination_load_more_text']);
- echo '</a>';
+ if ( 'yes' === $settings['filters_experiment'] ) {
+ echo '<a class="wpr-load-more-btn" data-e-disable-page-transition >';
+ echo esc_html($settings['pagination_load_more_text']);
+ echo '</a>';
+ } else {
+ echo '<a href="'. esc_url(get_pagenum_link( $paged + 1, true )) .'" class="wpr-load-more-btn" data-e-disable-page-transition >';
+ echo esc_html($settings['pagination_load_more_text']);
+ echo '</a>';
+ }
echo '<div class="wpr-pagination-loading">';
switch ( $settings['pagination_animation'] ) {
--- a/royal-elementor-addons/modules/pricing-table/widgets/pricing-table.php
+++ b/royal-elementor-addons/modules/pricing-table/widgets/pricing-table.php
@@ -925,6 +925,39 @@
);
$this->add_responsive_control(
+ 'heading_align',
+ [
+ 'label' => esc_html__( 'Alignment', 'wpr-addons' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'label_block' => false,
+ 'default' => 'center',
+ 'options' => [
+ 'left' => [
+ 'title' => esc_html__( 'Left', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-left',
+ ],
+ 'center' => [
+ 'title' => esc_html__( 'Center', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-center',
+ ],
+ 'right' => [
+ 'title' => esc_html__( 'Right', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-right',
+ ],
+ ],
+ // 'selectors_dictionary' => [
+ // 'flex-start' => 'justify-content: flex-start; text-align: left;',
+ // 'center' => 'justify-content: center; text-align: center;',
+ // 'flex-end' => 'justify-content: flex-end; text-align: right;',
+ // ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-heading' => 'text-align: {{VALUE}};',
+ ],
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_responsive_control(
'heading_section_padding',
[
'label' => esc_html__( 'Padding', 'wpr-addons' ),
@@ -1144,6 +1177,40 @@
);
$this->add_responsive_control(
+ 'price_align',
+ [
+ 'label' => esc_html__( 'Alignment', 'wpr-addons' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'label_block' => false,
+ 'default' => 'center',
+ 'options' => [
+ 'flex-start' => [
+ 'title' => esc_html__( 'Left', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-left',
+ ],
+ 'center' => [
+ 'title' => esc_html__( 'Center', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-center',
+ ],
+ 'flex-end' => [
+ 'title' => esc_html__( 'Right', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-right',
+ ],
+ ],
+ 'selectors_dictionary' => [
+ 'flex-start' => 'justify-content: flex-start; text-align: left;',
+ 'center' => 'justify-content: center; text-align: center;',
+ 'flex-end' => 'justify-content: flex-end; text-align: right;',
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-price' => '{{VALUE}};',
+ '{{WRAPPER}} .wpr-pricing-table-price-inner' => '{{VALUE}};',
+ ],
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_responsive_control(
'price_wrap_padding',
[
'label' => esc_html__( 'Padding', 'wpr-addons' ),
@@ -1785,6 +1852,34 @@
);
$this->add_control(
+ 'btn_align',
+ [
+ 'label' => esc_html__( 'Alignment', 'wpr-addons' ),
+ 'type' => Controls_Manager::CHOOSE,
+ 'label_block' => false,
+ 'default' => 'center',
+ 'options' => [
+ 'left' => [
+ 'title' => esc_html__( 'Left', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-left',
+ ],
+ 'center' => [
+ 'title' => esc_html__( 'Center', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-center',
+ ],
+ 'right' => [
+ 'title' => esc_html__( 'Right', 'wpr-addons' ),
+ 'icon' => 'eicon-text-align-right',
+ ],
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-button' => 'text-align: {{VALUE}};',
+ ],
+ 'separator' => 'before',
+ ]
+ );
+
+ $this->add_control(
'btn_section_padding',
[
'label' => esc_html__( 'Section Padding', 'wpr-addons' ),
@@ -1847,6 +1942,18 @@
);
$this->add_control(
+ 'btn_icon_color',
+ [
+ 'label' => esc_html__( 'Icon Color', 'wpr-addons' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-btn i' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
'btn_border_color',
[
'label' => esc_html__( 'Border Color', 'wpr-addons' ),
@@ -1902,6 +2009,18 @@
);
$this->add_control(
+ 'btn_icon_hover_color',
+ [
+ 'label' => esc_html__( 'Icon Color', 'wpr-addons' ),
+ 'type' => Controls_Manager::COLOR,
+ 'default' => '',
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-btn:hover i' => 'color: {{VALUE}};',
+ ],
+ ]
+ );
+
+ $this->add_control(
'btn_hover_border_color',
[
'label' => esc_html__( 'Border Color', 'wpr-addons' ),
@@ -2016,6 +2135,36 @@
]
);
+ $this->add_control(
+ 'btn_icon_style_divider',
+ [
+ 'type' => Controls_Manager::DIVIDER,
+ 'style' => 'thick',
+ ]
+ );
+
+ $this->add_responsive_control(
+ 'btn_icon_size',
+ [
+ 'label' => esc_html__( 'Icon Size', 'wpr-addons' ),
+ 'type' => Controls_Manager::SLIDER,
+ 'size_units' => [ 'px', 'em' ],
+ 'range' => [
+ 'px' => [
+ 'min' => 1,
+ 'max' => 200,
+ ],
+ 'em' => [
+ 'min' => 0.1,
+ 'max' => 10,
+ ],
+ ],
+ 'selectors' => [
+ '{{WRAPPER}} .wpr-pricing-table-btn i' => 'font-size: {{SIZE}}{{UNIT}};',
+ ],
+ ]
+ );
+
$this->add_responsive_control(
'btn_padding',
[
@@ -2678,9 +2827,9 @@
<?php if ( '' !== $item['select_icon']['value'] && $item['btn_position'] === 'after' ) : ?>
<i class="<?php echo esc_attr( $item['select_icon']['value'] ); ?>"></i>
+ <?php endif; ?>
</span>
- <?php endif; ?>
</a>
<?php elseif ( $item['type_select'] === 'divider' ) : ?>
--- a/royal-elementor-addons/modules/twitter-feed/widgets/wpr-twitter-feed.php
+++ b/royal-elementor-addons/modules/twitter-feed/widgets/wpr-twitter-feed.php
@@ -304,7 +304,7 @@
echo '<'. esc_attr($element_username_tag) .' class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
- echo '<a>'. $item['user']['name'] .'</a>';
+ echo '<a>'. $item['author']['name'] .'</a>';
echo '</div>';
echo '</'. esc_attr($element_username_tag) .'>';
}
@@ -314,7 +314,7 @@
echo '<div class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
echo '<small>';
- echo '<a href="https://twitter.com/' . $item['user']['screen_name'] .'">@'. $item['user']['screen_name'] .'</a>';
+ echo '<a href="https://twitter.com/' . $item['author']['userName'] .'">@'. $item['author']['userName'] .'</a>';
echo '</small>';
echo '</div>';
echo '</div>';
@@ -326,7 +326,7 @@
echo '<div class="inner-block">';
?>
<figure>
- <img src="<?php echo $item['user']['profile_image_url'] ?>" alt="Image">
+ <img src="<?php echo $item['author']['profilePicture'] ?>" alt="Image">
</figure>
<?php
echo '</div>';
@@ -340,7 +340,7 @@
echo '<div class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
- echo '<a href="'. esc_url('https://twitter.com/'. $item['user']['screen_name'] .'"/status/"'. $item['id'] ) .'" class="wpr-button-effect '. esc_attr($read_more_animation) .'">';
+ echo '<a href="'. esc_url('https://twitter.com/'. $item['author']['name'] .'"/status/"'. $item['id'] ) .'" class="wpr-button-effect '. esc_attr($read_more_animation) .'">';
// // Icon: Before
// if ( 'before' === $settings['element_extra_icon_pos'] ) {
@@ -362,15 +362,14 @@
}
public function render_post_caption($settings, $class, $item) {
-
- if ( !isset($item['full_text']) || '' === $item['full_text'] ) {
+ if ( !isset($item['text']) || '' === $item['text'] ) {
return;
}
echo '<div class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
echo '<p>';
- $string = preg_replace("~[[:alpha:]]+://[^<p>[:space:]]+[[:alnum:]/]~", "<a href="\0">\0</a>", $item['full_text']);
+ $string = preg_replace("~[[:alpha:]]+://[^<p>[:space:]]+[[:alnum:]/]~", "<a href="\0">\0</a>", $item['text']);
$new_string = preg_replace('/#([a-z0-9]+)/i', '<a href="https://twitter.com/hashtag/$1?src=hashtag_click">#$1</a>', $string);
if ( isset( $settings['element_word_count'] ) ) {
echo wp_trim_words(preg_replace('/@([a-z0-9]+)/i', '<a href="https://twitter.com/$1">@$1</a>' ,$new_string), $settings['element_word_count']);
@@ -397,7 +396,7 @@
// }
// echo wp_date(get_option( 'date_format' ), strtotime($item['created_at']))
- echo human_time_diff(strtotime($item['created_at'])) .' '. esc_html__('ago', 'wpr-addons');
+ echo human_time_diff(strtotime($item['createdAt'])) .' '. esc_html__('ago', 'wpr-addons');
// Icon: After
// if ( 'after' === $settings['element_extra_icon_pos'] ) {
@@ -445,15 +444,14 @@
}
public function render_post_likes($settings, $class, $item) {
-
echo '<div class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
?>
- <a href="https://twitter.com/intent/like?tweet_id=<?php echo $item['id'] ?>&related=<?php echo $item['user']['screen_name'] ?>" target="_blank" title="Likes">
+ <a href="https://twitter.com/intent/like?tweet_id=<?php echo $item['id'] ?>&related=<?php echo $item['author']['name'] ?>" target="_blank" title="Likes">
<span class=""><i class="fas fa-heart"></i></span>
<span class="wpr-tweet-likes">
- <?php echo $item['favorite_count'] ?>
+ <?php echo $item['likeCount'] ?>
</span>
</a>
<?php
@@ -468,7 +466,7 @@
echo '<div class="inner-block">';
?>
- <a href="https://twitter.com/intent/tweet?in_reply_to=<?php echo $item['id'] ?>&related=<?php echo $item['user']['screen_name'] ?>" target="_blank" title="Comments">
+ <a href="https://twitter.com/intent/tweet?in_reply_to=<?php echo $item['id'] ?>&related=<?php echo $item['author']['name'] ?>" target="_blank" title="Comments">
<span class=""><i class="fas fa-comment"></i></span>
</a>
<?php
@@ -483,10 +481,10 @@
echo '<div class="inner-block">';
?>
- <a href="https://twitter.com/intent/retweet?tweet_id=<?php echo $item['id'] ?>&related=<?php echo $item['user']['screen_name'] ?>" target="_blank" title="Retweets">
+ <a href="https://twitter.com/intent/retweet?tweet_id=<?php echo $item['id'] ?>&related=<?php echo $item['author']['name'] ?>" target="_blank" title="Retweets">
<span class=""><i class="fa fa-retweet"></i></span>
<span class="wpr-retweets">
- <?php echo $item['retweet_count'] ?>
+ <?php echo $item['retweetCount'] ?>
</span>
</a>
<?php
@@ -503,15 +501,24 @@
}
public function render_post_media($settings, $class, $item) {
+
+// echo '<pre>';
+// print_r( $item );
+// echo '</pre>';
- if ( isset($item['extended_entities']) && null !== $item['extended_entities'] ) {
- if ( $item['extended_entities']['media'] ) {
- $media = $item['extended_entities']['media'];
- } else if ( isset( $item['retweeted_status']['entities']['media'] ) ) {
- $media = $item['retweeted_status']['entities']['media'];
- } else if ( isset( $item['quoted_status']['entities']['media'] ) ) {
- $media = $item['quoted_status']['entities']['media'];
- } else {
+ if ( isset($item['extendedEntities']) && null !== $item['extendedEntities'] ) {
+ if ( isset($item['extendedEntities']['media'] ) && !empty( $item['extendedEntities']['media'] ) ) {
+ $media = $item['extendedEntities']['media'];
+ }
+ // Altered logic for Retweets
+ else if ( isset($item['retweeted_tweet']['extendedEntities']['media']) ) {
+ $media = $item['retweeted_tweet']['extendedEntities']['media'];
+ }
+ // Altered logic for Quoted Tweets
+ else if ( isset($item['quoted_tweet']['extendedEntities']['media']) ) {
+ $media = $item['quoted_tweet']['extendedEntities']['media'];
+ }
+ else {
$media = [];
}
}
@@ -520,7 +527,7 @@
echo '<div class="'. esc_attr($class) .'">';
echo '<div class="inner-block">';
// && $media[0]['type'] == 'photo'
- echo (isset( $media[0] )) ? '<img class="wpr-twit-image" src="' . $media[0]['media_url_https'] . '">' : '';
+ echo ( isset( $media[0] ) && !empty($media) ) ? '<img class="wpr-twit-image" src="' . $media[0]['media_url_https'] . '">' : '';
echo '</div>';
echo '</div>';
}
@@ -739,30 +746,16 @@
}
$this->add_control(
- 'twitter_feed_consumer_key',
+ 'twitter_io_api_key',
[
- 'label' => esc_html__('Consumer Key', 'wpr-addons'),
+ 'label' => esc_html__('API key', 'wpr-addons'),
'type' => Controls_Manager::TEXT,
'dynamic' => [
'active' => true,
],
'label_block' => false,
'default' => '',
- 'description' => '<a href="https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret" target="_blank">Get Consumer Key.</a> Create a new app or select existing app and grab the <b>consumer key.</b>',
- ]
- );
-
- $this->add_control(
- 'twitter_feed_consumer_secret',
- [
- 'label' => esc_html__('Consumer Secret', 'wpr-addons'),
- 'type' => Controls_Manager::TEXT,
- 'dynamic' => [
- 'active' => true,
- ],
- 'label_block' => false,
- 'default' => '',
- 'description' => '<a href="https://developer.twitter.com/en/docs/authentication/oauth-1-0a/api-key-and-secret" target="_blank">Get Consumer Secret.</a> Create a new app or select existing app and grab the <b>consumer secret.</b>',
+ 'description' => '<a href="https://twitterapi.io/" target="_blank">Get API Key.</a>Create Account, Go to Dashboard and grab the <b>API Key.</b>',
]
);
@@ -1012,6 +1005,7 @@
'separator' => 'before',
'condition' => [
'layout_select!' => 'carousel',
+ 'test' => 'yes',
]
]
);
@@ -4672,8 +4666,8 @@
protected function render() {
$settings = $this->get_settings_for_display();
- if ( empty($settings['twitter_feed_consumer_key']) || empty($settings['twitter_feed_consumer_secret']) ) {
- echo '<p class="wpr-token-missing">'. esc_html__('Please insert Consumer and Secret Keys in respective fields', 'wpr-addons') .'</p>';
+ if ( empty($settings['twitter_io_api_key']) ) {
+ echo '<p class="wpr-token-missing">'. esc_html__('Please insert API key', 'wpr-addons') .'</p>';
return;
}
@@ -4687,36 +4681,11 @@
array_push($twitter_feed_account_names, $value['twitter_feed_account_name']);
}
- $token = get_transient('wpr_' . $settings['number_of_posts'] . '_' . $this->get_ID() . '_' . implode("_", $twitter_feed_account_names) . '_tf_token');
$expiration = !empty( $settings['auto_clear_cache'] ) && !empty( $settings['twitter_feed_cache_limit'] ) ? absint( $settings['twitter_feed_cache_limit'] ) * MINUTE_IN_SECONDS : DAY_IN_SECONDS;
- $cache_key = 'wpr_' . implode("_", $twitter_feed_account_names) . '_' . $expiration . '_' . md5( $settings['twitter_feed_hashtag_name'] . $settings['twitter_feed_consumer_key'] . $settings['twitter_feed_consumer_secret'] ) . '_tf_cache' . '_' . $settings['number_of_posts'];
+ $cache_key = 'wpr_' . implode("_", $twitter_feed_account_names) . '_' . $expiration . '_' . md5( $settings['twitter_feed_hashtag_name'] . $settings['twitter_io_api_key']) . '_tf_cache' . '_' . $settings['number_of_posts'];
$items_array = get_transient( $cache_key );
if ($items_array === false) {
- if (empty($token)) {
- $credentials = base64_encode($settings['twitter_feed_consumer_key'] . ':' . $settings['twitter_feed_consumer_secret']);
-
- add_filter('https_ssl_verify', '__return_false');
-
- $response = wp_remote_post('https://api.twitter.com/oauth2/token', [
- 'method' => 'POST',
- 'httpversion' => '1.1',
- 'blocking' => true,
- 'headers' => [
- 'Authorization' => 'Basic ' . $credentials,
- 'Content-Type' => 'application/x-www-form-urlencoded;charset=UTF-8',
- ],
- 'body' => ['grant_type' => 'client_credentials'],
- ]);
-
- $body = json_decode(wp_remote_retrieve_body($response));
-
- if ($body) {
- set_transient('wpr_' . $settings['number_of_posts'] . '_' . $this->get_ID() . '_' . implode("_", $twitter_feed_account_names) . '_tf_token', $body->access_token, $expiration);
- $token = $body->access_token;
- }
- }
-
add_filter('https_ssl_verify', '__return_false');
$response = [];
@@ -4729,16 +4698,36 @@
foreach ($settings['twitter_accounts'] as $key=>$value) {
array_push($twitter_feed_account_names, $value['twitter_feed_account_name']);
- $response[$key] = wp_remote_get('https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=' . $value['twitter_feed_account_name'] . '&count='. $settings['number_of_posts'] .'&tweet_mode=extended', [
- 'httpversion' => '1.1',
- 'blocking' => true,
- 'headers' => [
- 'Authorization' => "Bearer $token",
- ],
- ]);
+ $base_url = 'https://api.twitterapi.io/twitter/user/last_tweets';
+ // 2. Add query parameters (userName and limit)
+ $url = add_query_arg( array(
+ 'userName' => $value['twitter_feed_account_name'], // REMOVE the "@" symbol; use "userName"
+ 'limit' => $settings['number_of_posts'], // Use "limit" instead of "count"
+ ), $base_url );
+
+ // 3. Set the Request Headers
+ $args = array(
+ 'headers' => array(
+ 'x-api-key' => $settings['twitter_io_api_key'], // Use your Twitter API
+ ),
+ 'timeout' => 20,
+ 'sslverify' => false, // Better to put this directly in the args for local testing
+ );
+
+ // 4. Make the Request
+ $response[$key] = wp_remote_get( $url, $args );
+
+ // Debugging
if ( is_wp_error( $response[$key] ) ) {
- // return $html;
+ echo "WP_Error: " . $response[$key]->get_error_message();
+ } else {
+ $code = wp_remote_retrieve_response_code( $response[$key] );
+ $body = wp_remote_retrieve_body( $response[$key] );
+ }
+ // 5. Handle Errors and Parse Data
+ if (is_wp_error($response[$key])) {
+ return 'Error: ' . $response[$key]->get_error_message();
}
if ( ! empty( $response[$key]['response'] ) && $response[$key]['response']['code'] == 200 ) {
@@ -4748,8 +4737,13 @@
}
}
+ $cover_picture = '';
+ if ( isset($items_array[0]) ) {
+ $cover_picture = $items_array[0]['data']['tweets'][0]['author']['coverPicture'];
+ }
+
$header_banner_placeholder = WPR_ADDONS_ASSETS_URL . 'img/placeholder.png';
- $header_banner = $items_array[0][0]['user']['profile_banner_url'] ? $items_array[0][0]['user']['profile_banner_url'] : $header_banner_placeholder;
+ $header_banner = $cover_picture ? $cover_picture : $header_banner_placeholder;
$columns_mobile = isset($settings['columns_mobile']) ? $settings['columns_mobile'] : $settings['columns'];
$columns_tablet = isset($settings['columns_tablet']) ? $settings['columns_tablet'] : $settings['columns'];
@@ -4774,8 +4768,7 @@
$twitter_settings['twitter_load_more_settings'] = [
'number_of_posts' => $settings['number_of_posts'],
- 'twitter_feed_consumer_key' => $settings['twitter_feed_consumer_key'],
- 'twitter_feed_consumer_secret' => $settings['twitter_feed_consumer_secret'],
+ 'twitter_io_api_key' => $settings['twitter_io_api_key'],
'twitter_feed_hashtag_name' => $settings['twitter_feed_hashtag_name'],
// 'image_effects' => $settings['image_effects'],
// 'image_effects' => $settings['image_effects_size'],
@@ -4850,20 +4843,20 @@
<div class="wpr-tf-header-content">
<div class="wpr-tf-header-profile-img">
- <img src="<?php echo str_replace('_normal', '', $items_array[0][0]['user']['profile_image_url']) ?>" alt="Image">
+ <img src="<?php echo str_replace('_normal', '', $items_array[0]['data']['tweets'][0]['author']['profilePicture']) ?>" alt="Image">
<div class="wpr-tf-statistics">
<div class="wpr-tf-header-user">
- <p class="wpr-tf-header-user-name"><?php echo $items_array[0][0]['user']['name'] ?></p>
- <p class="wpr-tf-header-user-acc-name"><a href="<?php echo $items_array[0][0]['user']['screen_name'] ?>" target="_blank"><?php echo '@'. $items_array[0][0]['user']['screen_name'] ?></a></p>
+ <p class="wpr-tf-header-user-name"><?php echo $items_array[0]['data']['tweets'][0]['author']['name'] ?></p>
+ <p class="wpr-tf-header-user-acc-name"><a href="<?php echo $items_array[0]['data']['tweets'][0]['author']['userName'] ?>" target="_blank"><?php echo '@'. $items_array[0]['data']['tweets'][0]['author']['userName'] ?></a></p>
</div>
- <span class=""><a href='https://twitter.com/<?php echo $items_array[0][0]['user']['screen_name'] ?>' target="_blank"><span><?php echo $this->format_numbers($items_array[0][0]['user']['statuses_count']) ?></span><span><?php esc_html__(' Tweets', 'wpr-addons') ?></span></a></span>
- <span class=""><a href='https://twitter.com/<?php echo $items_array[0][0]['user']['screen_name'] ?>/following' target="_blank"><span><?php echo $this->format_numbers($items_array[0][0]['user']['friends_count']) ?></span><span><?php esc_html__(' Following', 'wpr-addons') ?></span></a></span>
- <span class=""><a href='https://twitter.com/<?php echo $items_array[0][0]['user']['screen_name'] ?>/followers' target="_blank"><span><?php echo $this->format_numbers($items_array[0][0]['user']['followers_count']) ?></span><span><?php esc_html__(' Followers', 'wpr-addons') ?></span></a></span>
+ <span class=""><a href='https://twitter.com/<?php echo $items_array[0]['data']['tweets'][0]['author']['userName'] ?>' target="_blank"><span><?php echo $this->format_numbers($items_array[0]['data']['tweets'][0]['author']['statusesCount']) ?></span><span><?php echo esc_html__(' Tweets', 'wpr-addons'); ?></span></a></span>
+ <span class=""><a href='https://twitter.com/<?php echo $items_array[0]['data']['tweets'][0]['author']['userName'] ?>/following' target="_blank"><span><?php echo $this->format_numbers($items_array[0]['data']['tweets'][0]['author']['following']) ?></span><span><?php echo esc_html__(' Following', 'wpr-addons'); ?></span></a></span>
+ <span class=""><a href='https://twitter.com/<?php echo $items_array[0]['data']['tweets'][0]['author']['userName'] ?>/followers' target="_blank"><span><?php echo $this->format_numbers($items_array[0]['data']['tweets'][0]['author']['fastFollowersCount']) ?></span><span><?php echo esc_html__(' Followers', 'wpr-addons'); ?></span></a></span>
</div>
</div>
<span class="wpr-twitter-follow-btn-wrap">
- <a class="wpr-twitter-follow-btn" rel="nofollow" href="https://twitter.com/intent/follow?screen_name=<?php echo $items_array[0][0]['user']['screen_name'] ?>" target="_blank">
+ <a class="wpr-twitter-follow-btn" rel="nofollow" href="https://twitter.com/intent/follow?screen_name=<?php echo $items_array[0]['data']['tweets'][0]['author']['userName'] ?>" target="_blank">
Follow
</a>
</span>
@@ -4889,7 +4882,6 @@
if ( 'yes' === $settings['enable_cs_pag'] ) {
echo '<div class="swiper-pagination"></div>';
}
-
echo '<div '. wp_kses_post( $this->get_render_attribute_string( 'twitter_feed' ) ) .'>';
foreach ( $items_array as $key=>$items ) :
@@ -4915,15 +4907,15 @@
}
}
- foreach ( $items as $item) :
+ foreach ( $items['data']['tweets'] as $item ) :
$banner_placeholder = WPR_ADDONS_ASSETS_URL . 'img/placeholder.png';
- $banner = $item['user']['profile_banner_url'] ? $item['user']['profile_banner_url'] : $banner_placeholder;
+ // $banner = $item['author']['profile_banner_url'] ? $item['author']['profile_banner_url'] : $banner_placeholder;
?>
<div class="wpr-tweet elementor-clearfix">
<article class="media">
- <?php
+ <?php
// Content: Above Media
echo $this->get_elements_by_location( 'above', $settings, $item );
?>
--- a/royal-elementor-addons/modules/woo-grid/widgets/wpr-woo-grid.php
+++ b/royal-elementor-addons/modules/woo-grid/widgets/wpr-woo-grid.php
@@ -819,7 +819,7 @@
'advanced_filters',
[
'label' => esc_html__( 'Enable Advanced Filters', 'wpr-addons' ),
- 'description' => esc_html__( 'Turn on Only with Advanced Filters widget.', 'wpr-addons' ),
+ 'description' => esc_html__( 'Turn on Only with Advanced Filters widget. Works with Load More Pagination for now (Other Pagination Types will be applied in next updates as well).', 'wpr-addons' ),
'type' => Controls_Manager::SWITCHER,
'default' => 'no',
'return_value' => 'yes',
--- a/royal-elementor-addons/plugin.php
+++ b/royal-elementor-addons/plugin.php
@@ -77,6 +77,25 @@
return self::$_instance;
}
+ /**
+ * Cached extension/option toggles (reduces get_option calls on every request).
+ */
+ private static $wpr_extension_options = null;
+
+ private function wpr_get_extension_option( $key, $default = 'on' ) {
+ if ( null === self::$wpr_extension_options ) {
+ self::$wpr_extension_options = [
+ 'wpr-particles' => get_option( 'wpr-particles', 'on' ),
+ 'wpr-parallax-background' => get_option( 'wpr-parallax-background', 'on' ),
+ 'wpr-parallax-multi-layer' => get_option( 'wpr-parallax-multi-layer', 'on' ),
+ 'wpr-sticky-section' => get_option( 'wpr-sticky-section', 'on' ),
+ 'wpr-custom-css' => get_option( 'wpr-custom-css', 'on' ),
+ 'wpr_override_woo_templates'=> get_option( 'wpr_override_woo_templates', 'on' ),
+ ];
+ }
+ return isset( self::$wpr_extension_options[ $key ] ) ? self::$wpr_extension_options[ $key ] : $default;
+ }
+
private function _includes() {
// Modules Manager
require WPR_ADDONS_PATH . 'includes/modules-manager.php';
@@ -115,22 +134,22 @@
require WPR_ADDONS_PATH . 'classes/modules/wpr-filter-grid-media.php';
// Particles
- if ( 'on' === get_option('wpr-particles', 'on') ) {//TODO: make this check automatic(loop through) for all extensions
+ if ( 'on' === $this->wpr_get_extension_option( 'wpr-particles' ) ) {
require WPR_ADDONS_PATH . 'extensions/wpr-particles.php';
}
// Parallax
- if ( 'on' === get_option('wpr-parallax-background', 'on') || 'on' === get_option('wpr-parallax-multi-layer', 'on') ) {
+ if ( 'on' === $this->wpr_get_extension_option( 'wpr-parallax-background' ) || 'on' === $this->wpr_get_extension_option( 'wpr-parallax-multi-layer' ) ) {
require WPR_ADDONS_PATH . 'extensions/wpr-parallax.php';
}
// Sticky Header
- if ( 'on' === get_option('wpr-sticky-section', 'on') ) {
+ if ( 'on' === $this->wpr_get_extension_option( 'wpr-sticky-section' ) ) {
require WPR_ADDONS_PATH . 'extensions/wpr-sticky-section.php';
}
// Custom CSS
- if ( 'on' === get_option('wpr-custom-css', 'on') ) {
+ if ( 'on' === $this->wpr_get_extension_option( 'wpr-custom-css' ) ) {
require WPR_ADDONS_PATH . 'extensions/wpr-custom-css.php';
}
@@ -174,7 +193,7 @@
}
if ( class_exists('WooCommerce') ) {
- if ( 'on' === get_option('wpr_override_woo_templates', 'on') ) {
+ if ( 'on' === $this->wpr_get_extension_option( 'wpr_override_woo_templates' ) ) {
// add_filter( 'astra_enable_woocommerce_integration', '__return_false' );
require WPR_ADDONS_PATH . 'includes/woocommerce/woocommerce-config.php';
}
@@ -446,16 +465,18 @@
public function wpr_some_init_actions() {
load_plugin_textdomain('wpr-addons', false, dirname(plugin_basename(__FILE__)) . '/languages/');
- if ( get_option('wpr_hide_banners') !== 'on' ) {
- // Pro Features Notice
- require WPR_ADDONS_PATH . 'admin/notices/pro-features-notice.php';
-
- // Plugin Update Notice
- require WPR_ADDONS_PATH . 'admin/notices/plugin-update-notice.php';
-
- // Plugin Sale Notice
- require WPR_ADDONS_PATH . 'admin/notices/plugin-sale-notice.php';
-
+ // Notices only in admin to reduce frontend CPU (no file I/O on every page view).
+ if ( is_admin() ) {
+ if ( get_option('wpr_hide_banners') !== 'on' ) {
+ // Pro Features Notice
+ require WPR_ADDONS_PATH . 'admin/notices/pro-features-notice.php';
+
+ // Plugin Update Notice
+ require WPR_ADDONS_PATH . 'admin/notices/plugin-update-notice.php';
+
+ // Plugin Sale Notice
+ require WPR_ADDONS_PATH . 'admin/notices/plugin-sale-notice.php';
+ }
// Rating Notice
require WPR_ADDONS_PATH . 'admin/notices/rating-notice.php';
}
@@ -598,6 +619,7 @@
'wishlistPageURL' => get_permalink(get_option('wpr_wishlist_page')),
'chooseQuantityText' => esc_html__('Please select the required number of items.', 'wpr-addons'),
'site_key' => get_option('wpr_recaptcha_v3_site_key'),
+ 'site_key_v2' => get_option('wpr_recaptcha_v2_site_key'),
'is_admin' => current_user_can('manage_options'),
'input_empty' => esc_html__('Please fill out this field', 'wpr-addons'),
'select_empty' => esc_html__('Nothing selected', 'wpr-addons'),
@@ -608,6 +630,7 @@
'woo_shop_tag_ppp' => get_option('wpr_woo_shop_tag_ppp', 9),
'is_product_category' => function_exists('is_product_category') ? is_product_category() : false,
'is_product_tag' => function_exists('is_product_tag') ? is_product_tag() : false,
+ 'sticky_section' => $this->wpr_get_extension_option( 'wpr-sticky-section' ),
// 'token' => $custom_token
]
);
--- a/royal-elementor-addons/wpr-addons.php
+++ b/royal-elementor-addons/wpr-addons.php
@@ -4,7 +4,7 @@
* Description: The only plugin you need for Elementor page builder.
* Plugin URI: https://royal-elementor-addons.com/
* Author: WP Royal
- * Version: 1.7.1049
+ * Version: 1.7.1050
* License: GPLv3
* Author URI: https://royal-elementor-addons.com/
* Elementor tested up to: 3.35.3
@@ -17,7 +17,7 @@
exit; // Exit if accessed directly.
}
-define( 'WPR_ADDONS_VERSION', '1.7.1049' );
+define( 'WPR_ADDONS_VERSION', '1.7.1050' );
define( 'WPR_ADDONS__FILE__', __FILE__ );
define( 'WPR_ADDONS_PLUGIN_BASE', plugin_basename( WPR_ADDONS__FILE__ ) );