Plugin Directory

Changeset 3382845


Ignore:
Timestamp:
10/22/2025 05:48:19 PM (5 months ago)
Author:
stankovski
Message:

Fixed image generation. Version 1.0.2

Location:
digital-signage/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • digital-signage/trunk/digital-signage.php

    r3290139 r3382845  
    33Plugin Name: Digital Signage
    44Description: Adds a page that displays a digital signage gallery of images from your WordPress posts.
    5 Version: 1.0.1
     5Version: 1.0.2
    66Author: stankovski
    77Author URI: https://github.com/stankovski/
     
    7575}
    7676
     77// Get image URL with modern format support (WebP, AVIF, etc.)
     78function digsign_get_modern_image_url($post_id, $image_size) {
     79    $thumb_id = get_post_thumbnail_id($post_id);
     80    if (!$thumb_id) {
     81        return false;
     82    }
     83   
     84    // Check if webp-uploads plugin is active and modern formats should be used
     85    $use_modern_formats = is_plugin_active('webp-uploads/webp-uploads.php') ||
     86                         is_plugin_active('performance-lab/performance-lab.php') ||
     87                         function_exists('webp_uploads_get_image_output_format');
     88   
     89    if ($use_modern_formats) {
     90        // Get attachment metadata to check for modern format sources
     91        $metadata = wp_get_attachment_metadata($thumb_id);
     92        if (!empty($metadata) && isset($metadata['sizes'][$image_size]['sources'])) {
     93            $upload_dir = wp_upload_dir();
     94            $base_url = trailingslashit($upload_dir['baseurl']);
     95            $file_dir = dirname($metadata['file']);
     96           
     97            // Get the preferred modern format
     98            $preferred_format = 'webp';
     99            if (function_exists('webp_uploads_get_image_output_format')) {
     100                $preferred_format = webp_uploads_get_image_output_format();
     101            }
     102           
     103            // Look for modern format in sources
     104            $sources = $metadata['sizes'][$image_size]['sources'];
     105            if (isset($sources['image/' . $preferred_format])) {
     106                $modern_file = $sources['image/' . $preferred_format]['file'];
     107                return $base_url . trailingslashit($file_dir) . $modern_file;
     108            }
     109           
     110            // Fallback: look for any WebP source if preferred format not found
     111            if ($preferred_format !== 'webp' && isset($sources['image/webp'])) {
     112                $webp_file = $sources['image/webp']['file'];
     113                return $base_url . trailingslashit($file_dir) . $webp_file;
     114            }
     115        }
     116       
     117        // Check if full-size image has modern format sources
     118        if (!empty($metadata) && isset($metadata['sources'])) {
     119            $upload_dir = wp_upload_dir();
     120            $base_url = trailingslashit($upload_dir['baseurl']);
     121            $file_dir = dirname($metadata['file']);
     122           
     123            $preferred_format = 'webp';
     124            if (function_exists('webp_uploads_get_image_output_format')) {
     125                $preferred_format = webp_uploads_get_image_output_format();
     126            }
     127           
     128            // Look for modern format in full-size sources
     129            $sources = $metadata['sources'];
     130            if (isset($sources['image/' . $preferred_format])) {
     131                $modern_file = $sources['image/' . $preferred_format]['file'];
     132                return $base_url . trailingslashit($file_dir) . $modern_file;
     133            }
     134           
     135            // Fallback: look for any WebP source if preferred format not found
     136            if ($preferred_format !== 'webp' && isset($sources['image/webp'])) {
     137                $webp_file = $sources['image/webp']['file'];
     138                return $base_url . trailingslashit($file_dir) . $webp_file;
     139            }
     140        }
     141    }
     142   
     143    // Fallback to standard method
     144    return get_the_post_thumbnail_url($post_id, $image_size);
     145}
     146
    77147// Register custom image size (do not hook to after_setup_theme)
    78148function digsign_register_image_sizes() {
     
    156226require_once plugin_dir_path(__FILE__) . 'settings.php';
    157227
     228/**
     229 * Collect media (slides or image URLs) for a given category.
     230 * Options (array):
     231 *  - category_name (string)
     232 *  - image_size (string) image size name to request
     233 *  - include_html (bool) whether to fallback to post HTML content when no featured image
     234 *  - include_qr (bool) whether to generate QR codes for posts
     235 *  - structure (string) 'slides' for detailed slide objects or 'urls' for simple list of image URLs
     236 *
     237 * @return array
     238 */
     239function digsign_collect_media($options = []) {
     240    // Performance timing instrumentation
     241    $start_time = microtime(true);
     242    $timings = [];
     243   
     244    $defaults = [
     245        'category_name' => 'news',
     246        'image_size'    => 'digsign-gallery-thumb',
     247        'include_html'  => true,
     248        'include_qr'    => true,
     249        'structure'     => 'slides', // 'slides' or 'urls'
     250    ];
     251    $opts = wp_parse_args($options, $defaults);
     252
     253    $args = [
     254        'category_name'  => $opts['category_name'],
     255        'posts_per_page' => -1,
     256        'post_status'    => 'publish',
     257    ];
     258   
     259    $query_start = microtime(true);
     260    $query = new WP_Query($args);
     261    $timings['database_query'] = (microtime(true) - $query_start) * 1000;
     262   
     263    $results = [];
     264    $processed_posts = 0;
     265    $qr_generation_time = 0;
     266    $image_processing_time = 0;
     267
     268    if ($query->have_posts()) {
     269        while ($query->have_posts()) {
     270            $query->the_post();
     271            $post_id  = get_the_ID();
     272            $thumb_id = get_post_thumbnail_id($post_id);
     273           
     274            // Time QR code generation
     275            $qr_start = microtime(true);
     276            $qr_code_url = ($opts['include_qr']) ? digsign_generate_qrcode($post_id) : '';
     277            $qr_generation_time += (microtime(true) - $qr_start) * 1000;
     278
     279            if ($thumb_id) {
     280                $img_start = microtime(true);
     281               
     282                // PERFORMANCE FIX: Skip expensive synchronous image regeneration
     283                // Instead, use existing image sizes or fallback gracefully
     284                $meta = wp_get_attachment_metadata($thumb_id);
     285               
     286                // Log when image size is missing (for debugging)
     287                if (!isset($meta['sizes'][$opts['image_size']])) {
     288                    error_log("Digital Signage: Missing image size '{$opts['image_size']}' for attachment {$thumb_id}, using fallback");
     289                }
     290               
     291                // Get image URL with modern format support (WebP if available)
     292                // If the requested size doesn't exist, try fallback sizes
     293                $img_url = digsign_get_modern_image_url($post_id, $opts['image_size']);
     294               
     295                // Fallback to other sizes if the requested size is not available
     296                if (!$img_url && !isset($meta['sizes'][$opts['image_size']])) {
     297                    $fallback_sizes = ['large', 'medium_large', 'medium', 'full'];
     298                    foreach ($fallback_sizes as $fallback_size) {
     299                        $img_url = digsign_get_modern_image_url($post_id, $fallback_size);
     300                        if ($img_url) {
     301                            error_log("Digital Signage: Used fallback size '{$fallback_size}' for post {$post_id}");
     302                            break;
     303                        }
     304                    }
     305                }
     306                if ($img_url) {
     307                    if ($opts['structure'] === 'urls') {
     308                        $results[] = $img_url; // simple list
     309                    } else {
     310                        $results[] = [
     311                            'type'       => 'image',
     312                            'content'    => $img_url,
     313                            'qrcode'     => $qr_code_url,
     314                            'post_title' => get_the_title(),
     315                            'post_url'   => get_permalink($post_id),
     316                        ];
     317                    }
     318                }
     319            } elseif ($opts['include_html'] && $opts['structure'] !== 'urls') {
     320                // Fallback to post content (only for slides structure)
     321                $content = apply_filters('the_content', get_the_content());
     322                if (!empty($content)) {
     323                    $results[] = [
     324                        'type'     => 'html',
     325                        'content'  => $content,
     326                        'title'    => get_the_title(),
     327                        'qrcode'   => $qr_code_url,
     328                        'post_url' => get_permalink($post_id),
     329                    ];
     330                }
     331               
     332                $image_processing_time += (microtime(true) - $img_start) * 1000;
     333            }
     334            $processed_posts++;
     335        }
     336        wp_reset_postdata();
     337    }
     338   
     339    // Performance logging
     340    $total_time = (microtime(true) - $start_time) * 1000;
     341    $timings['total_execution'] = $total_time;
     342    $timings['processed_posts'] = $processed_posts;
     343    $timings['qr_generation'] = $qr_generation_time;
     344    $timings['image_processing'] = $image_processing_time;
     345    $timings['results_count'] = count($results);
     346   
     347    // Add debug info to results if WP_DEBUG is enabled
     348    if (defined('WP_DEBUG') && WP_DEBUG) {
     349        $results['_debug_timing'] = $timings;
     350    }
     351   
     352    return $results;
     353}
     354
    158355// REST API endpoint for gallery images
    159356add_action('rest_api_init', function () {
     
    161358        'methods' => 'GET',
    162359        'callback' => function () {
    163             $category_name = get_option('digsign_category_name', 'news');
    164             $width = intval(get_option('digsign_image_width', 1260));
    165             $height = intval(get_option('digsign_image_height', 940));
    166             $image_size = 'digsign-gallery-thumb';
    167             $refresh_interval = intval(get_option('digsign_refresh_interval', 10));
    168             $slide_delay = absint(get_option('digsign_slide_delay', 5));
    169             $enable_qrcodes = (bool)get_option('digsign_enable_qrcodes', true);
    170             $layout_type = get_option('digsign_layout_type', 'fullscreen');
    171            
    172             $args = [
     360            $category_name     = get_option('digsign_category_name', 'news');
     361            $refresh_interval  = intval(get_option('digsign_refresh_interval', 10));
     362            $slide_delay       = absint(get_option('digsign_slide_delay', 5));
     363            $enable_qrcodes    = (bool)get_option('digsign_enable_qrcodes', true);
     364            $layout_type       = get_option('digsign_layout_type', 'fullscreen');
     365            $slides = digsign_collect_media([
    173366                'category_name' => $category_name,
    174                 'posts_per_page' => -1,
    175                 'post_status' => 'publish',
    176             ];
    177             $query = new WP_Query($args);
    178             $slides = [];
    179             if ($query->have_posts()) {
    180                 while ($query->have_posts()) {
    181                     $query->the_post();
    182                     $post_id = get_the_ID();
    183                     $thumb_id = get_post_thumbnail_id($post_id);
    184                    
    185                     // Generate QR code only if enabled
    186                     $qr_code_url = $enable_qrcodes ? digsign_generate_qrcode($post_id) : '';
    187                    
    188                     if ($thumb_id) {
    189                         // Check if the custom size exists, generate if not
    190                         $meta = wp_get_attachment_metadata($thumb_id);
    191                         if (!isset($meta['sizes'][$image_size])) {
    192                             // Generate the image size on demand
    193                             require_once ABSPATH . 'wp-admin/includes/image.php';
    194                             $fullsizepath = get_attached_file($thumb_id);
    195                             if ($fullsizepath && file_exists($fullsizepath)) {
    196                                 $metadata = wp_generate_attachment_metadata($thumb_id, $fullsizepath);
    197                                 if ($metadata && !is_wp_error($metadata)) {
    198                                     wp_update_attachment_metadata($thumb_id, $metadata);
    199                                 }
    200                             }
    201                         }
    202                         $img_url = get_the_post_thumbnail_url($post_id, $image_size);
    203                         if ($img_url) {
    204                             $slides[] = [
    205                                 'type' => 'image',
    206                                 'content' => $img_url,
    207                                 'qrcode' => $qr_code_url,
    208                                 'post_title' => get_the_title(),
    209                                 'post_url' => get_permalink($post_id)
    210                             ];
    211                         }
    212                     } else {
    213                         // No featured image, use post content instead
    214                         $content = apply_filters('the_content', get_the_content());
    215                         if (!empty($content)) {
    216                             $slides[] = [
    217                                 'type' => 'html',
    218                                 'content' => $content,
    219                                 'title' => get_the_title(),
    220                                 'qrcode' => $qr_code_url,
    221                                 'post_url' => get_permalink($post_id)
    222                             ];
    223                         }
    224                     }
    225                 }
    226                 wp_reset_postdata();
    227             }
    228             $layout_type = get_option('digsign_layout_type', 'fullscreen');
    229            
     367                'image_size'    => 'digsign-gallery-thumb',
     368                'include_html'  => true,
     369                'include_qr'    => $enable_qrcodes,
     370                'structure'     => 'slides'
     371            ]);
    230372            return rest_ensure_response([
    231373                'slides' => $slides,
     
    248390        'callback' => function () {
    249391            $category_name = get_option('dsp_category_name', 'news');
    250             $width = intval(get_option('dsp_image_width', 1260));
    251             $height = intval(get_option('dsp_image_height', 940));
    252             $image_size = 'dsp-gallery-thumb';
    253             $args = [
     392            // Legacy endpoint only returns image URLs (no HTML, no QR codes)
     393            $images = digsign_collect_media([
    254394                'category_name' => $category_name,
    255                 'posts_per_page' => -1,
    256                 'post_status' => 'publish',
    257             ];
    258             $query = new WP_Query($args);
    259             $images = [];
    260             if ($query->have_posts()) {
    261                 while ($query->have_posts()) {
    262                     $query->the_post();
    263                     $post_id = get_the_ID();
    264                     $thumb_id = get_post_thumbnail_id($post_id);
    265                     if ($thumb_id) {
    266                         // Check if the custom size exists, generate if not
    267                         $meta = wp_get_attachment_metadata($thumb_id);
    268                         if (!isset($meta['sizes'][$image_size])) {
    269                             // Generate the image size on demand
    270                             require_once ABSPATH . 'wp-admin/includes/image.php';
    271                             $fullsizepath = get_attached_file($thumb_id);
    272                             if ($fullsizepath && file_exists($fullsizepath)) {
    273                                 $metadata = wp_generate_attachment_metadata($thumb_id, $fullsizepath);
    274                                 if ($metadata && !is_wp_error($metadata)) {
    275                                     wp_update_attachment_metadata($thumb_id, $metadata);
    276                                 }
    277                             }
    278                         }
    279                         $img_url = get_the_post_thumbnail_url($post_id, $image_size);
    280                         if ($img_url) {
    281                             $images[] = $img_url;
    282                         }
    283                     }
    284                 }
    285                 wp_reset_postdata();
    286             }
     395                'image_size'    => 'dsp-gallery-thumb',
     396                'include_html'  => false,
     397                'include_qr'    => false,
     398                'structure'     => 'urls'
     399            ]);
    287400            return rest_ensure_response($images);
    288401        },
  • digital-signage/trunk/readme.txt

    r3290143 r3382845  
    44Requires at least: 5.0
    55Tested up to: 6.8
    6 Stable tag: 1.0.1
     6Stable tag: 1.0.2
    77Requires PHP: 7.0
    88License: MIT
     
    4141== Screenshots ==
    4242
    43 1. Admin settings page
    44 2. Digital signage display showing rotating images
     431. Digital signage display showing rotating images
     442. Admin settings page
    4545
    4646== Changelog ==
     47
     48= 1.0.2 =
     49* Version bump
    4750
    4851= 1.0.1 =
Note: See TracChangeset for help on using the changeset viewer.