Plugin Directory

Changeset 3378680


Ignore:
Timestamp:
10/15/2025 07:54:44 AM (6 months ago)
Author:
shutterpressgallery
Message:

Update to version 1.7.6 from GitHub

Location:
shutterpress-gallery
Files:
30 edited
1 copied

Legend:

Unmodified
Added
Removed
  • shutterpress-gallery/tags/1.7.6/README.txt

    r3376238 r3378680  
    66Tested up to: 6.8
    77Requires PHP: 8.0
    8 Stable tag: 1.7.5
     8Stable tag: 1.7.6
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    119119
    120120== Changelog ==
     121
     122= 1.7.6 =
     123
     124* Update - Shortcodes show current post gallery when no id is set
     125* Update - Refactor Gallery Block Defaults
     126* Fix - Shortcodes take defaults from gallery template
    121127
    122128= 1.7.5 =
  • shutterpress-gallery/tags/1.7.6/includes/blocks/shutterpress-gallery-block/block.json

    r3376238 r3378680  
    2727    "galleryLayout": {
    2828      "type": "string",
    29       "default": "masonry"
     29      "default": "grid"
    3030    },
    3131    "galleryGap": {
  • shutterpress-gallery/tags/1.7.6/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block-render.php

    r3371808 r3378680  
    6767                if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    6868                    $gallery_attributes['infinite_scroll'] = '0';
     69                    $gallery_attributes['use_lightbox'] = '0';
    6970                }
    7071
    7172                if (method_exists($renderer, 'set_attributes')) {
    7273                    $renderer->set_attributes($gallery_attributes);
    73                 }
    74 
    75                 if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    7674                }
    7775
  • shutterpress-gallery/tags/1.7.6/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block.asset.php

    r3376238 r3378680  
    1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '0961de81d9cf02dac39c');
     1<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'aead3cea6f4ea9eea0c9');
  • shutterpress-gallery/tags/1.7.6/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block.js

    r3376238 r3378680  
    1 (()=>{"use strict";var e={n:l=>{var t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var r in t)e.o(t,r)&&!e.o(l,r)&&Object.defineProperty(l,r,{enumerable:!0,get:t[r]})},o:(e,l)=>Object.prototype.hasOwnProperty.call(e,l)};const l=window.wp.blocks,t=window.wp.element,r=window.wp.components,s=window.wp.i18n,o=window.wp.blockEditor,a=window.wp.apiFetch;var n=e.n(a);const u=JSON.parse('{"UU":"shutterpress-gallery/shutterpress-gallery-block"}'),i=window.wp.serverSideRender;var p=e.n(i);const g=window.ReactJSXRuntime;(0,l.registerBlockType)(u.UU,{attributes:{galleryId:{type:"number",default:-1},useLightbox:{type:"boolean",default:!0},showDefaultButtons:{type:"boolean",default:!0},galleryLayout:{type:"string",default:"masonry"},galleryGap:{type:"number",default:20},rowHeight:{type:"number",default:300},columns_desktop:{type:"number",default:3},columns_tablet:{type:"number",default:2},columns_mobile:{type:"number",default:1},hasLoadedDefaults:{type:"boolean",default:!1}},edit:function(e){const{attributes:l,setAttributes:a}=e,{galleryId:i,useLightbox:c,showDefaultButtons:d,galleryLayout:h,galleryGap:y,rowHeight:b,columns_desktop:_,columns_tablet:m,columns_mobile:v}=l,[f,w]=(0,t.useState)([]),[x,j]=(0,t.useState)(!0),[S,L]=(0,t.useState)(null),k=(0,o.useBlockProps)();(0,t.useEffect)(()=>{j(!0),L(null);let e=[];const t=async(l=1)=>{const r=await n()({path:`wp/v2/shutterpress-gallery?per_page=100&page=${l}`,parse:!1}),s=await r.json();if(e=e.concat(Array.isArray(s)?s:[]),l<parseInt(r.headers.get("X-WP-TotalPages")||"1",10))return t(l+1)};t(1).then(()=>{w(e),j(!1)}).catch(e=>{L(e&&e.message?e.message:String(e)),w([]),j(!1)}),l.hasLoadedDefaults||n()({path:"shutterpress/v1/options"}).then(e=>{const t=(e,l)=>{const t=parseInt(e,10);return Number.isFinite(t)?t:l},r={};void 0!==l.useLightbox&&null!==l.useLightbox||(r.useLightbox=!!e.sp_gallery_use_lightbox),void 0!==l.galleryLayout&&null!==l.galleryLayout||(r.galleryLayout=e.sp_gallery_layout||"masonry"),void 0!==l.galleryGap&&null!==l.galleryGap||(r.galleryGap=t(e.sp_gallery_column_gap,20)),void 0!==l.rowHeight&&null!==l.rowHeight||(r.rowHeight=t(e.sp_gallery_justified_row_height,300)),void 0!==l.columns_desktop&&null!==l.columns_desktop||(r.columns_desktop=t(e.sp_gallery_columns_desktop,3)),void 0!==l.columns_tablet&&null!==l.columns_tablet||(r.columns_tablet=t(e.sp_gallery_columns_tablet,2)),void 0!==l.columns_mobile&&null!==l.columns_mobile||(r.columns_mobile=t(e.sp_gallery_columns_mobile,1)),a({...r,hasLoadedDefaults:!0})}).catch(e=>{console.error("Error fetching options:",e),a({hasLoadedDefaults:!0})})},[l.hasLoadedDefaults]);const C=(()=>{if(!x&&Array.isArray(f)&&f.length>0){const e=f.map(e=>({label:e.title?.rendered||(0,s.__)("Untitled Gallery","shutterpress-gallery"),value:String(e.id)}));return[{label:(0,s.__)("Use Post Gallery","shutterpress-gallery"),value:"-1"},...e]}return[]})(),N=(e,l)=>Number.isFinite(e)?e:l,G={galleryId:N(i,0),useLightbox:!!c,showDefaultButtons:!!d,galleryLayout:h||"masonry",galleryGap:N(y,20),rowHeight:"justified"===h?N(b,300):void 0,columns_desktop:"grid"===h||"masonry"===h?N(_,3):void 0,columns_tablet:"grid"===h||"masonry"===h?N(m,2):void 0,columns_mobile:"grid"===h||"masonry"===h?N(v,1):void 0},I=Object.fromEntries(Object.entries(G).filter(([,e])=>null!=e)),P=I;return(0,g.jsxs)("div",{...k,children:[x&&(0,g.jsx)(r.Spinner,{}),Number.isFinite(i)&&-1===i&&!x&&!S&&(0,g.jsx)("div",{className:"sp-gallery-block-preview",children:(0,g.jsx)("div",{className:"components-placeholder",children:(0,g.jsx)("p",{children:(0,s.__)("ShutterPress Gallery. View the post to see images.","shutterpress-gallery")})})}),Number.isFinite(i)&&i>0&&!x&&!S&&(0,g.jsxs)("div",{className:"sp-gallery-block-preview",children:[console&&"function"==typeof console.log?console.log("[ShutterPress] SSR attributes",I):null,(0,g.jsx)(p(),{block:u.UU,httpMethod:"GET",attributes:P,LoadingResponsePlaceholder:()=>(0,g.jsx)(r.Spinner,{}),ErrorResponsePlaceholder:e=>{const l=e&&e.error?e.error:null;console&&"function"==typeof console.error&&console.error("[ShutterPress] SSR error props",e);let t=(0,s.__)("Error rendering block","shutterpress-gallery");if(l)if("string"==typeof l)t=l;else if(l&&"string"==typeof l.message)t=l.message;else try{t=JSON.stringify(l)}catch(e){t=String(l)}return console&&"function"==typeof console.error&&console.error("[ShutterPress] Block render error",l),(0,g.jsx)("div",{className:"components-error",children:(0,g.jsx)("p",{children:t})})}})]}),S&&(0,g.jsx)("p",{style:{color:"red"},children:(0,s.sprintf)((0,s.__)("Error: %s","shutterpress-gallery"),S)}),(0,g.jsx)(o.InspectorControls,{children:(0,g.jsxs)(r.PanelBody,{title:(0,s.__)("Gallery Settings","shutterpress-gallery"),initialOpen:!0,children:[(0,g.jsx)(r.ComboboxControl,{label:(0,s.__)("Select Gallery","shutterpress-gallery"),value:String(Number.isFinite(i)?i:""),options:C,onChange:e=>{const l=parseInt(e,10);a({galleryId:Number.isFinite(l)?l:0})},help:x?(0,s.__)("Loading galleries…","shutterpress-gallery"):S?(0,s.__)("Error loading galleries","shutterpress-gallery"):(0,s.__)("Type to search by gallery name","shutterpress-gallery"),disabled:x||!!S}),(0,g.jsx)(r.ToggleControl,{label:(0,s.__)("Use Lightbox","shutterpress-gallery"),checked:c,onChange:e=>a({useLightbox:!!e})}),(0,g.jsx)(r.ToggleControl,{label:(0,s.__)("Use Default Buttons","shutterpress-gallery"),checked:d,onChange:e=>a({showDefaultButtons:!!e})}),(0,g.jsxs)("p",{className:"components-base-control__help",children:[(0,s.sprintf)((0,s.__)('If you want to add custom buttons, set the button HTML anchor to "%s".',"shutterpress-gallery"),`sp-gallery-filter-liked-photos-${i}`)," ",(0,g.jsx)("a",{href:"https://shutterpress.io",target:"_blank",rel:"noopener noreferrer",children:(0,s.__)("See ShutterPress.io for more info.","shutterpress-gallery")})]}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Layout","shutterpress-gallery"),value:h,options:[{label:(0,s.__)("Masonry","shutterpress-gallery"),value:"masonry"},{label:(0,s.__)("Grid","shutterpress-gallery"),value:"grid"},{label:(0,s.__)("Justified","shutterpress-gallery"),value:"justified"}],onChange:e=>a({galleryLayout:e})}),(0,g.jsx)(r.RangeControl,{label:(0,s.__)("Image Gap","shutterpress-gallery"),value:y,onChange:e=>a({galleryGap:parseInt(e,10)}),min:0,max:100}),"justified"===h&&(0,g.jsx)(r.RangeControl,{label:(0,s.__)("Row Height","shutterpress-gallery"),value:b,onChange:e=>a({rowHeight:parseInt(e,10)}),min:0,max:1e3}),("grid"===h||"masonry"===h)&&(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Desktop Columns","shutterpress-gallery"),value:_,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8},{label:"9",value:9},{label:"10",value:10}],onChange:e=>a({columns_desktop:parseInt(e,10)})}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Tablet Columns","shutterpress-gallery"),value:m,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8}],onChange:e=>a({columns_tablet:parseInt(e,10)})}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Mobile Columns","shutterpress-gallery"),value:v,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4}],onChange:e=>a({columns_mobile:parseInt(e,10)})})]})]})})]})},save:function(){return null}})})();
     1(()=>{"use strict";var e={n:l=>{var t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var s in t)e.o(t,s)&&!e.o(l,s)&&Object.defineProperty(l,s,{enumerable:!0,get:t[s]})},o:(e,l)=>Object.prototype.hasOwnProperty.call(e,l)};const l=window.wp.blocks,t=window.wp.element,s=window.wp.components,r=window.wp.i18n,a=window.wp.blockEditor,o=JSON.parse('{"UU":"shutterpress-gallery/shutterpress-gallery-block"}'),n=window.wp.serverSideRender;var u=e.n(n);const i=window.wp.data,p=window.ReactJSXRuntime,d=()=>(0,p.jsx)(s.Spinner,{}),g=e=>{const l=e&&e.error?e.error:null;let t=(0,r.__)("Error rendering block","shutterpress-gallery");if(l)if("string"==typeof l)t=l;else if(l&&"string"==typeof l.message)t=l.message;else try{t=JSON.stringify(l)}catch(e){t=String(l)}return(0,p.jsx)("div",{className:"components-error",children:(0,p.jsx)("p",{children:t})})};(0,l.registerBlockType)(o.UU,{attributes:{galleryId:{type:"number",default:-1},useLightbox:{type:"boolean",default:!0},showDefaultButtons:{type:"boolean",default:!0},galleryLayout:{type:"string",default:"grid"},galleryGap:{type:"number",default:20},rowHeight:{type:"number",default:300},columns_desktop:{type:"number",default:3},columns_tablet:{type:"number",default:2},columns_mobile:{type:"number",default:1},hasLoadedDefaults:{type:"boolean",default:!1}},edit:function(e){const{attributes:l,setAttributes:n}=e,{galleryId:b,useLightbox:c,showDefaultButtons:h,galleryLayout:y,galleryGap:m,rowHeight:_,columns_desktop:f,columns_tablet:v,columns_mobile:w}=l,x=(0,a.useBlockProps)(),j=(0,i.useSelect)(e=>e("core").getEntityRecords("postType","shutterpress-gallery",{per_page:-1,orderby:"title",order:"asc",_fields:["id","title"]}),[]),C=null===j;(0,t.useEffect)(()=>{if(!l.hasLoadedDefaults){const e="undefined"!=typeof window&&window.shutterpressDefaults?window.shutterpressDefaults:{},t=(e,l)=>{const t=parseInt(e,10);return Number.isFinite(t)?t:l},s={};null==l.useLightbox&&(s.useLightbox=!!e.use_lightbox),null==l.galleryLayout&&(s.galleryLayout=e.layout||"grid"),null==l.galleryGap&&(s.galleryGap=t(e.gap,20)),null==l.rowHeight&&(s.rowHeight=t(e.row_height,300)),null==l.columns_desktop&&(s.columns_desktop=t(e.columns_desktop,3)),null==l.columns_tablet&&(s.columns_tablet=t(e.columns_tablet,2)),null==l.columns_mobile&&(s.columns_mobile=t(e.columns_mobile,1)),n({...s,hasLoadedDefaults:!0})}},[l.hasLoadedDefaults]);const k=(()=>{if(!C&&Array.isArray(j)&&j.length>0){const e=j.map(e=>({label:e.title?.rendered||(0,r.__)("Untitled Gallery","shutterpress-gallery"),value:String(e.id)}));return[{label:(0,r.__)("Use Post Gallery","shutterpress-gallery"),value:"-1"},...e]}return[]})(),L=(e,l)=>Number.isFinite(e)?e:l,S=(0,t.useMemo)(()=>{const e={galleryId:L(b,0),useLightbox:!!c,showDefaultButtons:!!h,galleryLayout:null!=y?y:void 0,galleryGap:L(m,20),rowHeight:"justified"===y?L(_,300):void 0,columns_desktop:"grid"===y||"masonry"===y?L(f,3):void 0,columns_tablet:"grid"===y||"masonry"===y?L(v,2):void 0,columns_mobile:"grid"===y||"masonry"===y?L(w,1):void 0};return Object.fromEntries(Object.entries(e).filter(([,e])=>null!=e))},[b,c,h,y,m,_,f,v,w]);return(0,p.jsxs)("div",{...x,children:[C&&(0,p.jsx)(s.Spinner,{}),Number.isFinite(b)&&-1===b&&!C&&(0,p.jsx)("div",{className:"sp-gallery-block-preview",children:(0,p.jsx)("div",{className:"components-placeholder",children:(0,p.jsx)("p",{children:(0,r.__)("ShutterPress Gallery. View the post to see images.","shutterpress-gallery")})})}),Number.isFinite(b)&&b>0&&!C&&(0,p.jsx)("div",{className:"sp-gallery-block-preview",children:(0,p.jsx)(u(),{block:o.UU,httpMethod:"GET",attributes:S,LoadingResponsePlaceholder:d,ErrorResponsePlaceholder:g})}),null,(0,p.jsx)(a.InspectorControls,{children:(0,p.jsxs)(s.PanelBody,{title:(0,r.__)("Gallery Settings","shutterpress-gallery"),initialOpen:!0,children:[(0,p.jsx)(s.ComboboxControl,{label:(0,r.__)("Select Gallery","shutterpress-gallery"),value:String(Number.isFinite(b)?b:""),options:k,onChange:e=>{const l=parseInt(e,10);n({galleryId:Number.isFinite(l)?l:0})},help:C?(0,r.__)("Loading galleries…","shutterpress-gallery"):(0,r.__)("Type to search by gallery name","shutterpress-gallery"),disabled:C||!1}),(0,p.jsx)(s.ToggleControl,{label:(0,r.__)("Use Lightbox","shutterpress-gallery"),checked:c,onChange:e=>n({useLightbox:!!e})}),(0,p.jsx)(s.ToggleControl,{label:(0,r.__)("Use Default Buttons","shutterpress-gallery"),checked:h,onChange:e=>n({showDefaultButtons:!!e})}),(0,p.jsxs)("p",{className:"components-base-control__help",children:[(0,r.sprintf)((0,r.__)('If you want to add custom buttons, set the button HTML anchor to "%s".',"shutterpress-gallery"),`sp-gallery-filter-liked-photos-${b}`)," ",(0,p.jsx)("a",{href:"https://shutterpress.io",target:"_blank",rel:"noopener noreferrer",children:(0,r.__)("See ShutterPress.io for more info.","shutterpress-gallery")})]}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Layout","shutterpress-gallery"),value:y,options:[{label:(0,r.__)("Grid","shutterpress-gallery"),value:"grid"},{label:(0,r.__)("Masonry","shutterpress-gallery"),value:"masonry"},{label:(0,r.__)("Justified","shutterpress-gallery"),value:"justified"}],onChange:e=>n({galleryLayout:e})}),(0,p.jsx)(s.RangeControl,{label:(0,r.__)("Image Gap","shutterpress-gallery"),value:m,onChange:e=>n({galleryGap:parseInt(e,10)}),min:0,max:100}),"justified"===y&&(0,p.jsx)(s.RangeControl,{label:(0,r.__)("Row Height","shutterpress-gallery"),value:_,onChange:e=>n({rowHeight:parseInt(e,10)}),min:0,max:1e3}),("grid"===y||"masonry"===y)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Desktop Columns","shutterpress-gallery"),value:f,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8},{label:"9",value:9},{label:"10",value:10}],onChange:e=>n({columns_desktop:parseInt(e,10)})}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Tablet Columns","shutterpress-gallery"),value:v,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8}],onChange:e=>n({columns_tablet:parseInt(e,10)})}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Mobile Columns","shutterpress-gallery"),value:w,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4}],onChange:e=>n({columns_mobile:parseInt(e,10)})})]})]})})]})},save:function(){return null}})})();
  • shutterpress-gallery/tags/1.7.6/shutterpress-gallery.php

    r3376238 r3378680  
    11<?php
    2 
    32/**
    43 * The plugin bootstrap file
     
    109 * @wordpress-plugin
    1110 * Plugin Name:       ShutterPress Gallery
    12  * Plugin URI:        shutterpress.io
     11 * Plugin URI:        https://shutterpress.io
    1312 * Description:       WordPress photo gallery plugin for photographers and creatives. Build fast, responsive image galleries with Masonry, Justified, and Grid layouts, lightbox support, and Infinite Scroll.
    14  * Version:           1.7.5
     13 * Version:           1.7.6
    1514 * Author:            ShutterPress
    1615 * Author URI:        https://shutterpress.io
     
    2827 * Current plugin version.
    2928 */
    30 define('SHUTTERPRESS_GALLERY_VERSION', '1.7.5');
     29define('SHUTTERPRESS_GALLERY_VERSION', '1.7.6');
    3130
    3231define('SP_GALLERY_DIR', plugin_dir_path(__FILE__));
  • shutterpress-gallery/tags/1.7.6/src/admin/Shutterpress_Gallery_Admin.php

    r3376238 r3378680  
    105105        }
    106106
    107         if (!is_admin() || !function_exists('get_current_screen')) {
     107        $should_load = true;
     108        if (function_exists('wp_should_load_block_editor_scripts_and_styles')) {
     109            $should_load = wp_should_load_block_editor_scripts_and_styles();
     110        }
     111        if (!$should_load && !defined('SHUTTERPRESS_TESTING')) {
    108112            return;
    109113        }
    110         $screen = get_current_screen();
    111         if (!$screen || !$screen->is_block_editor()) {
    112             return;
    113         }
    114114
    115115        wp_enqueue_style($this->plugin_name . '-public', SP_GALLERY_URL . 'includes/css/shutterpress-gallery-public.css', [], $this->version, 'all');
    116116
    117117        $vendor_base = SP_GALLERY_URL . 'includes/js/';
    118         wp_register_script('infinite-scroll', $vendor_base . 'infinite-scroll.pkgd.min.js', ['jquery'], '5.0.0', false);
     118       
    119119        wp_register_script('isotope', $vendor_base . 'isotope.pkgd.min.js', ['jquery'], '3.0.0', false);
    120120       
    121         wp_enqueue_script('shutterpress-gallery-editor', SP_GALLERY_URL . 'includes/js/shutterpress-gallery-editor.js', ['isotope', 'infinite-scroll', 'wp-i18n'], $this->version, false);
     121        wp_enqueue_script($this->plugin_name . '-editor', SP_GALLERY_URL . 'includes/js/shutterpress-gallery-editor.js', ['isotope', 'wp-i18n'], $this->version, false);
     122
     123        $defaults = Shutterpress_Gallery_Defaults::get_template_defaults();
    122124
    123125        $localize_data = [
    124             'rest_url' => esc_url_raw(rest_url()),
    125             'nonce' => wp_create_nonce('wp_rest'),
     126            'use_lightbox' => (bool) $defaults['use_lightbox'],
     127            'layout' => $defaults['layout'],
     128            'gap' => (int) $defaults['gap'],
     129            'row_height' => (int) $defaults['row_height'],
     130            'columns_desktop' => (int) $defaults['columns']['desktop'],
     131            'columns_tablet' => (int) $defaults['columns']['tablet'],
     132            'columns_mobile' => (int) $defaults['columns']['mobile'],
    126133        ];
    127134        if (get_option('sp_gallery_debug') === '1') {
     
    130137
    131138        $localize_data['is'] = false;
     139        $localize_data['lg'] = false;
    132140
    133141        Shutterpress_Gallery_Debug::log('Localising Data', [$localize_data]);
    134142       
    135         wp_localize_script('shutterpress-gallery-editor', 'shutterpressData', $localize_data);
     143        wp_localize_script('shutterpress-gallery-editor', 'shutterpressDefaults', $localize_data);
    136144
    137145        wp_set_script_translations('shutterpress-gallery-editor', 'shutterpress-gallery', SP_GALLERY_DIR . 'languages');
  • shutterpress-gallery/tags/1.7.6/src/admin/Shutterpress_Gallery_Elementor_Widget.php

    r3371857 r3378680  
    294294
    295295        if (!empty($filtered_content)) {
     296           
    296297            echo \Shutterpress\Gallery\Shutterpress_Gallery_Utils::sanitize_form_html($filtered_content);
    297298        } else {
  • shutterpress-gallery/tags/1.7.6/src/includes/Shutterpress_Gallery.php

    r3374472 r3378680  
    135135        $this->loader->sp_gallery_add_action('elementor/widgets/register', $plugin_admin, 'sp_gallery_register_elementor_widget', 10);
    136136        $this->loader->sp_gallery_add_action('elementor/elements/categories_registered', $plugin_admin, 'sp_gallery_add_elementor_category');
    137         $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_options_route');
    138137        $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_save_field_route');
    139138        $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_dismiss_notice_route');
  • shutterpress-gallery/tags/1.7.6/src/includes/Shutterpress_Gallery_REST.php

    r3371808 r3378680  
    2323{
    2424    /**
    25      * Returns the JSON schema definition for Shutterpress Gallery plugin options.
    26      *
    27      * This schema describes the structure and allowed types for the plugin's settings
    28      * when accessed via the REST API. It helps ensure validation and consistency when
    29      * reading or updating plugin options externally.
    30      *
    31      * @since 1.3.6
    32      *
    33      * @return array The JSON schema for plugin options.
    34      */
    35     public function options_schema()
    36     {
    37         return [
    38             '$schema' => 'http://json-schema.org/draft-04/schema#',
    39             'title' => 'Gallery Options',
    40             'type' => 'object',
    41             'properties' => [
    42                 'some_option' => [
    43                     'type' => 'string',
    44                     'description' => 'A sample option',
    45                 ],
    46             ],
    47         ];
    48     }
    49 
    50     /**
    51      * Registers a custom REST API route to retrieve plugin options.
    52      *
    53      * This method registers a new REST API route at `/wp/v2/options` that can be accessed by users with the `manage_options` capability (typically administrators). When the route is accessed, it calls the `sp_gallery_get_options_for_api()` method to retrieve the following plugin options:
    54      *
    55      * - `sp_gallery_use_lightbox`: Whether the lightbox feature is enabled.
    56      * - `sp_gallery_layout`: The selected layout for the gallery.
    57      * - `sp_gallery_column_gap`: The gap between columns in the gallery.
    58      * - `sp_gallery_columns_desktop`: The number of columns to display on desktop devices.
    59      * - `sp_gallery_columns_tablet`: The number of columns to display on tablet devices.
    60      * - `sp_gallery_columns_mobile`: The number of columns to display on mobile devices.
    61      *
    62      * The method returns the options as a JSON response.
    63      */
    64     public function register_options_route()
    65     {
    66         register_rest_route('shutterpress/v1', '/options', [
    67             'schema' => [$this, 'options_schema'],
    68             'methods' => 'GET',
    69             'callback' => [$this, 'get_options_for_api'],
    70             'permission_callback' => function () {
    71                 return current_user_can('manage_options');
    72             },
    73         ]);
    74     }
    75     /**
    7625     * Registers a custom REST API route to save a single metabox field.
    7726     *
     
    251200        do_action('sp_gallery_review_notice_dismissed', $user_id);
    252201        return rest_ensure_response(['message' => 'Review notice dismissed']);
    253     }
    254 
    255     /**
    256      * Retrieves the options for the Shutterpress Gallery plugin and returns them as a JSON response.
    257      *
    258      * This method is registered as a custom REST API route at `/wp/v2/options`. It retrieves the following options:
    259      *
    260      * - `sp_gallery_use_lightbox`: Whether the lightbox feature is enabled.
    261      * - `sp_gallery_layout`: The selected layout for the gallery.
    262      * - `sp_gallery_column_gap`: The gap between columns in the gallery.
    263      * - `sp_gallery_columns_desktop`: The number of columns to display on desktop devices.
    264      * - `sp_gallery_columns_tablet`: The number of columns to display on tablet devices.
    265      * - `sp_gallery_columns_mobile`: The number of columns to display on mobile devices.
    266      *
    267      * The method returns the options as a JSON response, and is only accessible to users with the `manage_options` capability (typically administrators).
    268      *
    269      * @return WP_REST_Response The options as a JSON response.
    270      */
    271     public function get_options_for_api()
    272     {
    273        
    274         $options = [
    275             'sp_gallery_use_lightbox' => filter_var(get_option('sp_gallery_use_lightbox'), FILTER_VALIDATE_BOOLEAN),
    276             'sp_gallery_layout' => sanitize_text_field(get_option('sp_gallery_layout')),
    277             'sp_gallery_column_gap' => intval(get_option('sp_gallery_column_gap')),
    278             'sp_gallery_columns_desktop' => intval(get_option('sp_gallery_columns_desktop')),
    279             'sp_gallery_columns_tablet' => intval(get_option('sp_gallery_columns_tablet')),
    280             'sp_gallery_columns_mobile' => intval(get_option('sp_gallery_columns_mobile')),
    281         ];
    282         Shutterpress_Gallery_Debug::log('REST API options output', $options);
    283         return rest_ensure_response($options);
    284202    }
    285203
  • shutterpress-gallery/tags/1.7.6/src/public/Shutterpress_Gallery_Public.php

    r3376238 r3378680  
    6666        wp_enqueue_script('lightgallery', SP_GALLERY_URL . 'includes/js/lightgallery.bundle.js', ['jquery'], '2.7.1', true);
    6767        wp_enqueue_script('imagesloaded');
    68         wp_enqueue_script('infinite-scroll', SP_GALLERY_URL . 'includes/js/infinite-scroll.pkgd.min.js', ['jquery']);
     68        wp_enqueue_script('infinite-scroll', SP_GALLERY_URL . 'includes/js/infinite-scroll.pkgd.min.js', ['jquery'], null, true);
    6969        wp_enqueue_script('isotope', SP_GALLERY_URL . 'includes/js/isotope.pkgd.min.js', ['jquery'], null, true);
    7070        wp_enqueue_script('shutterpress-gallery-isotope', SP_GALLERY_URL . 'src/public/js/shutterpress-gallery-isotope.js', ['isotope', 'jquery'], null, true);
     
    187187        Shutterpress_Gallery_Debug::log('Rendering gallery shortcode', $attributes);
    188188       
    189         $use_lightbox = isset($attributes['use_lightbox'])
    190             ? $this->sp_gallery_is_truthy($attributes['use_lightbox'])
    191             : filter_var(get_option('sp_gallery_use_lightbox', true), FILTER_VALIDATE_BOOLEAN);
    192 
    193         $show_buttons = isset($attributes['show_buttons'])
    194             ? $this->sp_gallery_is_truthy($attributes['show_buttons'])
    195             : filter_var(get_option('sp_gallery_show_buttons', true), FILTER_VALIDATE_BOOLEAN);
     189        $use_lightbox = isset($attributes['use_lightbox']) ? $this->sp_gallery_is_truthy($attributes['use_lightbox']) : null;
     190
     191        $show_buttons = isset($attributes['show_buttons']) ? $this->sp_gallery_is_truthy($attributes['show_buttons']) : null;
    196192
    197193        $gallery_attributes = [
    198194            'gallery_id' => isset($attributes['id']) ? intval($attributes['id']) : null,
    199195            'use_lightbox' => $use_lightbox,
    200             'layout' => isset($attributes['layout']) ? $attributes['layout'] : sanitize_text_field(get_option('sp_gallery_layout', 'masonry')),
    201             'gap' => isset($attributes['gap']) ? intval($attributes['gap']) : intval(get_option('sp_gallery_column_gap', 20)),
    202             'row_height' => isset($attributes['row_height']) ? intval($attributes['row_height']) : intval(get_option('sp_gallery_justified_row_height', 300)),
     196            'layout' => isset($attributes['layout']) ? $attributes['layout'] : null,
     197            'gap' => isset($attributes['gap']) ? intval($attributes['gap']) : null,
     198            'row_height' => isset($attributes['row_height']) ? intval($attributes['row_height']) : null,
    203199            'show_buttons' => $show_buttons,
    204200            'gallery_type' => 'shortcode',
    205201        ];
    206202
    207         $gallery_id = $gallery_attributes['gallery_id'] ?? 'default';
     203        if (empty($gallery_attributes['gallery_id'])) {
     204            $current_id = get_the_ID();
     205            if ($current_id && is_numeric($current_id)) {
     206                $gallery_attributes['gallery_id'] = (int) $current_id;
     207            }
     208        }
     209
     210        $gallery_id = !empty($gallery_attributes['gallery_id']) ? (int) $gallery_attributes['gallery_id'] : 'default';
    208211        Shutterpress_Gallery_Debug::log('Resolved gallery ID', ['gallery_id' => $gallery_id]);
    209212
  • shutterpress-gallery/tags/1.7.6/src/shutterpress-gallery-block/block.json

    r3376238 r3378680  
    1616    "useLightbox": { "type": "boolean", "default": true },
    1717    "showDefaultButtons": { "type": "boolean", "default": true },
    18     "galleryLayout": { "type": "string", "default": "masonry" },
     18    "galleryLayout": { "type": "string", "default": "grid" },
    1919    "galleryGap": { "type": "number", "default": 20 },
    2020    "rowHeight": { "type": "number", "default": 300 },
  • shutterpress-gallery/tags/1.7.6/src/shutterpress-gallery-block/shutterpress-gallery-block-render.php

    r3371808 r3378680  
    6767                if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    6868                    $gallery_attributes['infinite_scroll'] = '0';
     69                    $gallery_attributes['use_lightbox'] = '0';
    6970                }
    7071
    7172                if (method_exists($renderer, 'set_attributes')) {
    7273                    $renderer->set_attributes($gallery_attributes);
    73                 }
    74 
    75                 if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    7674                }
    7775
  • shutterpress-gallery/tags/1.7.6/src/shutterpress-gallery-block/shutterpress-gallery-block.js

    r3376238 r3378680  
    11import { registerBlockType } from '@wordpress/blocks';
    2 import { useState, useEffect } from '@wordpress/element';
     2import { useState, useEffect, useMemo } from '@wordpress/element';
    33import { SelectControl, ToggleControl, RangeControl, TextControl, PanelBody, Spinner, ComboboxControl } from '@wordpress/components';
    44import { __, sprintf } from '@wordpress/i18n';
    55import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
    6 import apiFetch from '@wordpress/api-fetch'; // Use WordPress built-in fetch
    76import metadata from './block.json';
    87import ServerSideRender from '@wordpress/server-side-render';
     8import { useSelect } from '@wordpress/data';
     9
     10// Loading and error placeholders for SSR
     11const LoadingPlaceholder = () => <Spinner />;
     12const ErrorPlaceholder = (props) => {
     13  const err = props && props.error ? props.error : null;
     14  let msg = __('Error rendering block', 'shutterpress-gallery');
     15  if (err) {
     16    if (typeof err === 'string') msg = err;
     17    else if (err && typeof err.message === 'string') msg = err.message;
     18    else {
     19      try {
     20        msg = JSON.stringify(err);
     21      } catch (e) {
     22        msg = String(err);
     23      }
     24    }
     25  }
     26  return (
     27    <div className="components-error">
     28      <p>{msg}</p>
     29    </div>
     30  );
     31};
    932
    1033// Register the block
     
    2548    galleryLayout: {
    2649      type: 'string',
    27       default: 'masonry',
     50      default: 'grid',
    2851    },
    2952    galleryGap: {
     
    5780    const { galleryId, useLightbox, showDefaultButtons, galleryLayout, galleryGap, rowHeight, columns_desktop, columns_tablet, columns_mobile } = attributes;
    5881
    59     const [galleries, setGalleries] = useState([]);
    60     const [loading, setLoading] = useState(true);
    61     const [error, setError] = useState(null);
     82    // Remove local state for galleries, loading, error.
    6283
    6384    const blockProps = useBlockProps();
    6485
     86    // Fetch galleries using useSelect at the top level (not in useEffect).
     87    const galleries = useSelect(
     88      (select) =>
     89        select('core').getEntityRecords('postType', 'shutterpress-gallery', {
     90          per_page: -1,
     91          orderby: 'title',
     92          order: 'asc',
     93          _fields: ['id', 'title'],
     94        }),
     95      [],
     96    );
     97    const loading = galleries === null;
     98    const error = null;
     99
    65100    useEffect(() => {
    66       // always fetch galleries list
    67       setLoading(true);
    68       setError(null);
    69 
    70       const perPage = 100;
    71       let all = [];
    72 
    73       const fetchPage = async (page = 1) => {
    74         // Use parse:false so we can read headers for total pages
    75         const res = await apiFetch({
    76           path: `wp/v2/shutterpress-gallery?per_page=${perPage}&page=${page}`,
    77           parse: false,
    78         });
    79         const json = await res.json();
    80         all = all.concat(Array.isArray(json) ? json : []);
    81         const totalPages = parseInt(res.headers.get('X-WP-TotalPages') || '1', 10);
    82         if (page < totalPages) {
    83           return fetchPage(page + 1);
    84         }
    85       };
    86 
    87       fetchPage(1)
    88         .then(() => {
    89           setGalleries(all);
    90           setLoading(false);
    91         })
    92         .catch((err) => {
    93           setError(err && err.message ? err.message : String(err));
    94           setGalleries([]);
    95           setLoading(false);
    96         });
    97 
    98       // only pull REST defaults once, and never overwrite saved values
    99101      if (!attributes.hasLoadedDefaults) {
    100         apiFetch({ path: 'shutterpress/v1/options' })
    101           .then((options) => {
    102             const toInt = (v, fb) => {
    103               const n = parseInt(v, 10);
    104               return Number.isFinite(n) ? n : fb;
    105             };
    106 
    107             const next = {};
    108             if (attributes.useLightbox === undefined || attributes.useLightbox === null) next.useLightbox = !!options.sp_gallery_use_lightbox;
    109             if (attributes.galleryLayout === undefined || attributes.galleryLayout === null) next.galleryLayout = options.sp_gallery_layout || 'masonry';
    110             if (attributes.galleryGap === undefined || attributes.galleryGap === null) next.galleryGap = toInt(options.sp_gallery_column_gap, 20);
    111             if (attributes.rowHeight === undefined || attributes.rowHeight === null) next.rowHeight = toInt(options.sp_gallery_justified_row_height, 300);
    112             if (attributes.columns_desktop === undefined || attributes.columns_desktop === null) next.columns_desktop = toInt(options.sp_gallery_columns_desktop, 3);
    113             if (attributes.columns_tablet === undefined || attributes.columns_tablet === null) next.columns_tablet = toInt(options.sp_gallery_columns_tablet, 2);
    114             if (attributes.columns_mobile === undefined || attributes.columns_mobile === null) next.columns_mobile = toInt(options.sp_gallery_columns_mobile, 1);
    115 
    116             setAttributes({ ...next, hasLoadedDefaults: true });
    117           })
    118           .catch((error) => {
    119             console.error('Error fetching options:', error);
    120             // still mark as loaded to avoid future overwrites
    121             setAttributes({ hasLoadedDefaults: true });
    122           });
     102        const options = typeof window !== 'undefined' && window.shutterpressDefaults ? window.shutterpressDefaults : {};
     103
     104        const toInt = (v, fb) => {
     105          const n = parseInt(v, 10);
     106          return Number.isFinite(n) ? n : fb;
     107        };
     108
     109        const next = {};
     110        if (attributes.useLightbox == null) next.useLightbox = !!options.use_lightbox;
     111        if (attributes.galleryLayout == null) next.galleryLayout = options.layout || 'grid';
     112        if (attributes.galleryGap == null) next.galleryGap = toInt(options.gap, 20);
     113        if (attributes.rowHeight == null) next.rowHeight = toInt(options.row_height, 300);
     114        if (attributes.columns_desktop == null) next.columns_desktop = toInt(options.columns_desktop, 3);
     115        if (attributes.columns_tablet == null) next.columns_tablet = toInt(options.columns_tablet, 2);
     116        if (attributes.columns_mobile == null) next.columns_mobile = toInt(options.columns_mobile, 1);
     117
     118        setAttributes({ ...next, hasLoadedDefaults: true });
    123119      }
    124120    }, [attributes.hasLoadedDefaults]);
     
    137133    // Sanitize attributes for preview and exclude internal-only keys
    138134    const sanitizeNumber = (val, fallback) => (Number.isFinite(val) ? val : fallback);
    139     const renderAttributes = {
    140       galleryId: sanitizeNumber(galleryId, 0),
    141       useLightbox: !!useLightbox,
    142       showDefaultButtons: !!showDefaultButtons,
    143       galleryLayout: galleryLayout || 'masonry',
    144       galleryGap: sanitizeNumber(galleryGap, 20),
    145       rowHeight: galleryLayout === 'justified' ? sanitizeNumber(rowHeight, 300) : undefined,
    146       columns_desktop: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_desktop, 3) : undefined,
    147       columns_tablet: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_tablet, 2) : undefined,
    148       columns_mobile: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_mobile, 1) : undefined,
    149     };
    150     const filteredRenderAttributes = Object.fromEntries(Object.entries(renderAttributes).filter(([, v]) => v !== undefined && v !== null));
    151     const ssrAttributes = filteredRenderAttributes;
     135    const ssrAttributes = useMemo(() => {
     136      const base = {
     137        galleryId: sanitizeNumber(galleryId, 0),
     138        useLightbox: !!useLightbox,
     139        showDefaultButtons: !!showDefaultButtons,
     140        galleryLayout: galleryLayout ?? undefined,
     141        galleryGap: sanitizeNumber(galleryGap, 20),
     142        rowHeight: galleryLayout === 'justified' ? sanitizeNumber(rowHeight, 300) : undefined,
     143        columns_desktop: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_desktop, 3) : undefined,
     144        columns_tablet: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_tablet, 2) : undefined,
     145        columns_mobile: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_mobile, 1) : undefined,
     146      };
     147      return Object.fromEntries(Object.entries(base).filter(([, v]) => v !== undefined && v !== null));
     148    }, [galleryId, useLightbox, showDefaultButtons, galleryLayout, galleryGap, rowHeight, columns_desktop, columns_tablet, columns_mobile]);
    152149
    153150    return (
     
    165162        {Number.isFinite(galleryId) && galleryId > 0 && !loading && !error && (
    166163          <div className="sp-gallery-block-preview">
    167             {console && typeof console.log === 'function' ? console.log('[ShutterPress] SSR attributes', filteredRenderAttributes) : null}
    168             <ServerSideRender
    169               block={metadata.name}
    170               httpMethod="GET"
    171               attributes={ssrAttributes}
    172               LoadingResponsePlaceholder={() => <Spinner />}
    173               ErrorResponsePlaceholder={(props) => {
    174                 const err = props && props.error ? props.error : null;
    175                 if (console && typeof console.error === 'function') {
    176                   console.error('[ShutterPress] SSR error props', props);
    177                 }
    178                 let msg = __('Error rendering block', 'shutterpress-gallery');
    179                 if (err) {
    180                   if (typeof err === 'string') {
    181                     msg = err;
    182                   } else if (err && typeof err.message === 'string') {
    183                     msg = err.message;
    184                   } else {
    185                     try {
    186                       msg = JSON.stringify(err);
    187                     } catch (e) {
    188                       msg = String(err);
    189                     }
    190                   }
    191                 }
    192                 if (console && typeof console.error === 'function') {
    193                   console.error('[ShutterPress] Block render error', err);
    194                 }
    195                 return (
    196                   <div className="components-error">
    197                     <p>{msg}</p>
    198                   </div>
    199                 );
    200               }}
    201             />
     164            <ServerSideRender block={metadata.name} httpMethod="GET" attributes={ssrAttributes} LoadingResponsePlaceholder={LoadingPlaceholder} ErrorResponsePlaceholder={ErrorPlaceholder} />
    202165          </div>
    203166        )}
     
    239202              value={galleryLayout}
    240203              options={[
     204                { label: __('Grid', 'shutterpress-gallery'), value: 'grid' },
    241205                { label: __('Masonry', 'shutterpress-gallery'), value: 'masonry' },
    242                 { label: __('Grid', 'shutterpress-gallery'), value: 'grid' },
    243206                { label: __('Justified', 'shutterpress-gallery'), value: 'justified' },
    244207              ]}
  • shutterpress-gallery/tags/1.7.6/vendor/composer/installed.php

    r3376238 r3378680  
    44        'pretty_version' => 'dev-master',
    55        'version' => 'dev-master',
    6         'reference' => '1037916b588c758f6615994b2c77f6588d3b29b5',
     6        'reference' => 'ee154d9281e430a177064ec382dda47bc35fbef9',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    3535            'pretty_version' => 'dev-master',
    3636            'version' => 'dev-master',
    37             'reference' => '1037916b588c758f6615994b2c77f6588d3b29b5',
     37            'reference' => 'ee154d9281e430a177064ec382dda47bc35fbef9',
    3838            'type' => 'wordpress-plugin',
    3939            'install_path' => __DIR__ . '/../../',
  • shutterpress-gallery/trunk/README.txt

    r3376238 r3378680  
    66Tested up to: 6.8
    77Requires PHP: 8.0
    8 Stable tag: 1.7.5
     8Stable tag: 1.7.6
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    119119
    120120== Changelog ==
     121
     122= 1.7.6 =
     123
     124* Update - Shortcodes show current post gallery when no id is set
     125* Update - Refactor Gallery Block Defaults
     126* Fix - Shortcodes take defaults from gallery template
    121127
    122128= 1.7.5 =
  • shutterpress-gallery/trunk/includes/blocks/shutterpress-gallery-block/block.json

    r3376238 r3378680  
    2727    "galleryLayout": {
    2828      "type": "string",
    29       "default": "masonry"
     29      "default": "grid"
    3030    },
    3131    "galleryGap": {
  • shutterpress-gallery/trunk/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block-render.php

    r3371808 r3378680  
    6767                if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    6868                    $gallery_attributes['infinite_scroll'] = '0';
     69                    $gallery_attributes['use_lightbox'] = '0';
    6970                }
    7071
    7172                if (method_exists($renderer, 'set_attributes')) {
    7273                    $renderer->set_attributes($gallery_attributes);
    73                 }
    74 
    75                 if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    7674                }
    7775
  • shutterpress-gallery/trunk/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block.asset.php

    r3376238 r3378680  
    1 <?php return array('dependencies' => array('react-jsx-runtime', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '0961de81d9cf02dac39c');
     1<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'aead3cea6f4ea9eea0c9');
  • shutterpress-gallery/trunk/includes/blocks/shutterpress-gallery-block/shutterpress-gallery-block.js

    r3376238 r3378680  
    1 (()=>{"use strict";var e={n:l=>{var t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var r in t)e.o(t,r)&&!e.o(l,r)&&Object.defineProperty(l,r,{enumerable:!0,get:t[r]})},o:(e,l)=>Object.prototype.hasOwnProperty.call(e,l)};const l=window.wp.blocks,t=window.wp.element,r=window.wp.components,s=window.wp.i18n,o=window.wp.blockEditor,a=window.wp.apiFetch;var n=e.n(a);const u=JSON.parse('{"UU":"shutterpress-gallery/shutterpress-gallery-block"}'),i=window.wp.serverSideRender;var p=e.n(i);const g=window.ReactJSXRuntime;(0,l.registerBlockType)(u.UU,{attributes:{galleryId:{type:"number",default:-1},useLightbox:{type:"boolean",default:!0},showDefaultButtons:{type:"boolean",default:!0},galleryLayout:{type:"string",default:"masonry"},galleryGap:{type:"number",default:20},rowHeight:{type:"number",default:300},columns_desktop:{type:"number",default:3},columns_tablet:{type:"number",default:2},columns_mobile:{type:"number",default:1},hasLoadedDefaults:{type:"boolean",default:!1}},edit:function(e){const{attributes:l,setAttributes:a}=e,{galleryId:i,useLightbox:c,showDefaultButtons:d,galleryLayout:h,galleryGap:y,rowHeight:b,columns_desktop:_,columns_tablet:m,columns_mobile:v}=l,[f,w]=(0,t.useState)([]),[x,j]=(0,t.useState)(!0),[S,L]=(0,t.useState)(null),k=(0,o.useBlockProps)();(0,t.useEffect)(()=>{j(!0),L(null);let e=[];const t=async(l=1)=>{const r=await n()({path:`wp/v2/shutterpress-gallery?per_page=100&page=${l}`,parse:!1}),s=await r.json();if(e=e.concat(Array.isArray(s)?s:[]),l<parseInt(r.headers.get("X-WP-TotalPages")||"1",10))return t(l+1)};t(1).then(()=>{w(e),j(!1)}).catch(e=>{L(e&&e.message?e.message:String(e)),w([]),j(!1)}),l.hasLoadedDefaults||n()({path:"shutterpress/v1/options"}).then(e=>{const t=(e,l)=>{const t=parseInt(e,10);return Number.isFinite(t)?t:l},r={};void 0!==l.useLightbox&&null!==l.useLightbox||(r.useLightbox=!!e.sp_gallery_use_lightbox),void 0!==l.galleryLayout&&null!==l.galleryLayout||(r.galleryLayout=e.sp_gallery_layout||"masonry"),void 0!==l.galleryGap&&null!==l.galleryGap||(r.galleryGap=t(e.sp_gallery_column_gap,20)),void 0!==l.rowHeight&&null!==l.rowHeight||(r.rowHeight=t(e.sp_gallery_justified_row_height,300)),void 0!==l.columns_desktop&&null!==l.columns_desktop||(r.columns_desktop=t(e.sp_gallery_columns_desktop,3)),void 0!==l.columns_tablet&&null!==l.columns_tablet||(r.columns_tablet=t(e.sp_gallery_columns_tablet,2)),void 0!==l.columns_mobile&&null!==l.columns_mobile||(r.columns_mobile=t(e.sp_gallery_columns_mobile,1)),a({...r,hasLoadedDefaults:!0})}).catch(e=>{console.error("Error fetching options:",e),a({hasLoadedDefaults:!0})})},[l.hasLoadedDefaults]);const C=(()=>{if(!x&&Array.isArray(f)&&f.length>0){const e=f.map(e=>({label:e.title?.rendered||(0,s.__)("Untitled Gallery","shutterpress-gallery"),value:String(e.id)}));return[{label:(0,s.__)("Use Post Gallery","shutterpress-gallery"),value:"-1"},...e]}return[]})(),N=(e,l)=>Number.isFinite(e)?e:l,G={galleryId:N(i,0),useLightbox:!!c,showDefaultButtons:!!d,galleryLayout:h||"masonry",galleryGap:N(y,20),rowHeight:"justified"===h?N(b,300):void 0,columns_desktop:"grid"===h||"masonry"===h?N(_,3):void 0,columns_tablet:"grid"===h||"masonry"===h?N(m,2):void 0,columns_mobile:"grid"===h||"masonry"===h?N(v,1):void 0},I=Object.fromEntries(Object.entries(G).filter(([,e])=>null!=e)),P=I;return(0,g.jsxs)("div",{...k,children:[x&&(0,g.jsx)(r.Spinner,{}),Number.isFinite(i)&&-1===i&&!x&&!S&&(0,g.jsx)("div",{className:"sp-gallery-block-preview",children:(0,g.jsx)("div",{className:"components-placeholder",children:(0,g.jsx)("p",{children:(0,s.__)("ShutterPress Gallery. View the post to see images.","shutterpress-gallery")})})}),Number.isFinite(i)&&i>0&&!x&&!S&&(0,g.jsxs)("div",{className:"sp-gallery-block-preview",children:[console&&"function"==typeof console.log?console.log("[ShutterPress] SSR attributes",I):null,(0,g.jsx)(p(),{block:u.UU,httpMethod:"GET",attributes:P,LoadingResponsePlaceholder:()=>(0,g.jsx)(r.Spinner,{}),ErrorResponsePlaceholder:e=>{const l=e&&e.error?e.error:null;console&&"function"==typeof console.error&&console.error("[ShutterPress] SSR error props",e);let t=(0,s.__)("Error rendering block","shutterpress-gallery");if(l)if("string"==typeof l)t=l;else if(l&&"string"==typeof l.message)t=l.message;else try{t=JSON.stringify(l)}catch(e){t=String(l)}return console&&"function"==typeof console.error&&console.error("[ShutterPress] Block render error",l),(0,g.jsx)("div",{className:"components-error",children:(0,g.jsx)("p",{children:t})})}})]}),S&&(0,g.jsx)("p",{style:{color:"red"},children:(0,s.sprintf)((0,s.__)("Error: %s","shutterpress-gallery"),S)}),(0,g.jsx)(o.InspectorControls,{children:(0,g.jsxs)(r.PanelBody,{title:(0,s.__)("Gallery Settings","shutterpress-gallery"),initialOpen:!0,children:[(0,g.jsx)(r.ComboboxControl,{label:(0,s.__)("Select Gallery","shutterpress-gallery"),value:String(Number.isFinite(i)?i:""),options:C,onChange:e=>{const l=parseInt(e,10);a({galleryId:Number.isFinite(l)?l:0})},help:x?(0,s.__)("Loading galleries…","shutterpress-gallery"):S?(0,s.__)("Error loading galleries","shutterpress-gallery"):(0,s.__)("Type to search by gallery name","shutterpress-gallery"),disabled:x||!!S}),(0,g.jsx)(r.ToggleControl,{label:(0,s.__)("Use Lightbox","shutterpress-gallery"),checked:c,onChange:e=>a({useLightbox:!!e})}),(0,g.jsx)(r.ToggleControl,{label:(0,s.__)("Use Default Buttons","shutterpress-gallery"),checked:d,onChange:e=>a({showDefaultButtons:!!e})}),(0,g.jsxs)("p",{className:"components-base-control__help",children:[(0,s.sprintf)((0,s.__)('If you want to add custom buttons, set the button HTML anchor to "%s".',"shutterpress-gallery"),`sp-gallery-filter-liked-photos-${i}`)," ",(0,g.jsx)("a",{href:"https://shutterpress.io",target:"_blank",rel:"noopener noreferrer",children:(0,s.__)("See ShutterPress.io for more info.","shutterpress-gallery")})]}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Layout","shutterpress-gallery"),value:h,options:[{label:(0,s.__)("Masonry","shutterpress-gallery"),value:"masonry"},{label:(0,s.__)("Grid","shutterpress-gallery"),value:"grid"},{label:(0,s.__)("Justified","shutterpress-gallery"),value:"justified"}],onChange:e=>a({galleryLayout:e})}),(0,g.jsx)(r.RangeControl,{label:(0,s.__)("Image Gap","shutterpress-gallery"),value:y,onChange:e=>a({galleryGap:parseInt(e,10)}),min:0,max:100}),"justified"===h&&(0,g.jsx)(r.RangeControl,{label:(0,s.__)("Row Height","shutterpress-gallery"),value:b,onChange:e=>a({rowHeight:parseInt(e,10)}),min:0,max:1e3}),("grid"===h||"masonry"===h)&&(0,g.jsxs)(g.Fragment,{children:[(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Desktop Columns","shutterpress-gallery"),value:_,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8},{label:"9",value:9},{label:"10",value:10}],onChange:e=>a({columns_desktop:parseInt(e,10)})}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Tablet Columns","shutterpress-gallery"),value:m,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8}],onChange:e=>a({columns_tablet:parseInt(e,10)})}),(0,g.jsx)(r.SelectControl,{label:(0,s.__)("Number of Mobile Columns","shutterpress-gallery"),value:v,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4}],onChange:e=>a({columns_mobile:parseInt(e,10)})})]})]})})]})},save:function(){return null}})})();
     1(()=>{"use strict";var e={n:l=>{var t=l&&l.__esModule?()=>l.default:()=>l;return e.d(t,{a:t}),t},d:(l,t)=>{for(var s in t)e.o(t,s)&&!e.o(l,s)&&Object.defineProperty(l,s,{enumerable:!0,get:t[s]})},o:(e,l)=>Object.prototype.hasOwnProperty.call(e,l)};const l=window.wp.blocks,t=window.wp.element,s=window.wp.components,r=window.wp.i18n,a=window.wp.blockEditor,o=JSON.parse('{"UU":"shutterpress-gallery/shutterpress-gallery-block"}'),n=window.wp.serverSideRender;var u=e.n(n);const i=window.wp.data,p=window.ReactJSXRuntime,d=()=>(0,p.jsx)(s.Spinner,{}),g=e=>{const l=e&&e.error?e.error:null;let t=(0,r.__)("Error rendering block","shutterpress-gallery");if(l)if("string"==typeof l)t=l;else if(l&&"string"==typeof l.message)t=l.message;else try{t=JSON.stringify(l)}catch(e){t=String(l)}return(0,p.jsx)("div",{className:"components-error",children:(0,p.jsx)("p",{children:t})})};(0,l.registerBlockType)(o.UU,{attributes:{galleryId:{type:"number",default:-1},useLightbox:{type:"boolean",default:!0},showDefaultButtons:{type:"boolean",default:!0},galleryLayout:{type:"string",default:"grid"},galleryGap:{type:"number",default:20},rowHeight:{type:"number",default:300},columns_desktop:{type:"number",default:3},columns_tablet:{type:"number",default:2},columns_mobile:{type:"number",default:1},hasLoadedDefaults:{type:"boolean",default:!1}},edit:function(e){const{attributes:l,setAttributes:n}=e,{galleryId:b,useLightbox:c,showDefaultButtons:h,galleryLayout:y,galleryGap:m,rowHeight:_,columns_desktop:f,columns_tablet:v,columns_mobile:w}=l,x=(0,a.useBlockProps)(),j=(0,i.useSelect)(e=>e("core").getEntityRecords("postType","shutterpress-gallery",{per_page:-1,orderby:"title",order:"asc",_fields:["id","title"]}),[]),C=null===j;(0,t.useEffect)(()=>{if(!l.hasLoadedDefaults){const e="undefined"!=typeof window&&window.shutterpressDefaults?window.shutterpressDefaults:{},t=(e,l)=>{const t=parseInt(e,10);return Number.isFinite(t)?t:l},s={};null==l.useLightbox&&(s.useLightbox=!!e.use_lightbox),null==l.galleryLayout&&(s.galleryLayout=e.layout||"grid"),null==l.galleryGap&&(s.galleryGap=t(e.gap,20)),null==l.rowHeight&&(s.rowHeight=t(e.row_height,300)),null==l.columns_desktop&&(s.columns_desktop=t(e.columns_desktop,3)),null==l.columns_tablet&&(s.columns_tablet=t(e.columns_tablet,2)),null==l.columns_mobile&&(s.columns_mobile=t(e.columns_mobile,1)),n({...s,hasLoadedDefaults:!0})}},[l.hasLoadedDefaults]);const k=(()=>{if(!C&&Array.isArray(j)&&j.length>0){const e=j.map(e=>({label:e.title?.rendered||(0,r.__)("Untitled Gallery","shutterpress-gallery"),value:String(e.id)}));return[{label:(0,r.__)("Use Post Gallery","shutterpress-gallery"),value:"-1"},...e]}return[]})(),L=(e,l)=>Number.isFinite(e)?e:l,S=(0,t.useMemo)(()=>{const e={galleryId:L(b,0),useLightbox:!!c,showDefaultButtons:!!h,galleryLayout:null!=y?y:void 0,galleryGap:L(m,20),rowHeight:"justified"===y?L(_,300):void 0,columns_desktop:"grid"===y||"masonry"===y?L(f,3):void 0,columns_tablet:"grid"===y||"masonry"===y?L(v,2):void 0,columns_mobile:"grid"===y||"masonry"===y?L(w,1):void 0};return Object.fromEntries(Object.entries(e).filter(([,e])=>null!=e))},[b,c,h,y,m,_,f,v,w]);return(0,p.jsxs)("div",{...x,children:[C&&(0,p.jsx)(s.Spinner,{}),Number.isFinite(b)&&-1===b&&!C&&(0,p.jsx)("div",{className:"sp-gallery-block-preview",children:(0,p.jsx)("div",{className:"components-placeholder",children:(0,p.jsx)("p",{children:(0,r.__)("ShutterPress Gallery. View the post to see images.","shutterpress-gallery")})})}),Number.isFinite(b)&&b>0&&!C&&(0,p.jsx)("div",{className:"sp-gallery-block-preview",children:(0,p.jsx)(u(),{block:o.UU,httpMethod:"GET",attributes:S,LoadingResponsePlaceholder:d,ErrorResponsePlaceholder:g})}),null,(0,p.jsx)(a.InspectorControls,{children:(0,p.jsxs)(s.PanelBody,{title:(0,r.__)("Gallery Settings","shutterpress-gallery"),initialOpen:!0,children:[(0,p.jsx)(s.ComboboxControl,{label:(0,r.__)("Select Gallery","shutterpress-gallery"),value:String(Number.isFinite(b)?b:""),options:k,onChange:e=>{const l=parseInt(e,10);n({galleryId:Number.isFinite(l)?l:0})},help:C?(0,r.__)("Loading galleries…","shutterpress-gallery"):(0,r.__)("Type to search by gallery name","shutterpress-gallery"),disabled:C||!1}),(0,p.jsx)(s.ToggleControl,{label:(0,r.__)("Use Lightbox","shutterpress-gallery"),checked:c,onChange:e=>n({useLightbox:!!e})}),(0,p.jsx)(s.ToggleControl,{label:(0,r.__)("Use Default Buttons","shutterpress-gallery"),checked:h,onChange:e=>n({showDefaultButtons:!!e})}),(0,p.jsxs)("p",{className:"components-base-control__help",children:[(0,r.sprintf)((0,r.__)('If you want to add custom buttons, set the button HTML anchor to "%s".',"shutterpress-gallery"),`sp-gallery-filter-liked-photos-${b}`)," ",(0,p.jsx)("a",{href:"https://shutterpress.io",target:"_blank",rel:"noopener noreferrer",children:(0,r.__)("See ShutterPress.io for more info.","shutterpress-gallery")})]}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Layout","shutterpress-gallery"),value:y,options:[{label:(0,r.__)("Grid","shutterpress-gallery"),value:"grid"},{label:(0,r.__)("Masonry","shutterpress-gallery"),value:"masonry"},{label:(0,r.__)("Justified","shutterpress-gallery"),value:"justified"}],onChange:e=>n({galleryLayout:e})}),(0,p.jsx)(s.RangeControl,{label:(0,r.__)("Image Gap","shutterpress-gallery"),value:m,onChange:e=>n({galleryGap:parseInt(e,10)}),min:0,max:100}),"justified"===y&&(0,p.jsx)(s.RangeControl,{label:(0,r.__)("Row Height","shutterpress-gallery"),value:_,onChange:e=>n({rowHeight:parseInt(e,10)}),min:0,max:1e3}),("grid"===y||"masonry"===y)&&(0,p.jsxs)(p.Fragment,{children:[(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Desktop Columns","shutterpress-gallery"),value:f,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8},{label:"9",value:9},{label:"10",value:10}],onChange:e=>n({columns_desktop:parseInt(e,10)})}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Tablet Columns","shutterpress-gallery"),value:v,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4},{label:"5",value:5},{label:"6",value:6},{label:"7",value:7},{label:"8",value:8}],onChange:e=>n({columns_tablet:parseInt(e,10)})}),(0,p.jsx)(s.SelectControl,{label:(0,r.__)("Number of Mobile Columns","shutterpress-gallery"),value:w,options:[{label:"1",value:1},{label:"2",value:2},{label:"3",value:3},{label:"4",value:4}],onChange:e=>n({columns_mobile:parseInt(e,10)})})]})]})})]})},save:function(){return null}})})();
  • shutterpress-gallery/trunk/shutterpress-gallery.php

    r3376238 r3378680  
    11<?php
    2 
    32/**
    43 * The plugin bootstrap file
     
    109 * @wordpress-plugin
    1110 * Plugin Name:       ShutterPress Gallery
    12  * Plugin URI:        shutterpress.io
     11 * Plugin URI:        https://shutterpress.io
    1312 * Description:       WordPress photo gallery plugin for photographers and creatives. Build fast, responsive image galleries with Masonry, Justified, and Grid layouts, lightbox support, and Infinite Scroll.
    14  * Version:           1.7.5
     13 * Version:           1.7.6
    1514 * Author:            ShutterPress
    1615 * Author URI:        https://shutterpress.io
     
    2827 * Current plugin version.
    2928 */
    30 define('SHUTTERPRESS_GALLERY_VERSION', '1.7.5');
     29define('SHUTTERPRESS_GALLERY_VERSION', '1.7.6');
    3130
    3231define('SP_GALLERY_DIR', plugin_dir_path(__FILE__));
  • shutterpress-gallery/trunk/src/admin/Shutterpress_Gallery_Admin.php

    r3376238 r3378680  
    105105        }
    106106
    107         if (!is_admin() || !function_exists('get_current_screen')) {
     107        $should_load = true;
     108        if (function_exists('wp_should_load_block_editor_scripts_and_styles')) {
     109            $should_load = wp_should_load_block_editor_scripts_and_styles();
     110        }
     111        if (!$should_load && !defined('SHUTTERPRESS_TESTING')) {
    108112            return;
    109113        }
    110         $screen = get_current_screen();
    111         if (!$screen || !$screen->is_block_editor()) {
    112             return;
    113         }
    114114
    115115        wp_enqueue_style($this->plugin_name . '-public', SP_GALLERY_URL . 'includes/css/shutterpress-gallery-public.css', [], $this->version, 'all');
    116116
    117117        $vendor_base = SP_GALLERY_URL . 'includes/js/';
    118         wp_register_script('infinite-scroll', $vendor_base . 'infinite-scroll.pkgd.min.js', ['jquery'], '5.0.0', false);
     118       
    119119        wp_register_script('isotope', $vendor_base . 'isotope.pkgd.min.js', ['jquery'], '3.0.0', false);
    120120       
    121         wp_enqueue_script('shutterpress-gallery-editor', SP_GALLERY_URL . 'includes/js/shutterpress-gallery-editor.js', ['isotope', 'infinite-scroll', 'wp-i18n'], $this->version, false);
     121        wp_enqueue_script($this->plugin_name . '-editor', SP_GALLERY_URL . 'includes/js/shutterpress-gallery-editor.js', ['isotope', 'wp-i18n'], $this->version, false);
     122
     123        $defaults = Shutterpress_Gallery_Defaults::get_template_defaults();
    122124
    123125        $localize_data = [
    124             'rest_url' => esc_url_raw(rest_url()),
    125             'nonce' => wp_create_nonce('wp_rest'),
     126            'use_lightbox' => (bool) $defaults['use_lightbox'],
     127            'layout' => $defaults['layout'],
     128            'gap' => (int) $defaults['gap'],
     129            'row_height' => (int) $defaults['row_height'],
     130            'columns_desktop' => (int) $defaults['columns']['desktop'],
     131            'columns_tablet' => (int) $defaults['columns']['tablet'],
     132            'columns_mobile' => (int) $defaults['columns']['mobile'],
    126133        ];
    127134        if (get_option('sp_gallery_debug') === '1') {
     
    130137
    131138        $localize_data['is'] = false;
     139        $localize_data['lg'] = false;
    132140
    133141        Shutterpress_Gallery_Debug::log('Localising Data', [$localize_data]);
    134142       
    135         wp_localize_script('shutterpress-gallery-editor', 'shutterpressData', $localize_data);
     143        wp_localize_script('shutterpress-gallery-editor', 'shutterpressDefaults', $localize_data);
    136144
    137145        wp_set_script_translations('shutterpress-gallery-editor', 'shutterpress-gallery', SP_GALLERY_DIR . 'languages');
  • shutterpress-gallery/trunk/src/admin/Shutterpress_Gallery_Elementor_Widget.php

    r3371857 r3378680  
    294294
    295295        if (!empty($filtered_content)) {
     296           
    296297            echo \Shutterpress\Gallery\Shutterpress_Gallery_Utils::sanitize_form_html($filtered_content);
    297298        } else {
  • shutterpress-gallery/trunk/src/includes/Shutterpress_Gallery.php

    r3374472 r3378680  
    135135        $this->loader->sp_gallery_add_action('elementor/widgets/register', $plugin_admin, 'sp_gallery_register_elementor_widget', 10);
    136136        $this->loader->sp_gallery_add_action('elementor/elements/categories_registered', $plugin_admin, 'sp_gallery_add_elementor_category');
    137         $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_options_route');
    138137        $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_save_field_route');
    139138        $this->loader->sp_gallery_add_action('rest_api_init', $plugin_admin_rest, 'register_dismiss_notice_route');
  • shutterpress-gallery/trunk/src/includes/Shutterpress_Gallery_REST.php

    r3371808 r3378680  
    2323{
    2424    /**
    25      * Returns the JSON schema definition for Shutterpress Gallery plugin options.
    26      *
    27      * This schema describes the structure and allowed types for the plugin's settings
    28      * when accessed via the REST API. It helps ensure validation and consistency when
    29      * reading or updating plugin options externally.
    30      *
    31      * @since 1.3.6
    32      *
    33      * @return array The JSON schema for plugin options.
    34      */
    35     public function options_schema()
    36     {
    37         return [
    38             '$schema' => 'http://json-schema.org/draft-04/schema#',
    39             'title' => 'Gallery Options',
    40             'type' => 'object',
    41             'properties' => [
    42                 'some_option' => [
    43                     'type' => 'string',
    44                     'description' => 'A sample option',
    45                 ],
    46             ],
    47         ];
    48     }
    49 
    50     /**
    51      * Registers a custom REST API route to retrieve plugin options.
    52      *
    53      * This method registers a new REST API route at `/wp/v2/options` that can be accessed by users with the `manage_options` capability (typically administrators). When the route is accessed, it calls the `sp_gallery_get_options_for_api()` method to retrieve the following plugin options:
    54      *
    55      * - `sp_gallery_use_lightbox`: Whether the lightbox feature is enabled.
    56      * - `sp_gallery_layout`: The selected layout for the gallery.
    57      * - `sp_gallery_column_gap`: The gap between columns in the gallery.
    58      * - `sp_gallery_columns_desktop`: The number of columns to display on desktop devices.
    59      * - `sp_gallery_columns_tablet`: The number of columns to display on tablet devices.
    60      * - `sp_gallery_columns_mobile`: The number of columns to display on mobile devices.
    61      *
    62      * The method returns the options as a JSON response.
    63      */
    64     public function register_options_route()
    65     {
    66         register_rest_route('shutterpress/v1', '/options', [
    67             'schema' => [$this, 'options_schema'],
    68             'methods' => 'GET',
    69             'callback' => [$this, 'get_options_for_api'],
    70             'permission_callback' => function () {
    71                 return current_user_can('manage_options');
    72             },
    73         ]);
    74     }
    75     /**
    7625     * Registers a custom REST API route to save a single metabox field.
    7726     *
     
    251200        do_action('sp_gallery_review_notice_dismissed', $user_id);
    252201        return rest_ensure_response(['message' => 'Review notice dismissed']);
    253     }
    254 
    255     /**
    256      * Retrieves the options for the Shutterpress Gallery plugin and returns them as a JSON response.
    257      *
    258      * This method is registered as a custom REST API route at `/wp/v2/options`. It retrieves the following options:
    259      *
    260      * - `sp_gallery_use_lightbox`: Whether the lightbox feature is enabled.
    261      * - `sp_gallery_layout`: The selected layout for the gallery.
    262      * - `sp_gallery_column_gap`: The gap between columns in the gallery.
    263      * - `sp_gallery_columns_desktop`: The number of columns to display on desktop devices.
    264      * - `sp_gallery_columns_tablet`: The number of columns to display on tablet devices.
    265      * - `sp_gallery_columns_mobile`: The number of columns to display on mobile devices.
    266      *
    267      * The method returns the options as a JSON response, and is only accessible to users with the `manage_options` capability (typically administrators).
    268      *
    269      * @return WP_REST_Response The options as a JSON response.
    270      */
    271     public function get_options_for_api()
    272     {
    273        
    274         $options = [
    275             'sp_gallery_use_lightbox' => filter_var(get_option('sp_gallery_use_lightbox'), FILTER_VALIDATE_BOOLEAN),
    276             'sp_gallery_layout' => sanitize_text_field(get_option('sp_gallery_layout')),
    277             'sp_gallery_column_gap' => intval(get_option('sp_gallery_column_gap')),
    278             'sp_gallery_columns_desktop' => intval(get_option('sp_gallery_columns_desktop')),
    279             'sp_gallery_columns_tablet' => intval(get_option('sp_gallery_columns_tablet')),
    280             'sp_gallery_columns_mobile' => intval(get_option('sp_gallery_columns_mobile')),
    281         ];
    282         Shutterpress_Gallery_Debug::log('REST API options output', $options);
    283         return rest_ensure_response($options);
    284202    }
    285203
  • shutterpress-gallery/trunk/src/public/Shutterpress_Gallery_Public.php

    r3376238 r3378680  
    6666        wp_enqueue_script('lightgallery', SP_GALLERY_URL . 'includes/js/lightgallery.bundle.js', ['jquery'], '2.7.1', true);
    6767        wp_enqueue_script('imagesloaded');
    68         wp_enqueue_script('infinite-scroll', SP_GALLERY_URL . 'includes/js/infinite-scroll.pkgd.min.js', ['jquery']);
     68        wp_enqueue_script('infinite-scroll', SP_GALLERY_URL . 'includes/js/infinite-scroll.pkgd.min.js', ['jquery'], null, true);
    6969        wp_enqueue_script('isotope', SP_GALLERY_URL . 'includes/js/isotope.pkgd.min.js', ['jquery'], null, true);
    7070        wp_enqueue_script('shutterpress-gallery-isotope', SP_GALLERY_URL . 'src/public/js/shutterpress-gallery-isotope.js', ['isotope', 'jquery'], null, true);
     
    187187        Shutterpress_Gallery_Debug::log('Rendering gallery shortcode', $attributes);
    188188       
    189         $use_lightbox = isset($attributes['use_lightbox'])
    190             ? $this->sp_gallery_is_truthy($attributes['use_lightbox'])
    191             : filter_var(get_option('sp_gallery_use_lightbox', true), FILTER_VALIDATE_BOOLEAN);
    192 
    193         $show_buttons = isset($attributes['show_buttons'])
    194             ? $this->sp_gallery_is_truthy($attributes['show_buttons'])
    195             : filter_var(get_option('sp_gallery_show_buttons', true), FILTER_VALIDATE_BOOLEAN);
     189        $use_lightbox = isset($attributes['use_lightbox']) ? $this->sp_gallery_is_truthy($attributes['use_lightbox']) : null;
     190
     191        $show_buttons = isset($attributes['show_buttons']) ? $this->sp_gallery_is_truthy($attributes['show_buttons']) : null;
    196192
    197193        $gallery_attributes = [
    198194            'gallery_id' => isset($attributes['id']) ? intval($attributes['id']) : null,
    199195            'use_lightbox' => $use_lightbox,
    200             'layout' => isset($attributes['layout']) ? $attributes['layout'] : sanitize_text_field(get_option('sp_gallery_layout', 'masonry')),
    201             'gap' => isset($attributes['gap']) ? intval($attributes['gap']) : intval(get_option('sp_gallery_column_gap', 20)),
    202             'row_height' => isset($attributes['row_height']) ? intval($attributes['row_height']) : intval(get_option('sp_gallery_justified_row_height', 300)),
     196            'layout' => isset($attributes['layout']) ? $attributes['layout'] : null,
     197            'gap' => isset($attributes['gap']) ? intval($attributes['gap']) : null,
     198            'row_height' => isset($attributes['row_height']) ? intval($attributes['row_height']) : null,
    203199            'show_buttons' => $show_buttons,
    204200            'gallery_type' => 'shortcode',
    205201        ];
    206202
    207         $gallery_id = $gallery_attributes['gallery_id'] ?? 'default';
     203        if (empty($gallery_attributes['gallery_id'])) {
     204            $current_id = get_the_ID();
     205            if ($current_id && is_numeric($current_id)) {
     206                $gallery_attributes['gallery_id'] = (int) $current_id;
     207            }
     208        }
     209
     210        $gallery_id = !empty($gallery_attributes['gallery_id']) ? (int) $gallery_attributes['gallery_id'] : 'default';
    208211        Shutterpress_Gallery_Debug::log('Resolved gallery ID', ['gallery_id' => $gallery_id]);
    209212
  • shutterpress-gallery/trunk/src/shutterpress-gallery-block/block.json

    r3376238 r3378680  
    1616    "useLightbox": { "type": "boolean", "default": true },
    1717    "showDefaultButtons": { "type": "boolean", "default": true },
    18     "galleryLayout": { "type": "string", "default": "masonry" },
     18    "galleryLayout": { "type": "string", "default": "grid" },
    1919    "galleryGap": { "type": "number", "default": 20 },
    2020    "rowHeight": { "type": "number", "default": 300 },
  • shutterpress-gallery/trunk/src/shutterpress-gallery-block/shutterpress-gallery-block-render.php

    r3371808 r3378680  
    6767                if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    6868                    $gallery_attributes['infinite_scroll'] = '0';
     69                    $gallery_attributes['use_lightbox'] = '0';
    6970                }
    7071
    7172                if (method_exists($renderer, 'set_attributes')) {
    7273                    $renderer->set_attributes($gallery_attributes);
    73                 }
    74 
    75                 if (defined('REST_REQUEST') && REST_REQUEST && 'edit' === $_GET['context']) {
    7674                }
    7775
  • shutterpress-gallery/trunk/src/shutterpress-gallery-block/shutterpress-gallery-block.js

    r3376238 r3378680  
    11import { registerBlockType } from '@wordpress/blocks';
    2 import { useState, useEffect } from '@wordpress/element';
     2import { useState, useEffect, useMemo } from '@wordpress/element';
    33import { SelectControl, ToggleControl, RangeControl, TextControl, PanelBody, Spinner, ComboboxControl } from '@wordpress/components';
    44import { __, sprintf } from '@wordpress/i18n';
    55import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
    6 import apiFetch from '@wordpress/api-fetch'; // Use WordPress built-in fetch
    76import metadata from './block.json';
    87import ServerSideRender from '@wordpress/server-side-render';
     8import { useSelect } from '@wordpress/data';
     9
     10// Loading and error placeholders for SSR
     11const LoadingPlaceholder = () => <Spinner />;
     12const ErrorPlaceholder = (props) => {
     13  const err = props && props.error ? props.error : null;
     14  let msg = __('Error rendering block', 'shutterpress-gallery');
     15  if (err) {
     16    if (typeof err === 'string') msg = err;
     17    else if (err && typeof err.message === 'string') msg = err.message;
     18    else {
     19      try {
     20        msg = JSON.stringify(err);
     21      } catch (e) {
     22        msg = String(err);
     23      }
     24    }
     25  }
     26  return (
     27    <div className="components-error">
     28      <p>{msg}</p>
     29    </div>
     30  );
     31};
    932
    1033// Register the block
     
    2548    galleryLayout: {
    2649      type: 'string',
    27       default: 'masonry',
     50      default: 'grid',
    2851    },
    2952    galleryGap: {
     
    5780    const { galleryId, useLightbox, showDefaultButtons, galleryLayout, galleryGap, rowHeight, columns_desktop, columns_tablet, columns_mobile } = attributes;
    5881
    59     const [galleries, setGalleries] = useState([]);
    60     const [loading, setLoading] = useState(true);
    61     const [error, setError] = useState(null);
     82    // Remove local state for galleries, loading, error.
    6283
    6384    const blockProps = useBlockProps();
    6485
     86    // Fetch galleries using useSelect at the top level (not in useEffect).
     87    const galleries = useSelect(
     88      (select) =>
     89        select('core').getEntityRecords('postType', 'shutterpress-gallery', {
     90          per_page: -1,
     91          orderby: 'title',
     92          order: 'asc',
     93          _fields: ['id', 'title'],
     94        }),
     95      [],
     96    );
     97    const loading = galleries === null;
     98    const error = null;
     99
    65100    useEffect(() => {
    66       // always fetch galleries list
    67       setLoading(true);
    68       setError(null);
    69 
    70       const perPage = 100;
    71       let all = [];
    72 
    73       const fetchPage = async (page = 1) => {
    74         // Use parse:false so we can read headers for total pages
    75         const res = await apiFetch({
    76           path: `wp/v2/shutterpress-gallery?per_page=${perPage}&page=${page}`,
    77           parse: false,
    78         });
    79         const json = await res.json();
    80         all = all.concat(Array.isArray(json) ? json : []);
    81         const totalPages = parseInt(res.headers.get('X-WP-TotalPages') || '1', 10);
    82         if (page < totalPages) {
    83           return fetchPage(page + 1);
    84         }
    85       };
    86 
    87       fetchPage(1)
    88         .then(() => {
    89           setGalleries(all);
    90           setLoading(false);
    91         })
    92         .catch((err) => {
    93           setError(err && err.message ? err.message : String(err));
    94           setGalleries([]);
    95           setLoading(false);
    96         });
    97 
    98       // only pull REST defaults once, and never overwrite saved values
    99101      if (!attributes.hasLoadedDefaults) {
    100         apiFetch({ path: 'shutterpress/v1/options' })
    101           .then((options) => {
    102             const toInt = (v, fb) => {
    103               const n = parseInt(v, 10);
    104               return Number.isFinite(n) ? n : fb;
    105             };
    106 
    107             const next = {};
    108             if (attributes.useLightbox === undefined || attributes.useLightbox === null) next.useLightbox = !!options.sp_gallery_use_lightbox;
    109             if (attributes.galleryLayout === undefined || attributes.galleryLayout === null) next.galleryLayout = options.sp_gallery_layout || 'masonry';
    110             if (attributes.galleryGap === undefined || attributes.galleryGap === null) next.galleryGap = toInt(options.sp_gallery_column_gap, 20);
    111             if (attributes.rowHeight === undefined || attributes.rowHeight === null) next.rowHeight = toInt(options.sp_gallery_justified_row_height, 300);
    112             if (attributes.columns_desktop === undefined || attributes.columns_desktop === null) next.columns_desktop = toInt(options.sp_gallery_columns_desktop, 3);
    113             if (attributes.columns_tablet === undefined || attributes.columns_tablet === null) next.columns_tablet = toInt(options.sp_gallery_columns_tablet, 2);
    114             if (attributes.columns_mobile === undefined || attributes.columns_mobile === null) next.columns_mobile = toInt(options.sp_gallery_columns_mobile, 1);
    115 
    116             setAttributes({ ...next, hasLoadedDefaults: true });
    117           })
    118           .catch((error) => {
    119             console.error('Error fetching options:', error);
    120             // still mark as loaded to avoid future overwrites
    121             setAttributes({ hasLoadedDefaults: true });
    122           });
     102        const options = typeof window !== 'undefined' && window.shutterpressDefaults ? window.shutterpressDefaults : {};
     103
     104        const toInt = (v, fb) => {
     105          const n = parseInt(v, 10);
     106          return Number.isFinite(n) ? n : fb;
     107        };
     108
     109        const next = {};
     110        if (attributes.useLightbox == null) next.useLightbox = !!options.use_lightbox;
     111        if (attributes.galleryLayout == null) next.galleryLayout = options.layout || 'grid';
     112        if (attributes.galleryGap == null) next.galleryGap = toInt(options.gap, 20);
     113        if (attributes.rowHeight == null) next.rowHeight = toInt(options.row_height, 300);
     114        if (attributes.columns_desktop == null) next.columns_desktop = toInt(options.columns_desktop, 3);
     115        if (attributes.columns_tablet == null) next.columns_tablet = toInt(options.columns_tablet, 2);
     116        if (attributes.columns_mobile == null) next.columns_mobile = toInt(options.columns_mobile, 1);
     117
     118        setAttributes({ ...next, hasLoadedDefaults: true });
    123119      }
    124120    }, [attributes.hasLoadedDefaults]);
     
    137133    // Sanitize attributes for preview and exclude internal-only keys
    138134    const sanitizeNumber = (val, fallback) => (Number.isFinite(val) ? val : fallback);
    139     const renderAttributes = {
    140       galleryId: sanitizeNumber(galleryId, 0),
    141       useLightbox: !!useLightbox,
    142       showDefaultButtons: !!showDefaultButtons,
    143       galleryLayout: galleryLayout || 'masonry',
    144       galleryGap: sanitizeNumber(galleryGap, 20),
    145       rowHeight: galleryLayout === 'justified' ? sanitizeNumber(rowHeight, 300) : undefined,
    146       columns_desktop: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_desktop, 3) : undefined,
    147       columns_tablet: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_tablet, 2) : undefined,
    148       columns_mobile: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_mobile, 1) : undefined,
    149     };
    150     const filteredRenderAttributes = Object.fromEntries(Object.entries(renderAttributes).filter(([, v]) => v !== undefined && v !== null));
    151     const ssrAttributes = filteredRenderAttributes;
     135    const ssrAttributes = useMemo(() => {
     136      const base = {
     137        galleryId: sanitizeNumber(galleryId, 0),
     138        useLightbox: !!useLightbox,
     139        showDefaultButtons: !!showDefaultButtons,
     140        galleryLayout: galleryLayout ?? undefined,
     141        galleryGap: sanitizeNumber(galleryGap, 20),
     142        rowHeight: galleryLayout === 'justified' ? sanitizeNumber(rowHeight, 300) : undefined,
     143        columns_desktop: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_desktop, 3) : undefined,
     144        columns_tablet: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_tablet, 2) : undefined,
     145        columns_mobile: galleryLayout === 'grid' || galleryLayout === 'masonry' ? sanitizeNumber(columns_mobile, 1) : undefined,
     146      };
     147      return Object.fromEntries(Object.entries(base).filter(([, v]) => v !== undefined && v !== null));
     148    }, [galleryId, useLightbox, showDefaultButtons, galleryLayout, galleryGap, rowHeight, columns_desktop, columns_tablet, columns_mobile]);
    152149
    153150    return (
     
    165162        {Number.isFinite(galleryId) && galleryId > 0 && !loading && !error && (
    166163          <div className="sp-gallery-block-preview">
    167             {console && typeof console.log === 'function' ? console.log('[ShutterPress] SSR attributes', filteredRenderAttributes) : null}
    168             <ServerSideRender
    169               block={metadata.name}
    170               httpMethod="GET"
    171               attributes={ssrAttributes}
    172               LoadingResponsePlaceholder={() => <Spinner />}
    173               ErrorResponsePlaceholder={(props) => {
    174                 const err = props && props.error ? props.error : null;
    175                 if (console && typeof console.error === 'function') {
    176                   console.error('[ShutterPress] SSR error props', props);
    177                 }
    178                 let msg = __('Error rendering block', 'shutterpress-gallery');
    179                 if (err) {
    180                   if (typeof err === 'string') {
    181                     msg = err;
    182                   } else if (err && typeof err.message === 'string') {
    183                     msg = err.message;
    184                   } else {
    185                     try {
    186                       msg = JSON.stringify(err);
    187                     } catch (e) {
    188                       msg = String(err);
    189                     }
    190                   }
    191                 }
    192                 if (console && typeof console.error === 'function') {
    193                   console.error('[ShutterPress] Block render error', err);
    194                 }
    195                 return (
    196                   <div className="components-error">
    197                     <p>{msg}</p>
    198                   </div>
    199                 );
    200               }}
    201             />
     164            <ServerSideRender block={metadata.name} httpMethod="GET" attributes={ssrAttributes} LoadingResponsePlaceholder={LoadingPlaceholder} ErrorResponsePlaceholder={ErrorPlaceholder} />
    202165          </div>
    203166        )}
     
    239202              value={galleryLayout}
    240203              options={[
     204                { label: __('Grid', 'shutterpress-gallery'), value: 'grid' },
    241205                { label: __('Masonry', 'shutterpress-gallery'), value: 'masonry' },
    242                 { label: __('Grid', 'shutterpress-gallery'), value: 'grid' },
    243206                { label: __('Justified', 'shutterpress-gallery'), value: 'justified' },
    244207              ]}
  • shutterpress-gallery/trunk/vendor/composer/installed.php

    r3376238 r3378680  
    44        'pretty_version' => 'dev-master',
    55        'version' => 'dev-master',
    6         'reference' => '1037916b588c758f6615994b2c77f6588d3b29b5',
     6        'reference' => 'ee154d9281e430a177064ec382dda47bc35fbef9',
    77        'type' => 'wordpress-plugin',
    88        'install_path' => __DIR__ . '/../../',
     
    3535            'pretty_version' => 'dev-master',
    3636            'version' => 'dev-master',
    37             'reference' => '1037916b588c758f6615994b2c77f6588d3b29b5',
     37            'reference' => 'ee154d9281e430a177064ec382dda47bc35fbef9',
    3838            'type' => 'wordpress-plugin',
    3939            'install_path' => __DIR__ . '/../../',
Note: See TracChangeset for help on using the changeset viewer.