'grid', 'columns' => 3, 'columns_tablet' => 'auto', 'columns_mobile' => 'auto', 'gap' => 10, 'radius' => 6, 'radius_corners' => '', // "tl tr br bl" when corners are unlinked, '' = all corners = radius 'aspect' => 'square', 'hover' => 'zoom', 'hover_icon' => 'none', 'caption' => 'hover', 'accent' => '#2271b1', 'image_size' => 'large', 'order' => 'custom', // Lightbox. 'lightbox' => 1, 'lb_counter' => 1, 'lb_caption' => 1, // Filters. 'filters_show' => 1, 'filter_style' => 'buttons', 'filter_size' => 'md', 'filter_shadow' => 0, 'filter_mobile' => 'wrap', 'filter_align' => 'center', 'filter_all' => 1, 'filter_all_label' => 'All', 'filter_default' => '', // Pagination. 'pagination' => 'none', 'per_page' => 12, 'loadmore_label' => 'Load more', // Global only. 'load_assets_global' => 0, 'delete_on_uninstall' => 0, ); } /** * Field schema grouped in sections. Shared by the gallery builder and the global settings page. * * @return array */ public static function fields() { $columns = array(); for ( $i = 1; $i <= 6; $i++ ) { $columns[ $i ] = $i; } $columns_auto = array( 'auto' => __( 'Auto (from desktop)', '3pika-gallery' ) ) + $columns; $sizes = array(); foreach ( get_intermediate_image_sizes() as $size ) { $sizes[ $size ] = $size; } $sizes['full'] = 'full'; return array( 'layout' => array( 'title' => __( 'Layout', '3pika-gallery' ), 'fields' => array( 'layout' => array( 'label' => __( 'Layout type', '3pika-gallery' ), 'type' => 'choice', 'options' => array( 'grid' => __( 'Grid', '3pika-gallery' ), 'mosaic' => __( 'Mosaic', '3pika-gallery' ), 'list' => __( 'List', '3pika-gallery' ), ), 'previews' => array( 'grid' => '', 'mosaic' => '', 'list' => '', ), ), 'columns' => array( 'label' => __( 'Columns (desktop)', '3pika-gallery' ), 'type' => 'select', 'options' => $columns, 'show_if' => 'layout!=justified', ), 'columns_tablet' => array( 'label' => __( 'Columns (tablet, ≤1024px)', '3pika-gallery' ), 'type' => 'select', 'options' => $columns_auto, 'show_if' => 'layout!=justified', ), 'columns_mobile' => array( 'label' => __( 'Columns (mobile, ≤767px)', '3pika-gallery' ), 'type' => 'select', 'options' => array_slice( $columns_auto, 0, 5, true ), 'show_if' => 'layout!=justified', ), 'aspect' => array( 'label' => __( 'Image ratio', '3pika-gallery' ), 'type' => 'select', 'options' => array( 'square' => __( 'Square 1:1', '3pika-gallery' ), '4-3' => __( 'Landscape 4:3', '3pika-gallery' ), '3-2' => __( 'Landscape 3:2', '3pika-gallery' ), '16-9' => __( 'Wide 16:9', '3pika-gallery' ), '3-4' => __( 'Portrait 3:4', '3pika-gallery' ), 'original' => __( 'Original', '3pika-gallery' ), ), 'show_if' => 'layout=grid', ), 'gap' => array( 'label' => __( 'Gap between images (px)', '3pika-gallery' ), 'type' => 'number', 'min' => 0, 'max' => 60, ), 'radius' => array( 'label' => __( 'Corner radius (px)', '3pika-gallery' ), 'type' => 'radius', 'min' => 0, 'max' => 60, 'desc' => __( 'Click the lock to set each corner separately (top-left, top-right, bottom-right, bottom-left).', '3pika-gallery' ), ), 'radius_corners' => array( 'label' => 'radius_corners', 'type' => 'text', 'hidden' => true, ), 'hover' => array( 'label' => __( 'Hover effect', '3pika-gallery' ), 'type' => 'choice', 'previews' => array( 'none' => '', 'zoom' => '', 'fade' => '', ), 'options' => array( 'none' => __( 'None', '3pika-gallery' ), 'zoom' => __( 'Zoom', '3pika-gallery' ), 'fade' => __( 'Fade', '3pika-gallery' ), ), ), 'hover_icon' => array( 'label' => __( 'Hover icon', '3pika-gallery' ), 'type' => 'choice', 'options' => array( 'none' => __( 'None', '3pika-gallery' ), 'zoom' => __( 'Magnifier', '3pika-gallery' ), 'plus' => __( 'Plus', '3pika-gallery' ), 'expand' => __( 'Expand', '3pika-gallery' ), 'eye' => __( 'Eye', '3pika-gallery' ), 'link' => __( 'Link', '3pika-gallery' ), ), 'previews' => array( 'none' => '–', 'zoom' => '' . tpika_icon( 'hi-zoom' ) . '', 'plus' => '' . tpika_icon( 'hi-plus' ) . '', 'expand' => '' . tpika_icon( 'hi-expand' ) . '', 'eye' => '' . tpika_icon( 'hi-eye' ) . '', 'link' => '' . tpika_icon( 'hi-link' ) . '', ), 'desc' => __( 'Icon shown in the middle of the image on hover.', '3pika-gallery' ), ), 'caption' => array( 'label' => __( 'Caption', '3pika-gallery' ), 'type' => 'select', 'options' => array( 'none' => __( 'Hidden', '3pika-gallery' ), 'hover' => __( 'Show on hover', '3pika-gallery' ), 'below' => __( 'Below image', '3pika-gallery' ), ), ), 'accent' => array( 'label' => __( 'Accent color', '3pika-gallery' ), 'type' => 'color', 'presets' => array( '#0f0f0f', '#2271b1', '#0f8a5f', '#d6f25a', '#e11d48', '#f59e0b', '#7c3aed', '#0891b2', '#64748b', '#ffffff' ), 'desc' => __( 'Used for active filters, pagination and "Load more". Filters without their own color follow this.', '3pika-gallery' ), ), 'image_size' => array( 'label' => __( 'Thumbnail size', '3pika-gallery' ), 'type' => 'select', 'options' => $sizes, 'desc' => __( 'Image size used in the grid. The lightbox always uses the full image.', '3pika-gallery' ), ), 'order' => array( 'label' => __( 'Order', '3pika-gallery' ), 'type' => 'select', 'options' => array( 'custom' => __( 'Custom (drag & drop)', '3pika-gallery' ), 'random' => __( 'Random', '3pika-gallery' ), 'date_desc' => __( 'Upload date – newest first', '3pika-gallery' ), 'date_asc' => __( 'Upload date – oldest first', '3pika-gallery' ), 'caption_asc' => __( 'Caption A → Z', '3pika-gallery' ), 'caption_desc' => __( 'Caption Z → A', '3pika-gallery' ), 'file_asc' => __( 'File name A → Z', '3pika-gallery' ), 'file_desc' => __( 'File name Z → A', '3pika-gallery' ), ), ), ), ), 'filters' => array( 'title' => __( 'Filters', '3pika-gallery' ), 'fields' => array( 'filters_show' => array( 'label' => __( 'Show filter bar', '3pika-gallery' ), 'type' => 'checkbox', ), 'filter_style' => array( 'label' => __( 'Filter style', '3pika-gallery' ), 'type' => 'choice', 'options' => array( 'buttons' => __( 'Buttons', '3pika-gallery' ), 'pills' => __( 'Pills', '3pika-gallery' ), 'square' => __( 'Square', '3pika-gallery' ), 'soft' => __( 'Soft', '3pika-gallery' ), 'outline' => __( 'Outline', '3pika-gallery' ), 'underline' => __( 'Underline', '3pika-gallery' ), 'text' => __( 'Text only', '3pika-gallery' ), 'dropdown' => __( 'Dropdown', '3pika-gallery' ), ), 'previews' => array( 'buttons' => 'AllWebLogo', 'pills' => 'AllWebLogo', 'square' => 'AllWebLogo', 'soft' => 'AllWebLogo', 'outline' => 'AllWebLogo', 'underline' => 'AllWebLogo', 'text' => 'AllWebLogo', 'dropdown' => 'All ▾', ), 'show_if' => 'filters_show=1', ), 'filter_size' => array( 'label' => __( 'Filter size', '3pika-gallery' ), 'type' => 'select', 'options' => array( 'sm' => __( 'Small', '3pika-gallery' ), 'md' => __( 'Medium', '3pika-gallery' ), 'lg' => __( 'Large', '3pika-gallery' ), ), 'show_if' => 'filters_show=1', ), 'filter_shadow' => array( 'label' => __( 'Shadow on active filter', '3pika-gallery' ), 'type' => 'checkbox', 'show_if' => 'filters_show=1&filter_style!=underline&filter_style!=text&filter_style!=dropdown', ), 'filter_mobile' => array( 'label' => __( 'Filters on mobile', '3pika-gallery' ), 'type' => 'choice', 'options' => array( 'wrap' => __( 'Wrap in rows', '3pika-gallery' ), 'scroll' => __( 'One row, swipe', '3pika-gallery' ), 'chips' => __( 'Small chips', '3pika-gallery' ), 'grid2' => __( '2 columns', '3pika-gallery' ), 'stack' => __( 'Full-width list', '3pika-gallery' ), 'dropdown' => __( 'Dropdown', '3pika-gallery' ), ), 'previews' => array( 'wrap' => 'AllWebLogoApps', 'scroll' => 'AllWebLogoAppsPrint', 'chips' => 'AllWebLogoAppsPrint', 'grid2' => 'AllWebLogoApps', 'stack' => 'AllWebLogo', 'dropdown' => 'All ▾', ), 'show_if' => 'filters_show=1', ), 'filter_align' => array( 'label' => __( 'Alignment', '3pika-gallery' ), 'type' => 'select', 'options' => array( 'left' => __( 'Left', '3pika-gallery' ), 'center' => __( 'Center', '3pika-gallery' ), 'right' => __( 'Right', '3pika-gallery' ), ), 'show_if' => 'filters_show=1', ), 'filter_all' => array( 'label' => __( 'Show "All" filter', '3pika-gallery' ), 'type' => 'checkbox', 'show_if' => 'filters_show=1', ), 'filter_all_label' => array( 'label' => __( '"All" label', '3pika-gallery' ), 'type' => 'text', 'show_if' => 'filters_show=1', ), 'filter_default' => array( 'label' => __( 'Active filter on load', '3pika-gallery' ), 'type' => 'filter_select', 'show_if' => 'filters_show=1', 'desc' => __( 'Which filter is selected when the page loads.', '3pika-gallery' ), ), ), ), 'lightbox' => array( 'title' => __( 'Lightbox', '3pika-gallery' ), 'fields' => array( 'lightbox' => array( 'label' => __( 'Open images in lightbox', '3pika-gallery' ), 'type' => 'checkbox', ), 'lb_caption' => array( 'label' => __( 'Show caption', '3pika-gallery' ), 'type' => 'checkbox', 'show_if' => 'lightbox=1', ), 'lb_counter' => array( 'label' => __( 'Show counter (1 / 12)', '3pika-gallery' ), 'type' => 'checkbox', 'show_if' => 'lightbox=1', ), ), ), 'pagination' => array( 'title' => __( 'Pagination', '3pika-gallery' ), 'fields' => array( 'pagination' => array( 'label' => __( 'Type', '3pika-gallery' ), 'type' => 'choice', 'previews' => array( 'none' => '', 'numbers' => '‹123›', 'loadmore' => 'Load more', ), 'options' => array( 'none' => __( 'None (show all)', '3pika-gallery' ), 'numbers' => __( 'Page numbers', '3pika-gallery' ), 'loadmore' => __( '"Load more" button', '3pika-gallery' ), ), ), 'per_page' => array( 'label' => __( 'Items per page', '3pika-gallery' ), 'type' => 'number', 'min' => 1, 'max' => 200, 'show_if' => 'pagination!=none', ), 'loadmore_label' => array( 'label' => __( '"Load more" label', '3pika-gallery' ), 'type' => 'text', 'show_if' => 'pagination=loadmore', ), ), ), ); } /** * Global-only fields (settings page). * * @return array */ public static function global_fields() { return array( 'load_assets_global' => array( 'label' => __( 'Always load gallery assets', '3pika-gallery' ), 'type' => 'checkbox', 'desc' => __( 'Enable if galleries are loaded via AJAX (popups, tabs) and do not initialise. Otherwise assets are only loaded on pages that contain a gallery.', '3pika-gallery' ), ), 'delete_on_uninstall' => array( 'label' => __( 'Delete all data on uninstall', '3pika-gallery' ), 'type' => 'checkbox', 'desc' => __( 'Removes all galleries and settings when the plugin is deleted. Images in the Media Library are never deleted.', '3pika-gallery' ), ), ); } /** * Flat map key => field definition. * * @return array */ public static function flat_fields() { static $flat = null; if ( null === $flat ) { $flat = array(); foreach ( self::fields() as $section ) { foreach ( $section['fields'] as $key => $field ) { $flat[ $key ] = $field; } } foreach ( self::global_fields() as $key => $field ) { $flat[ $key ] = $field; } } return $flat; } /** * Global settings (defaults for new galleries). * * @return array */ public static function get() { $saved = get_option( self::OPTION, array() ); if ( ! is_array( $saved ) ) { $saved = array(); } return wp_parse_args( $saved, self::defaults() ); } /** * Save global settings. * * @param array $input Raw input. */ public static function update( $input ) { update_option( self::OPTION, self::sanitize( $input ) ); } /** * Sanitize a settings array against the schema. Unknown keys are dropped, missing keys fall back to defaults. * * @param array $input Raw input. * @param array $base Base values for missing keys (defaults to global settings). * @return array */ public static function sanitize( $input, $base = null ) { $input = is_array( $input ) ? $input : array(); $defaults = self::defaults(); $base = is_array( $base ) ? wp_parse_args( $base, $defaults ) : $defaults; $out = array(); foreach ( self::flat_fields() as $key => $field ) { $default = isset( $base[ $key ] ) ? $base[ $key ] : ''; if ( ! array_key_exists( $key, $input ) ) { $out[ $key ] = $default; continue; } $val = $input[ $key ]; switch ( $field['type'] ) { case 'checkbox': $out[ $key ] = ! empty( $val ) && '0' !== $val && 'false' !== $val ? 1 : 0; break; case 'radius': case 'number': $val = is_numeric( $val ) ? (int) $val : (int) $default; if ( isset( $field['min'] ) ) { $val = max( (int) $field['min'], $val ); } if ( isset( $field['max'] ) ) { $val = min( (int) $field['max'], $val ); } $out[ $key ] = $val; break; case 'select': case 'choice': $val = is_scalar( $val ) ? (string) $val : ''; $out[ $key ] = array_key_exists( $val, $field['options'] ) ? ( is_numeric( $val ) ? (int) $val : $val ) : $default; break; case 'color': $c = sanitize_hex_color( is_scalar( $val ) ? $val : '' ); $out[ $key ] = $c ? $c : $default; break; case 'filter_select': $out[ $key ] = sanitize_key( is_scalar( $val ) ? $val : '' ); break; default: $out[ $key ] = sanitize_text_field( is_scalar( $val ) ? $val : '' ); if ( 'radius_corners' === $key && ! preg_match( '/^\d{1,3} \d{1,3} \d{1,3} \d{1,3}$/', $out[ $key ] ) ) { $out[ $key ] = ''; } } } return $out; } /** * Resolve "auto" responsive columns from desktop columns. * * @param array $s Settings. * @return array [desktop, tablet, mobile] */ public static function resolve_columns( $s ) { $d = max( 1, min( 6, (int) $s['columns'] ) ); $t = 'auto' === $s['columns_tablet'] ? ( $d <= 2 ? $d : (int) ceil( $d / 2 ) ) : max( 1, (int) $s['columns_tablet'] ); $m = 'auto' === $s['columns_mobile'] ? ( $d >= 3 ? 2 : 1 ) : max( 1, (int) $s['columns_mobile'] ); return array( $d, $t, $m ); } }