Plugin Directory

Changeset 3465484


Ignore:
Timestamp:
02/20/2026 04:08:30 AM (5 weeks ago)
Author:
nutttaro
Message:

fix: resolve media uploader event binding issue for custom pin image upload (v1.1.1)

Location:
wp-featured-posts
Files:
22 added
5 edited

Legend:

Unmodified
Added
Removed
  • wp-featured-posts/trunk/assets/js/setting.js

    r2382708 r3465484  
    11(function($) {
    22
    3     $('.wpfp-toggle-expand').on('click', function (e) {
    4         e.preventDefault();
     3    $(document).ready(function() {
    54
    6         var expand = $(this).data('expand');
    7         if ($(expand).length) {
    8             $(expand).toggle();
    9         }
     5        $('.wpfp-toggle-expand').on('click', function (e) {
     6            e.preventDefault();
    107
    11         if ($(this).hasClass('show')) {
    12             $(this).addClass('hide');
    13             $(this).find('.hide').hide();
    14             $(this).find('.show').show();
    15         } else {
    16             $(this).addClass('show');
    17             $(this).find('.hide').show();
    18             $(this).find('.show').hide();
    19         }
     8            var expand = $(this).data('expand');
     9            if ($(expand).length) {
     10                $(expand).toggle();
     11            }
     12
     13            if ($(this).hasClass('show')) {
     14                $(this).addClass('hide');
     15                $(this).find('.hide').hide();
     16                $(this).find('.show').show();
     17            } else {
     18                $(this).addClass('show');
     19                $(this).find('.hide').show();
     20                $(this).find('.show').hide();
     21            }
     22        });
     23
     24        // Media Uploader for Pin Image
     25        var wpfpMediaUploader;
     26
     27        $(document).on('click', '.wpfp-upload-pin-image', function(e) {
     28            e.preventDefault();
     29
     30            // If the uploader already exists, reopen it
     31            if (wpfpMediaUploader) {
     32                wpfpMediaUploader.open();
     33                return;
     34            }
     35
     36            // Create a new media uploader
     37            wpfpMediaUploader = wp.media({
     38                title: 'Select Pin Icon Image',
     39                button: {
     40                    text: 'Use this image'
     41                },
     42                multiple: false
     43            });
     44
     45            // When an image is selected in the media uploader
     46            wpfpMediaUploader.on('select', function() {
     47                var attachment = wpfpMediaUploader.state().get('selection').first().toJSON();
     48                $('#wp-featured-posts-pin-image').val(attachment.url);
     49                $('.wpfp-pin-preview img').attr('src', attachment.url);
     50                $('.wpfp-pin-preview').show();
     51                $('.wpfp-remove-pin-image').show();
     52            });
     53
     54            // Open the uploader
     55            wpfpMediaUploader.open();
     56        });
     57
     58        // Remove pin image
     59        $(document).on('click', '.wpfp-remove-pin-image', function(e) {
     60            e.preventDefault();
     61            $('#wp-featured-posts-pin-image').val('');
     62            $('.wpfp-pin-preview').hide();
     63            $(this).hide();
     64        });
    2065
    2166
    22     });
    23 
    2467})(jQuery);
  • wp-featured-posts/trunk/assets/js/setting.min.js

    r2382708 r3465484  
    1 !function(h){h(".wpfp-toggle-expand").on("click",function(s){s.preventDefault();var i=h(this).data("expand");h(i).length&&h(i).toggle(),h(this).hasClass("show")?(h(this).addClass("hide"),h(this).find(".hide").hide(),h(this).find(".show").show()):(h(this).addClass("show"),h(this).find(".hide").show(),h(this).find(".show").hide())})}(jQuery);
     1!function(a){a(document).ready(function(){a(".wpfp-toggle-expand").on("click",function(b){b.preventDefault();var c=a(this).data("expand");a(c).length&&a(c).toggle(),a(this).hasClass("show")?(a(this).addClass("hide"),a(this).find(".hide").hide(),a(this).find(".show").show()):(a(this).addClass("show"),a(this).find(".hide").show(),a(this).find(".show").hide())});var b;a(document).on("click",".wpfp-upload-pin-image",function(c){c.preventDefault(),b?b.open():(b=wp.media({title:"Select Pin Icon Image",button:{text:"Use this image"},multiple:!1}),b.on("select",function(){var c=b.state().get("selection").first().toJSON();a("#wp-featured-posts-pin-image").val(c.url),a(".wpfp-pin-preview img").attr("src",c.url),a(".wpfp-pin-preview").show(),a(".wpfp-remove-pin-image").show()}),b.open())}),a(document).on("click",".wpfp-remove-pin-image",function(b){b.preventDefault(),a("#wp-featured-posts-pin-image").val(""),a(".wpfp-pin-preview").hide(),a(this).hide()})})}(jQuery);
  • wp-featured-posts/trunk/inc/wp-featured-posts-setting.php

    r3465479 r3465484  
    3333    {
    3434        if ($hook === 'toplevel_page_wp-featured-posts-settings-page') {
     35            wp_enqueue_media();
    3536            wp_enqueue_script('admin-featured-sorting-setting', WPFP_PLUGIN_URL . '/assets/js/setting.min.js', ['jquery'], WPFP_VERSION, true);
    3637        }
     
    125126
    126127        add_settings_section(
     128            'wp_featured_pin_icon_settings_section', // ID
     129            __('Pin Icon Settings', 'wp-featured-posts'), // Title
     130            [$this, 'wp_featured_pin_icon_settings_section'], // Callback
     131            'wp-featured-posts-settings-page' // Page
     132        );
     133
     134        add_settings_field(
     135            'wp-featured-posts-pin-enable', // ID
     136            __('Enable Pin Icon', 'wp-featured-posts'), // Title
     137            [$this, 'pin_enable_field'], // Callback
     138            'wp-featured-posts-settings-page', // Page
     139            'wp_featured_pin_icon_settings_section'
     140        );
     141
     142        add_settings_field(
     143            'wp-featured-posts-pin-size', // ID
     144            __('Pin Icon Size', 'wp-featured-posts'), // Title
     145            [$this, 'pin_size_field'], // Callback
     146            'wp-featured-posts-settings-page', // Page
     147            'wp_featured_pin_icon_settings_section'
     148        );
     149
     150        add_settings_field(
     151            'wp-featured-posts-pin-image', // ID
     152            __('Custom Pin Image', 'wp-featured-posts'), // Title
     153            [$this, 'pin_image_field'], // Callback
     154            'wp-featured-posts-settings-page', // Page
     155            'wp_featured_pin_icon_settings_section'
     156        );
     157
     158        add_settings_section(
    127159            'wp_featured_sticky_posts_settings_section', // ID
    128160            '', // Title
     
    145177            'post_types'       => [],
    146178            'sticky_post_type' => [],
     179            'pin_enable'       => 0,
     180            'pin_size'         => 16,
     181            'pin_image'        => '',
    147182        ];
    148183
    149184        $sanitized_input = array_merge($sanitized_input, $input);
     185
     186        // Sanitize pin size
     187        if (isset($sanitized_input['pin_size'])) {
     188            $sanitized_input['pin_size'] = absint($sanitized_input['pin_size']);
     189            if ($sanitized_input['pin_size'] < 10) {
     190                $sanitized_input['pin_size'] = 10;
     191            }
     192            if ($sanitized_input['pin_size'] > 50) {
     193                $sanitized_input['pin_size'] = 50;
     194            }
     195        }
     196
     197        // Sanitize pin image URL
     198        if (isset($sanitized_input['pin_image'])) {
     199            $sanitized_input['pin_image'] = esc_url_raw($sanitized_input['pin_image']);
     200        }
    150201
    151202        return $sanitized_input;
     
    212263    }
    213264
     265
     266    public function wp_featured_pin_icon_settings_section()
     267    {
     268        echo '<p>' . __('Configure the pin icon that appears next to featured post titles.', 'wp-featured-posts') . '</p>';
     269    }
     270
     271    public function pin_enable_field()
     272    {
     273        $pin_enable = isset($this->options['pin_enable']) ? $this->options['pin_enable'] : 0;
     274        echo '<label for="wp-featured-posts-pin-enable"><input type="checkbox" id="wp-featured-posts-pin-enable" name="wp_featured_posts_settings[pin_enable]" value="1" ' . checked($pin_enable, 1, false) . ' > ' . __('Show pin icon next to featured post titles', 'wp-featured-posts') . '</label>';
     275    }
     276
     277    public function pin_size_field()
     278    {
     279        $pin_size = isset($this->options['pin_size']) ? $this->options['pin_size'] : 16;
     280        echo '<input type="number" id="wp-featured-posts-pin-size" name="wp_featured_posts_settings[pin_size]" value="' . esc_attr($pin_size) . '" min="10" max="50" step="1" style="width: 80px;"> <span class="description">' . __('px (10-50)', 'wp-featured-posts') . '</span>';
     281    }
     282
     283    public function pin_image_field()
     284    {
     285        $pin_image = isset($this->options['pin_image']) ? $this->options['pin_image'] : '';
     286        ?>
     287        <div class="wpfp-pin-image-upload">
     288            <input type="hidden" id="wp-featured-posts-pin-image" name="wp_featured_posts_settings[pin_image]" value="<?php echo esc_attr($pin_image); ?>">
     289            <button type="button" class="button wpfp-upload-pin-image"><?php _e('Upload Image', 'wp-featured-posts'); ?></button>
     290            <button type="button" class="button wpfp-remove-pin-image" style="<?php echo empty($pin_image) ? 'display:none;' : ''; ?>"><?php _e('Remove Image', 'wp-featured-posts'); ?></button>
     291            <div class="wpfp-pin-preview" style="margin-top: 10px;<?php echo empty($pin_image) ? 'display:none;' : ''; ?>">
     292                <img src="<?php echo esc_url($pin_image); ?>" style="max-width: 100px; height: auto;">
     293            </div>
     294            <p class="description"><?php _e('Leave empty to use default pin icon (📌). Recommended size: 32x32px or larger.', 'wp-featured-posts'); ?></p>
     295        </div>
     296        <?php
     297    }
    214298
    215299    public function wp_featured_sticky_posts_settings_section()
  • wp-featured-posts/trunk/readme.txt

    r3465479 r3465484  
    55Requires at least: 4.7
    66Tested up to: 6.9
    7 Stable tag: 1.1.0
     7Stable tag: 1.1.1
    88Requires PHP: 7.4
    99License: GPLv2 or later
     
    4848== Changelog ==
    4949
     50= 1.1.1 =
     51* Fix: Resolved media uploader not working for custom pin image upload
     52* Fix: Improved JavaScript initialization with proper DOM ready handling
     53* Fix: Enhanced event delegation for better compatibility
     54
    5055= 1.1.0 =
    5156* Security: Added ABSPATH checks to prevent direct file access
     
    5459* Enhancement: Fixed wp_send_json_* function usage (removed incorrect echo statements)
    5560* Enhancement: Modernized code to comply with WordPress coding standards
     61* Enhancement: Fixed deprecated FILTER_SANITIZE_STRING for PHP 8.1+ compatibility
     62* Enhancement: Fixed undefined variable $q in sticky posts logic
     63* Feature: Added pin icon display for featured posts with customizable settings
     64* Feature: Pin icon can be enabled/disabled per configuration
     65* Feature: Adjustable pin icon size (10-50px)
     66* Feature: Support for custom pin image upload
     67* Feature: Pin icon position can be filtered (before/after title)
     68* Fix: Featured posts now work correctly on category, tag, author, and date archive pages
    5669* Compatibility: Tested up to WordPress 6.9
    5770
  • wp-featured-posts/trunk/wp-featured-posts.php

    r3465479 r3465484  
    44 * Plugin URI:        https://wordpress.org/plugins/wp-featured-posts/
    55 * Description:       Set featured posts, sortable and sticky custom post type. Compatible with WPML.
    6  * Version:           1.1.0
     6 * Version:           1.1.1
    77 * Requires at least: 4.7
    88 * Requires PHP:      7.4
     
    2424define('WPFP_BASENAME', plugin_basename(__FILE__));
    2525define('WPFP_PLUGIN_URL', plugin_dir_url(__FILE__));
    26 define('WPFP_VERSION', '1.1.0');
     26define('WPFP_VERSION', '1.1.1');
    2727
    2828/**
     
    7474            'post_types'       => [],
    7575            'sticky_post_type' => [],
     76            'pin_enable'       => 0,
     77            'pin_size'         => 16,
     78            'pin_image'        => '',
    7679        ];
    7780
     
    8386
    8487        add_filter('plugin_action_links_' . WPFP_BASENAME, [$this, 'add_plugin_donate_link']);
     88
     89        // Pin icon functionality
     90        if ($this->options['enable'] && $this->options['pin_enable']) {
     91            add_filter('the_title', [$this, 'add_pin_icon_to_title'], 10, 2);
     92            add_action('wp_head', [$this, 'add_pin_icon_styles']);
     93        }
    8594    }
    8695
     
    255264        check_ajax_referer('save-featured-sorting');
    256265
    257         $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
     266        $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    258267
    259268        $data['_redirect'] = $data['_wp_http_referer'];
     
    327336        check_ajax_referer('delete-featured-sorting');
    328337
    329         $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
     338        $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    330339
    331340        if ($data['post_type'] == 'post') {
     
    402411        check_ajax_referer('order-featured-sorting');
    403412
    404         $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_STRING);
     413        $data = filter_input_array(INPUT_POST, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
    405414
    406415        $post_ids = $data['post_id'];
     
    524533                foreach ($this->options['sticky_post_type'] as $sticky_post_type) {
    525534
    526                     if ($wp_query->is_home() && $sticky_post_type == 'post' || $wp_query->get('post_type') == $sticky_post_type) {
     535                    $is_post_archive = ($wp_query->is_home() || $wp_query->is_category() || $wp_query->is_tag() || $wp_query->is_author() || $wp_query->is_date()) && $sticky_post_type == 'post';
     536                    $is_custom_post_type = $wp_query->get('post_type') == $sticky_post_type;
     537
     538                    if ($is_post_archive || $is_custom_post_type) {
    527539
    528540                        // Get original meta query
     
    568580    {
    569581        $post_type = $wp_query->query_vars['post_type'];
     582
     583        // Handle standard post archives (category, tag, etc.) where post_type is empty
     584        if (empty($post_type) && ($wp_query->is_home() || $wp_query->is_category() || $wp_query->is_tag() || $wp_query->is_author() || $wp_query->is_date())) {
     585            $post_type = 'post';
     586        }
     587
    570588        if (!is_admin() && $wp_query->is_main_query() && $this->options['enable'] && in_array($post_type, $this->options['sticky_post_type'])) {
    571589
     
    605623
    606624                // If any posts have been excluded specifically, Ignore those that are sticky.
    607                 if (!empty($sticky_posts) && !empty($q['post__not_in'])) {
    608                     $sticky_posts = array_diff($sticky_posts, $q['post__not_in']);
     625                if (!empty($sticky_posts) && !empty($wp_query->query_vars['post__not_in'])) {
     626                    $sticky_posts = array_diff($sticky_posts, $wp_query->query_vars['post__not_in']);
    609627                }
    610628
     
    652670            $set_default_options = true;
    653671        }
     672        if (!isset($this->options['pin_enable'])) {
     673            $this->options['pin_enable'] = 0;
     674            $set_default_options = true;
     675        }
     676        if (!isset($this->options['pin_size'])) {
     677            $this->options['pin_size'] = 16;
     678            $set_default_options = true;
     679        }
     680        if (!isset($this->options['pin_image'])) {
     681            $this->options['pin_image'] = '';
     682            $set_default_options = true;
     683        }
    654684
    655685        if ($set_default_options) {
     
    658688    }
    659689
     690    /**
     691     * Add pin icon to featured post titles
     692     *
     693     * @param string $title
     694     * @param int $post_id
     695     * @return string
     696     */
     697    public function add_pin_icon_to_title($title, $post_id)
     698    {
     699        // Only add pin icon on frontend, not in admin or feeds
     700        if (is_admin() || is_feed()) {
     701            return $title;
     702        }
     703
     704        // Get post type
     705        $post_type = get_post_type($post_id);
     706
     707        // Check if this post type has pin icon enabled
     708        if (!in_array($post_type, $this->options['post_types'])) {
     709            return $title;
     710        }
     711
     712        // Check if this post is featured
     713        $featured_key = "{$post_type}_featured";
     714        $is_featured = get_post_meta($post_id, $featured_key, true);
     715
     716        if ($is_featured != '1') {
     717            return $title;
     718        }
     719
     720        // Build pin icon HTML
     721        $pin_html = $this->get_pin_icon_html();
     722
     723        // Allow filtering of pin position (before or after title)
     724        $position = apply_filters('wpfp_pin_icon_position', 'before', $post_id);
     725
     726        if ($position === 'after') {
     727            return $title . ' ' . $pin_html;
     728        }
     729
     730        return $pin_html . ' ' . $title;
     731    }
     732
     733    /**
     734     * Get pin icon HTML
     735     *
     736     * @return string
     737     */
     738    private function get_pin_icon_html()
     739    {
     740        $pin_size = isset($this->options['pin_size']) ? absint($this->options['pin_size']) : 16;
     741        $pin_image = isset($this->options['pin_image']) ? $this->options['pin_image'] : '';
     742
     743        if (!empty($pin_image)) {
     744            // Use custom image
     745            return sprintf(
     746                '<span class="wpfp-pin-icon wpfp-pin-custom"><img src="%s" alt="%s" width="%d" height="%d"></span>',
     747                esc_url($pin_image),
     748                esc_attr__('Featured', 'wp-featured-posts'),
     749                $pin_size,
     750                $pin_size
     751            );
     752        }
     753
     754        // Use default emoji pin
     755        return sprintf(
     756            '<span class="wpfp-pin-icon wpfp-pin-default" style="font-size:%dpx;">📌</span>',
     757            $pin_size
     758        );
     759    }
     760
     761    /**
     762     * Add pin icon styles to frontend
     763     */
     764    public function add_pin_icon_styles()
     765    {
     766        ?>
     767        <style type="text/css">
     768            .wpfp-pin-icon {
     769                display: inline-block;
     770                vertical-align: middle;
     771                line-height: 1;
     772            }
     773            .wpfp-pin-icon.wpfp-pin-custom img {
     774                display: inline-block;
     775                vertical-align: middle;
     776            }
     777            .wpfp-pin-icon.wpfp-pin-default {
     778                margin-right: 4px;
     779            }
     780        </style>
     781        <?php
     782    }
    660783
    661784    /**
     
    667790    public function add_plugin_donate_link($links)
    668791    {
    669         $links[] = '<a href="https://www.buymeacoffee.com/nutttaro" target="_blank">' . __('Donate', 'video-player-for-wpbakery') . '</a>';
     792        $links[] = '<a href="https://www.buymeacoffee.com/nutttaro" target="_blank">' . __('Donate', 'wp-featured-posts') . '</a>';
    670793        return $links;
    671794    }
Note: See TracChangeset for help on using the changeset viewer.