Plugin Directory

Changeset 3357146


Ignore:
Timestamp:
09/06/2025 03:37:39 PM (7 months ago)
Author:
iomidev
Message:

Release v1.3.0

Location:
uniqselprotb/trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • uniqselprotb/trunk/assets/css/uniqselprotb-admin.css

    r3329159 r3357146  
    11.tab-content {
    2     border: 1px solid #ddd;
    3     border-top: none;
    4     padding: 20px;
     2    border: 1px solid #ddd;
     3    border-top: none;
     4    padding: 20px;
    55}
    66
    77.nav-tab-wrapper {
    8     margin-bottom: 20px;
     8    margin-bottom: 20px;
    99}
    1010
    1111.nav-tab {
    12     background-color: #f1f1f1;
    13     border: 1px solid #ddd;
    14     display: inline-block;
    15     cursor: pointer;
    16     margin-right: 5px;
    17     padding: 10px 20px;
     12    background-color: #f1f1f1;
     13    border: 1px solid #ddd;
     14    display: inline-block;
     15    cursor: pointer;
     16    margin-right: 5px;
     17    padding: 10px 20px;
    1818}
    1919
    2020.nav-tab-active {
    21     background-color: #fff;
    22     border-bottom: none;
    23     font-weight: bold;
     21    background-color: #fff;
     22    border-bottom: none;
     23    font-weight: bold;
    2424}
    2525
    2626.form-table-settings input:not([type="checkbox"]) {
    27     width: 100%;
     27    width: 100%;
    2828}
    2929
    3030.form-settings  {
    31     display: none;
     31    display: none;
    3232}
    3333
    3434.form-table tr  {
    35     padding-top: 30px;
     35    padding-top: 30px;
    3636}
    3737
    3838.form-table th  {
    39     font-size: 22px;
    40     padding: 10px;
     39    font-size: 22px;
     40    padding: 10px;
    4141}
    4242
    4343.form-table-settings th label  {
    44     font-size: 18px;
     44    font-size: 18px;
    4545}
    4646
    4747.form-table td  {
    48     vertical-align: top;
     48    vertical-align: top;
     49}
     50
     51.form-table {
     52    table-layout: fixed;
     53    width: 100%;
     54}
     55
     56.form-table .delete-usp  {
     57    color: #99212B;
     58    cursor: pointer;
     59    font-size: 24px;
     60    margin-left: 5px;
     61}
     62
     63button#add-new-usp  {
     64    margin-top: 10px;
    4965}
    5066
    5167#form-style  {
    52     display: none;
     68    display: none;
    5369}
    5470
    5571.form-table-style input  {
    56     width: 100px;
     72    width: 100px;
    5773}
    5874
    5975.form-table-style select  {
    60     vertical-align: top;
     76    vertical-align: top;
    6177}
    6278
    6379#form-language-switcher  {
    64     display: none;
     80    display: none;
    6581}
    6682
    6783.form-table-padding input  {
    68     width: 100px;
     84    width: 100px;
    6985}
    7086
    7187.form-table-padding select  {
    72     vertical-align: top;
     88    vertical-align: top;
    7389}
    7490
    7591#tab-usps-style table label  {
    76     font-weight: bold;
     92    font-weight: bold;
    7793}
    7894
    7995.uniqselprotb_font_size  {
    80     width: 100px;
     96    width: 100px;
    8197}
    8298
     
    86102
    87103.container-table  {
    88     background-color: #FFFFFF;
    89     border-radius: 10px;
    90     margin-top: 30px;
    91     padding: 10px;
     104    background-color: #FFFFFF;
     105    border-radius: 10px;
     106    margin-top: 30px;
     107    padding: 10px;
    92108}
  • uniqselprotb/trunk/assets/css/uniqselprotb.css

    r3329159 r3357146  
    11.usps-top-banner.header-usps {
    2     overflow: hidden;
    3     width: 100%;
     2    overflow: hidden;
     3    width: 100%;
    44}
    55
    66.usps-top-banner.header-usps div.column-left {
    7     border: 1px solid transparent;
    8     float: left;
    9     width: calc(20% - 2px);
     7    border: 1px solid transparent;
     8    float: left;
     9    width: calc(20% - 2px);
    1010}
    1111
    1212.usps-top-banner.header-usps div.header-usps-column {
    13     display: flex;
    14     height: auto;
    15     float: left;
    16     justify-content: center;
    17     list-style: none;
    18     margin: 0;
    19     padding: 0;
    20     overflow: hidden;
    21     transition: none;
     13    display: flex;
     14    height: auto;
     15    float: left;
     16    justify-content: center;
     17    list-style: none;
     18    margin: 0;
     19    padding: 0;
     20    overflow: hidden;
     21    transition: none;
    2222}
    2323
    2424.usps-top-banner.header-usps div.column-center.full-width  {
    25     width: 100%;
     25    width: 100%;
    2626}
    2727
    2828.usps-top-banner.header-usps div.column-center:not(.full-width)  {
    29     width: 60%;
     29    width: 60%;
    3030}
    3131
    3232.usps-top-banner.header-usps div.column-right {
    33     float: right;
    34     text-align: right;
    35     width: 20%;
     33    float: right;
     34    text-align: right;
     35    width: 20%;
    3636}
    3737
    3838.usps-top-banner.header-usps div.column-right ul {
    39     margin: 0;
     39    margin: 0;
    4040}
    4141
    4242.usps-top-banner.header-usps span.item {
    43     box-sizing: border-box;
    44     display: block;
    45     font-size: 16px;
    46     margin: 0;
    47     transition: transform 0.3s ease;
     43    box-sizing: border-box;
     44    display: block;
     45    font-size: 16px;
     46    margin: 0;
     47    transition: transform 0.3s ease;
    4848}
    4949
    5050.usps-top-banner.header-usps span.usp-item {
    51     padding: 8px 30px;
    52     text-align: center;
     51    padding: 8px 30px;
     52    text-align: center;
    5353}
    5454
    5555.usps-top-banner.header-usps span.item span:not(.rtl) {
    56     margin-left: 10px;
     56    margin-left: 10px;
    5757}
    5858
    5959.usps-top-banner.header-usps span.item span.rtl {
    60     margin-right: 10px;
     60    margin-right: 10px;
    6161}
    6262
    6363.usps-top-banner.header-usps li.menu-item-language {
    64     display: inline-block;
    65     font-size: 16px;
    66     list-style-type: none;
    67     padding-right: 10px;
    68     padding-top: 5px;
     64    display: inline-block;
     65    font-size: 16px;
     66    list-style-type: none;
     67    padding-right: 10px;
     68    padding-top: 5px;
    6969}
    7070
    7171.usps-top-banner.header-usps li.menu-item-language a:link {
    72     text-decoration: none;
     72    text-decoration: none;
    7373}
    7474
    7575@media (max-width: 1024px) {
    76     .usps-top-banner.header-usps span.usp-item {
    77         padding: 8px 10px;
    78     }
     76    .usps-top-banner.header-usps span.usp-item {
     77        padding: 8px 10px;
     78    }
    7979
    80     .usps-top-banner.header-usps div.header-usps-column  {
    81         justify-content: flex-start;
    82     }
     80    .usps-top-banner.header-usps div.header-usps-column  {
     81        justify-content: flex-start;
     82    }
     83
     84    .usps-top-banner.header-usps div.column-left {
     85        display: none;
     86    }
     87
     88    .usps-top-banner.header-usps div.column-right {
     89        display: none;
     90    }
     91
     92    .usps-top-banner.header-usps span.item {
     93        flex: 0 0 33.3%;
     94        font-size: 14px;
     95    }
     96
     97    .usps-top-banner.header-usps div.column-center.full-width  {
     98        width: 300%;
     99    }
    83100}
    84101
    85102@media (max-width: 768px) {
    86     .usps-top-banner.header-usps span.item {
    87         flex: 0 0 33.3%;
    88         font-size: 14px;
    89     }
    90 
    91     .usps-top-banner.header-usps div.column-center.full-width  {
    92         width: 300%;
    93     }
    94 
    95     .usps-top-banner.header-usps div.column-left {
    96         display: none;
    97     }
    98 
    99     .usps-top-banner.header-usps div.column-right {
    100         displaY: none;
    101     }
    102 
    103     .usps-top-banner.header-usps li.menu-item-language {
    104         font-size: 14px;
    105     }
     103    .usps-top-banner.header-usps li.menu-item-language {
     104        font-size: 14px;
     105    }
    106106}
  • uniqselprotb/trunk/assets/js/uniqselprotb-admin.js

    r3326233 r3357146  
    1 jQuery(document).ready(function($) {
    2     $('.unique-selling-propositions-top-banner-color-field').wpColorPicker();
     1/**
     2 * Handles frontend interactions for the UNIQSELPROTB plugin admin panel.
     3 *
     4 * @package UNIQSELPROTB
     5 */
    36
    4     function showSettingsForm() {
    5         $('#form-settings').show();
    6         $('#form-style').hide();
    7     }
     7jQuery( document ).ready(
     8    function ( $ ) {
     9        $( '.unique-selling-propositions-top-banner-color-field' ).wpColorPicker();
    810
    9     function showStyleForm() {
    10         $('.form-settings').hide();
    11         $('#form-style').show();
    12     }
     11        function showSettingsForm()
     12        {
     13            $( '#form-settings' ).show();
     14            $( '#form-style' ).hide();
     15        }
    1316
    14     showSettingsForm();
     17        function showStyleForm()
     18        {
     19            $( '.form-settings' ).hide();
     20            $( '#form-style' ).show();
     21        }
    1522
    16     $('.nav-tab').on('click', function() {
    17         const tabId = $(this).attr('href');
     23        function applyClickEventOnAddNewUsp()
     24        {
     25            $( '#add-new-usp' ).on(
     26                'click' ,
     27                function ( e ) {
    1828
    19         if (tabId === '#form-settings') {
    20             showSettingsForm()
    21         } else if(tabId === '#form-style') {
    22             showStyleForm();
    23         }
     29                    e.preventDefault();
    2430
    25         $('.nav-tab').removeClass('nav-tab-active');
    26         $(this).addClass('nav-tab-active');
     31                    const countUsps = $( '#form-table-settings tr.tr-heading' ).length;
    2732
    28         return false;
    29     });
    30 });
     33                    // Get the last .tr-heading row inside tbody.
     34                    var $lastRowTrHeading = $( '#form-table-settings tr.tr-heading:last' );
     35                    var $lastRowTrInputs  = $( '#form-table-settings tr.tr-inputs:last' );
     36
     37                    // Clone last row.
     38                    var $newRowHeading = $lastRowTrHeading.clone();
     39
     40                    var $newRowInputs = $lastRowTrInputs.clone();
     41
     42                    $newRowHeading.find( 'th:first label' ).attr( 'for', 'uniqselprotb_usp_' + countUsps ).text( 'USP ' + ( countUsps + 1 ) );
     43                    $newRowHeading.find( 'th:last label' ).attr( 'for', 'uniqselprotb_usp_icon_' + countUsps );
     44
     45                    $newRowInputs.find( 'td:first input' )
     46                    .attr( 'id', 'uniqselprotb_settings_usp_' + countUsps )
     47                    .attr( 'name', 'uniqselprotb_settings[usp_' + countUsps + ']' )
     48                    .val( '' );
     49
     50                    $newRowInputs.find( 'td:last select' )
     51                    .attr( 'name', 'uniqselprotb_settings[usp_icon_' + countUsps + ']' );
     52
     53                    // Append the new row to the table.
     54                    $( '#form-table-settings tbody' ).append( $newRowHeading ).append( $newRowInputs );
     55
     56                    applyClickEventOnDeleteUsp();
     57                }
     58            );
     59        }
     60
     61        function applyClickEventOnDeleteUsp()
     62        {
     63            $( '.delete-usp' ).on(
     64                'click' ,
     65                function ( e ) {
     66                    const uspsCount = $( 'tr.tr-inputs' ).length;
     67
     68                    if (uspsCount === 1 ) {
     69                        alert( 'This item cannot be deleted because it is the only unique selling point (USP) left.' );
     70                    } else {
     71                        const parentRow           = $( this ).closest( 'tr.tr-inputs' );
     72                        const previewRowTrHeading = parentRow.prev( 'tr.tr-heading' );
     73
     74                        parentRow.remove();
     75                        previewRowTrHeading.remove();
     76
     77                        const trHeadings = $( 'tr.tr-heading' );
     78                        const trInputs   = $( 'tr.tr-inputs' );
     79
     80                        $.each(
     81                            trHeadings,
     82                            function (index, el) {
     83                                $( el ).find( '.th-usp label' )
     84                                .attr( 'for', 'uniqselprotb_usp_' + (index) )
     85                                .text( 'USP ' + (index + 1) );
     86
     87                                $( el ).find( '.th-icon label' )
     88                                .attr( 'for', 'uniqselprotb_usp_icon_' + (index) );
     89                            }
     90                        );
     91
     92                        $.each(
     93                            trInputs,
     94                            function (index, el) {
     95                                $( el ).find( 'td input[type="text"]' )
     96                                .attr( 'id', 'uniqselprotb_settings_usp_' + (index) )
     97                                .attr( 'name', 'uniqselprotb_settings[usp_' + index + ']' );
     98
     99                                $( el ).find( 'td select' )
     100                                .attr( 'id', 'icon-' + (index) )
     101                                .attr( 'name', 'uniqselprotb_settings[usp_icon_' + index + ']' );
     102                            }
     103                        );
     104                    }
     105                }
     106            );
     107        }
     108
     109        showSettingsForm();
     110
     111        $( '.nav-tab' ).on(
     112            'click' ,
     113            function () {
     114                const tabId = $( this ).attr( 'href' );
     115
     116                if (tabId === '#form-settings' ) {
     117                    showSettingsForm()
     118                } else if (tabId === '#form-style' ) {
     119                    showStyleForm();
     120                }
     121
     122                $( '.nav-tab' ).removeClass( 'nav-tab-active' );
     123                $( this ).addClass( 'nav-tab-active' );
     124
     125                return false;
     126            }
     127        );
     128
     129        applyClickEventOnAddNewUsp();
     130        applyClickEventOnDeleteUsp();
     131
     132    }
     133);
  • uniqselprotb/trunk/assets/js/uniqselprotb-frontend.js

    r3329159 r3357146  
    1 jQuery(document).ready(function($) {
    2     const items = $('.usps-top-banner.header-usps span.usp-item');
    3     let currentIndex = 0;
    4     const totalItems = items.length;
     1/**
     2 * Handles frontend interactions for the UNIQSELPROTB plugin frontend.
     3 *
     4 * @package UNIQSELPROTB
     5 */
    56
    6     function isMobileOrTablet() {
    7         return window.innerWidth <= 768;
    8     }
     7jQuery( document ).ready(
     8    function ( $ ) {
     9        const items      = $( '.usps-top-banner.header-usps span.usp-item' );
     10        let currentIndex = 0;
     11        const totalItems = items.length;
    912
    10     function moveToNextSlide() {
    11         currentIndex++;
    12         if (currentIndex >= totalItems) {
    13             currentIndex = 0;
    14         }
    15         updateSliderPosition();
    16     }
     13        function isMobileOrTablet()
     14        {
     15            return window.innerWidth <= 1024;
     16        }
    1717
    18     function updateSliderPosition() {
    19         const offset = -(currentIndex * 100);
    20         items.css('transform', 'translateX(' + offset + '%)');
    21     }
     18        function moveToNextSlide()
     19        {
     20            currentIndex++;
     21            if (currentIndex >= totalItems ) {
     22                currentIndex = 0;
     23            }
     24            updateSliderPosition();
     25        }
    2226
    23     if (isMobileOrTablet()) {
    24         setInterval(moveToNextSlide, 3000);
    25     }
    26 });
     27        function updateSliderPosition()
     28        {
     29            const offset = -( currentIndex * 100 );
     30            items.css( 'transform', 'translateX( ' + offset + '% )' );
     31        }
     32
     33        if (isMobileOrTablet()) {
     34            setInterval( moveToNextSlide, 3000 );
     35        }
     36    }
     37);
  • uniqselprotb/trunk/includes/class-uniqselprotb-loader.php

    r3329159 r3357146  
    11<?php
    2 
    32/**
    43 * Loader class for registering hooks (actions and filters) in the plugin.
     
    1918
    2019if ( ! defined( 'ABSPATH' ) ) {
    21     exit;
     20    exit;
    2221}
    2322
     
    2726class UNIQSELPROTB_Loader {
    2827
    29     private $actions = [];
    30     private $filters = [];
     28    /**
     29     * Stores registered actions for this plugin.
     30     *
     31     * @var array
     32     */
     33    private array $actions = array();
    3134
    32     /**
    33      * Register an action hook.
    34      *
    35      * @since 1.1.0
    36      *
    37      * @param $hook
    38      * @param $component
    39      * @param $callback
    40      * @param $priority
    41      * @param $accepted_args
    42      * @return void
    43      */
    44     public function add_action( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
    45         $this->actions[] = compact( 'hook', 'component', 'callback', 'priority', 'accepted_args' );
    46     }
     35    /**
     36     * Stores registered filters for this plugin.
     37     *
     38     * @var array
     39     */
     40    private array $filters = array();
    4741
    48     /**
    49      * @since 1.1.0
    50      *
    51      * @param $hook
    52      * @param $component
    53      * @param $callback
    54      * @param $priority
    55      * @param $accepted_args
    56      * @return void
    57      */
    58     public function add_filter( $hook, $component, $callback, $priority = 10, $accepted_args = 1 ) {
    59         $this->filters[] = compact( 'hook', 'component', 'callback', 'priority', 'accepted_args' );
    60     }
     42    /**
     43     * Register an action hook.
     44     *
     45     * @param string $hook The name of the WordPress filter hook.
     46     * @param object $component     The object instance that defines the callback.
     47     * @param string $callback      The callback method to be run when the filter is applied.
     48     * @param int    $priority      Optional. The priority at which the function should be fired. Default is 10.
     49     * @param int    $accepted_args Optional. The number of arguments the function accepts. Default is 1.
     50     * @return void
     51     * @since 1.1.0
     52     */
     53    public function add_action( $hook, $component, $callback, int $priority = 10, int $accepted_args = 1 ): void {
     54        $this->actions[] = array(
     55            'hook'          => $hook,
     56            'component'     => $component,
     57            'callback'      => $callback,
     58            'priority'      => $priority,
     59            'accepted_args' => $accepted_args,
     60        );
     61    }
    6162
    62     /**
    63      * @since 1.1.0
    64      *
    65      * @return void
    66      */
    67     public function run() {
    68         foreach ( $this->actions as $action ) {
    69             add_action( $action['hook'], [ $action['component'], $action['callback'] ], $action['priority'], $action['accepted_args'] );
    70         }
     63    /**
     64     * Registers a filter hook for later use.
     65     *
     66     * @param string   $hook          The name of the WordPress filter hook.
     67     * @param object   $component     The object instance that defines the callback.
     68     * @param callable $callback      The callback method to be run when the filter is applied.
     69     * @param int      $priority      Optional. The priority at which the function should be fired. Default is 10.
     70     * @param int      $accepted_args Optional. The number of arguments the function accepts. Default is 1.
     71     *
     72     * @return void
     73     * @since 1.1.0
     74     */
     75    public function add_filter( $hook, $component, $callback, int $priority = 10, int $accepted_args = 1 ): void {
     76        $this->filters[] = array(
     77            'hook'          => $hook,
     78            'component'     => $component,
     79            'callback'      => $callback,
     80            'priority'      => $priority,
     81            'accepted_args' => $accepted_args,
     82        );
     83    }
    7184
    72         foreach ( $this->filters as $filter ) {
    73             add_filter( $filter['hook'], [ $filter['component'], $filter['callback'] ], $filter['priority'], $filter['accepted_args'] );
    74         }
    75     }
     85    /**
     86     * Executes all registered actions and filters for the plugin.
     87     *
     88     * @since 1.1.0
     89     *
     90     * @return void
     91     */
     92    public function run() {
     93        foreach ( $this->actions as $action ) {
     94            add_action( $action['hook'], array( $action['component'], $action['callback'] ), $action['priority'], $action['accepted_args'] );
     95        }
     96
     97        foreach ( $this->filters as $filter ) {
     98            add_filter( $filter['hook'], array( $filter['component'], $filter['callback'] ), $filter['priority'], $filter['accepted_args'] );
     99        }
     100    }
    76101}
  • uniqselprotb/trunk/includes/class-uniqselprotb-plugin.php

    r3329159 r3357146  
    11<?php
    2 
    32/**
    43 * Plugin class file for Unique Selling Propositions Top Banner plugin.
     
    98 * @since     1.0.0
    109 * @since     1.1.0
    11  * 
     10 *
    1211 * @package   Unique_Selling_Propositions_Top_Banner
    1312 * @author    Ioanna Mitroulaki <ioanna@iomitroulaki.dev>
     
    1918
    2019if ( ! defined( 'ABSPATH' ) ) {
    21     exit;
     20    exit;
    2221}
    2322
     
    2726class UNIQSELPROTB_Plugin {
    2827
    29     private UNIQSELPROTB_Admin_Controller $admin_controller;
     28    /**
     29     * Handles admin-specific functionality for the plugin.
     30     *
     31     * @var UNIQSELPROTB_Admin_Controller
     32     */
     33    private UNIQSELPROTB_Admin_Controller $admin_controller;
    3034
    31     private UNIQSELPROTB_Frontend_Controller $frontend_controller;
     35    /**
     36     * Handles frontend-specific functionality for the plugin.
     37     *
     38     * @var UNIQSELPROTB_Frontend_Controller
     39     */
     40    private UNIQSELPROTB_Frontend_Controller $frontend_controller;
    3241
    33     private UNIQSELPROTB_Loader $loader;
     42    /**
     43     * Manages the registration of hooks and filters for the plugin.
     44     *
     45     * @var UNIQSELPROTB_Loader
     46     */
     47    private UNIQSELPROTB_Loader $loader;
    3448
    35     /**
    36     * Construct of class
    37     *
    38     * @since 1.0.0
    39     */
    40     public function __construct() {
     49    /**
     50    * Construct of class
     51    *
     52    * @since 1.0.0
     53    */
     54    public function __construct() {
    4155
    42         $this->uniqselprotb_load_dependencies();
    43         $this->define_hooks();
    44         $this->loader->run();
    45     }
     56        $this->uniqselprotb_load_dependencies();
     57        $this->define_hooks();
     58        $this->loader->run();
     59    }
    4660
    47     /**
    48     * Load dependencies
    49     *
    50     * @since 1.1.0
    51      *
    52     * @return void
    53     */
    54     private function uniqselprotb_load_dependencies(): void {
    55         require_once plugin_dir_path( __FILE__ ) . 'class-uniqselprotb-loader.php';
    56         $this->loader = new UNIQSELPROTB_Loader();
     61    /**
     62    * Load dependencies
     63    *
     64    * @since 1.1.0
     65     *
     66    * @return void
     67    */
     68    private function uniqselprotb_load_dependencies(): void {
     69        require_once plugin_dir_path( __FILE__ ) . 'class-uniqselprotb-loader.php';
     70        $this->loader = new UNIQSELPROTB_Loader();
    5771
    58         if ( is_admin() ) {
    59             require_once plugin_dir_path( __FILE__ ) . 'controllers/class-uniqselprotb-admin-controller.php';
    60             $this->admin_controller = new UNIQSELPROTB_Admin_Controller();
    61         } else {
    62             require_once plugin_dir_path( __FILE__ ) . 'controllers/class-uniqselprotb-frontend-controller.php';
    63             $this->frontend_controller = new UNIQSELPROTB_Frontend_Controller();
    64         }
    65     }
     72        if ( is_admin() ) {
     73            require_once plugin_dir_path( __FILE__ ) . 'controllers/class-uniqselprotb-admin-controller.php';
     74            $this->admin_controller = new UNIQSELPROTB_Admin_Controller();
     75        } else {
     76            require_once plugin_dir_path( __FILE__ ) . 'controllers/class-uniqselprotb-frontend-controller.php';
     77            $this->frontend_controller = new UNIQSELPROTB_Frontend_Controller();
     78        }
     79    }
    6680
    67     /**
    68     * Define hooks.
    69     *
    70     * @since 1.1.0
    71     *
    72     * @return void
    73     */
    74     private function define_hooks() {
    75         if ( is_admin() ) {
    76             $this->loader->add_action( 'admin_enqueue_scripts', $this->admin_controller, 'uniqselprotb_enqueue_styles' );
    77             $this->loader->add_action( 'admin_enqueue_scripts', $this->admin_controller, 'uniqselprotb_enqueue_scripts' );
    78             $this->loader->add_action( 'admin_menu', $this->admin_controller, 'uniqselprotb_register_menu' );
    79         } else {
    80             $this->loader->add_action( 'wp_enqueue_scripts', $this->frontend_controller, 'uniqselprotb_register_frontend_assets');
    81             $this->loader->add_action( 'wp_body_open', $this->frontend_controller, 'uniqselprotb_render_banner' );
    82         }
    83     }
     81    /**
     82    * Define hooks.
     83    *
     84    * @since 1.1.0
     85    *
     86    * @return void
     87    */
     88    private function define_hooks() {
     89        if ( is_admin() ) {
     90            $this->loader->add_action( 'admin_enqueue_scripts', $this->admin_controller, 'uniqselprotb_enqueue_styles' );
     91            $this->loader->add_action( 'admin_enqueue_scripts', $this->admin_controller, 'uniqselprotb_enqueue_scripts' );
     92            $this->loader->add_action( 'admin_menu', $this->admin_controller, 'uniqselprotb_register_menu' );
     93        } else {
     94            $this->loader->add_action( 'wp_enqueue_scripts', $this->frontend_controller, 'uniqselprotb_register_frontend_assets' );
     95            $this->loader->add_action( 'wp_body_open', $this->frontend_controller, 'uniqselprotb_render_banner' );
     96        }
     97    }
    8498}
  • uniqselprotb/trunk/includes/class-uniqselprotb-router.php

    r3329159 r3357146  
    11<?php
    2 
    32/**
    43 * Plugin router class file for Unique Selling Propositions Top Banner plugin.
    5  *
    64 *
    75 * @package   Unique_Selling_Propositions_Top_Banner
     
    1816
    1917if ( ! defined( 'ABSPATH' ) ) {
    20     exit;
     18    exit;
    2119}
    2220
     
    2624class UNIQSELPROTB_Router {
    2725
    28     /**
    29     * Render the main settings page content for the plugin.
    30     *
    31     * @since 1.0.0
    32     * @since 1.1.0 Updated to call uniqselprotb_verify_user_permission() instead of verify_user_permission().
    33     *
    34     * @return void
    35     */
    36     public function uniqselprotb_render_main_settings_page(): void {
    37         if ( ! is_admin() ) {
    38             return;
    39         }
     26    /**
     27    * Render the main settings page content for the plugin.
     28    *
     29    * @since 1.0.0
     30    * @since 1.1.0 Updated to call uniqselprotb_verify_user_permission() instead of verify_user_permission().
     31    *
     32    * @return void
     33    */
     34    public function uniqselprotb_render_main_settings_page(): void {
     35        if ( ! is_admin() ) {
     36            return;
     37        }
    4038
    41         $this->uniqselprotb_verify_user_permission();
     39        $this->uniqselprotb_verify_user_permission();
    4240
    43         $controller       = $this->get_controller();
    44         $controller_class = $this->get_controller_class( $controller );
     41        $controller       = $this->get_controller();
     42        $controller_class = $this->get_controller_class( $controller );
    4543
    46         if ( ! in_array( $controller, UNIQSELPROTB_Plugin_Constant::ALLOWED_CONTROLLERS, true ) ) {
    47             wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
    48         }
     44        if ( ! in_array( $controller, UNIQSELPROTB_Plugin_Constant::ALLOWED_CONTROLLERS, true ) ) {
     45            wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
     46        }
    4947
    50         $method          = $this->get_method();
    51         $allowed_methods = UNIQSELPROTB_Plugin_Constant::ALLOWED_METHODS;
     48        $method          = $this->get_method();
     49        $allowed_methods = UNIQSELPROTB_Plugin_Constant::ALLOWED_METHODS;
    5250
    53         if ( ! in_array( $method, $allowed_methods, true ) ) {
    54             wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
    55         }
    56         $this->verify_post_nonce();
     51        if ( ! in_array( $method, $allowed_methods, true ) ) {
     52            wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
     53        }
     54        $this->verify_post_nonce();
    5755
    58         if ( class_exists( $controller_class ) ) {
    59             $instance = new $controller_class();
    60             if ( method_exists( $instance, $method ) ) {
    61                 call_user_func( array( $instance, $method ) );
    62             } else {
    63                 $this->uniqselprotb_method_not_found();
    64             }
    65         } else {
    66             $this->uniqselprotb_controller_not_found();
    67         }
    68     }
     56        if ( class_exists( $controller_class ) ) {
     57            $instance = new $controller_class();
     58            if ( method_exists( $instance, $method ) ) {
     59                call_user_func( array( $instance, $method ) );
     60            } else {
     61                $this->uniqselprotb_method_not_found();
     62            }
     63        } else {
     64            $this->uniqselprotb_controller_not_found();
     65        }
     66    }
    6967
    70     /**
    71     * Get controller name.
    72     *
    73     * @since 1.0.0
    74     *
    75     * @return string
    76     */
    77     private function get_controller(): string {
    78         return 'admin';
    79     }
     68    /**
     69    * Get controller name.
     70    *
     71    * @since 1.0.0
     72    *
     73    * @return string
     74    */
     75    private function get_controller(): string {
     76        return 'admin';
     77    }
    8078
    81     /**
    82     * Get the controller class.
    83     *
    84     * @since 1.0.0
    85     *
    86     * @param  string $controller The controller class name.
    87     * @return string
    88     */
    89     private function get_controller_class( string $controller ): string {
    90         static $controller_classes = array();
     79    /**
     80    * Get the controller class.
     81    *
     82    * @since 1.0.0
     83    *
     84    * @param  string $controller The controller class name.
     85    * @return string
     86    */
     87    private function get_controller_class( string $controller ): string {
     88        static $controller_classes = array();
    9189
    92         if ( ! isset( $controller_classes[ $controller ] ) ) {
    93             $controller_classes[ $controller ] = strtoupper( UNIQSELPROTB_Plugin_Constant::PLUGIN_PREFIX ) . '_' . ucfirst( $controller ) . '_Controller';
    94         }
     90        if ( ! isset( $controller_classes[ $controller ] ) ) {
     91            $controller_classes[ $controller ] = strtoupper( UNIQSELPROTB_Plugin_Constant::PLUGIN_PREFIX ) . '_' . ucfirst( $controller ) . '_Controller';
     92        }
    9593
    96         return $controller_classes[ $controller ];
    97     }
     94        return $controller_classes[ $controller ];
     95    }
    9896
    99     /**
    100     * Get the method.
    101     *
    102     * @since 1.0.0
    103     *
    104     * @return string
    105     */
    106     private function get_method(): string {
    107         if (
    108             isset( $_GET['method'], $_GET['_wpnonce'] ) &&
    109             wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'uniqselprotb_router_method' )
    110         ) {
    111             $method = sanitize_text_field( wp_unslash( $_GET['method'] ) );
    112         }
     97    /**
     98    * Get the method.
     99    *
     100    * @since 1.0.0
     101    *
     102    * @return string
     103    */
     104    private function get_method(): string {
     105        if (
     106            isset( $_GET['method'], $_GET['_wpnonce'] ) &&
     107            wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'uniqselprotb_router_method' )
     108        ) {
     109            $method = sanitize_text_field( wp_unslash( $_GET['method'] ) );
     110        }
    113111
    114         return ! empty( $method ) ? $method : UNIQSELPROTB_Plugin_Constant::PLUGIN_PREFIX . '_' . UNIQSELPROTB_Plugin_Constant::DEFAULT_METHOD;
    115     }
     112        return ! empty( $method ) ? $method : UNIQSELPROTB_Plugin_Constant::PLUGIN_PREFIX . '_' . UNIQSELPROTB_Plugin_Constant::DEFAULT_METHOD;
     113    }
    116114
    117     /**
    118     * Verify the nonce sent via POST to secure form submissions.
    119     *
    120     * @since 1.0.0
    121     *
    122     * @return void
    123     */
    124     private function verify_post_nonce(): void {
    125         $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
     115    /**
     116    * Verify the nonce sent via POST to secure form submissions.
     117    *
     118    * @since 1.0.0
     119    *
     120    * @return void
     121    */
     122    private function verify_post_nonce(): void {
     123        $request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
    126124
    127         if ( 'POST' === $request_method
    128             && isset( $_POST[ UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ] )
    129         ) {
    130             $nonce = sanitize_text_field(
    131                 wp_unslash( $_POST[ UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ] )
    132             );
     125        if ( 'POST' === $request_method
     126            && isset( $_POST[ UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ] )
     127        ) {
     128            $nonce = sanitize_text_field(
     129                wp_unslash( $_POST[ UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ] )
     130            );
    133131
    134             if ( empty( $nonce )
    135                 || ! wp_verify_nonce( $nonce , UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_ACTION )
    136             ) {
    137                 wp_die( esc_html__( 'Security check failed. Please try again.', 'uniqselprotb' ) );
    138             }
    139         }
    140     }
     132            if ( empty( $nonce )
     133                || ! wp_verify_nonce( $nonce, UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_ACTION )
     134            ) {
     135                wp_die( esc_html__( 'Security check failed. Please try again.', 'uniqselprotb' ) );
     136            }
     137        }
     138    }
    141139
    142     /**
    143     * Verify that the current user has permission to manage plugin settings.
    144     *
    145     * Terminates execution if the user lacks the required capability.
    146     *
    147     * @since 1.1.0 Renamed from verify_user_permission().
    148     *
    149     * @return void
    150     */
    151     private function uniqselprotb_verify_user_permission(): void {
    152         if ( ! current_user_can( 'manage_options' ) ) {
    153             wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
    154         }
    155     }
     140    /**
     141    * Verify that the current user has permission to manage plugin settings.
     142    *
     143    * Terminates execution if the user lacks the required capability.
     144    *
     145    * @since 1.1.0 Renamed from verify_user_permission().
     146    *
     147    * @return void
     148    */
     149    private function uniqselprotb_verify_user_permission(): void {
     150        if ( ! current_user_can( 'manage_options' ) ) {
     151            wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
     152        }
     153    }
    156154
    157     /**
    158     * Handle the case when a requested controller is not found.
    159     *
    160     * @since 1.0.0
    161     *
    162     * @return void
    163     */
    164     #[NoReturn] private function uniqselprotb_controller_not_found(): void {
    165         wp_die(
    166             '<h1>' . esc_html__( 'Controller not found', 'uniqselprotb' ) . '</h1>' .
    167             '<p>' . esc_html__( 'The requested controller does not exist. Please check the URL and try again.', 'uniqselprotb' ) . '</p>',
    168             esc_html__( 'Controller Error', 'uniqselprotb' ),
    169             array(
    170                 'response'  => 404,
    171                 'back_link' => true,
    172             )
    173         );
    174     }
     155    /**
     156    * Handle the case when a requested controller is not found.
     157    *
     158    * @since 1.0.0
     159    *
     160    * @return void
     161    */
     162    #[NoReturn] private function uniqselprotb_controller_not_found(): void {
     163        wp_die(
     164            '<h1>' . esc_html__( 'Controller not found', 'uniqselprotb' ) . '</h1>' .
     165            '<p>' . esc_html__( 'The requested controller does not exist. Please check the URL and try again.', 'uniqselprotb' ) . '</p>',
     166            esc_html__( 'Controller Error', 'uniqselprotb' ),
     167            array(
     168                'response'  => 404,
     169                'back_link' => true,
     170            )
     171        );
     172    }
    175173
    176     /**
    177     * Handle the case when a called method is not found.
    178     *
    179     * @since 1.0.0
    180     *
    181     * @return void
    182     */
    183     #[NoReturn] private function uniqselprotb_method_not_found(): void {
    184         wp_die(
    185             '<h1>' . esc_html__( 'Method not found', 'uniqselprotb' ) . '</h1>' .
    186             '<p>' . esc_html__( 'The requested method does not exist in the controller. Please check the URL and try again.', 'uniqselprotb' ) . '</p>',
    187             esc_html__( 'Method Error', 'uniqselprotb' ),
    188             array(
    189                 'response'  => 404,
    190                 'back_link' => true,
    191             )
    192         );
    193     }
     174    /**
     175    * Handle the case when a called method is not found.
     176    *
     177    * @since 1.0.0
     178    *
     179    * @return void
     180    */
     181    #[NoReturn] private function uniqselprotb_method_not_found(): void {
     182        wp_die(
     183            '<h1>' . esc_html__( 'Method not found', 'uniqselprotb' ) . '</h1>' .
     184            '<p>' . esc_html__( 'The requested method does not exist in the controller. Please check the URL and try again.', 'uniqselprotb' ) . '</p>',
     185            esc_html__( 'Method Error', 'uniqselprotb' ),
     186            array(
     187                'response'  => 404,
     188                'back_link' => true,
     189            )
     190        );
     191    }
    194192}
  • uniqselprotb/trunk/includes/constants/class-uniqselprotb-font-awesome-constant.php

    r3329159 r3357146  
    1414
    1515if ( ! defined( 'ABSPATH' ) ) {
    16     exit;
     16    exit;
    1717}
    1818
     
    2222class UNIQSELPROTB_Font_Awesome_Constant {
    2323
    24     const ICONS_LIST = [
    25         'fa-solid fa-truck'          => 'Truck',
    26         'fa-solid fa-envelope'       => 'Envelope',
    27         'fa-solid fa-map-marker-alt' => 'Map Marker',
    28         'fa-solid fa-phone'          => 'Phone',
    29         'fa-solid fa-box'            => 'Box',
    30         'fa-solid fa-user'           => 'User',
    31         'fa-solid fa-clock'          => 'Clock',
    32         'fa-solid fa-calendar'       => 'Calendar',
    33         'fa-solid fa-store'          => 'Store',
    34         'fa-solid fa-shipping-fast'  => 'Fast Shipping',
    35         'fa-solid fa-globe'          => 'Globe',
    36         'fa-solid fa-clipboard-list' => 'Checklist',
    37         'fa-solid fa-undo'           => 'Returns',
    38         'fa-solid fa-check-circle'   => 'Check Circle',
    39     ];
     24    const ICONS_LIST = array(
     25        'fa-solid fa-truck'          => 'Truck',
     26        'fa-solid fa-envelope'       => 'Envelope',
     27        'fa-solid fa-map-marker-alt' => 'Map Marker',
     28        'fa-solid fa-phone'          => 'Phone',
     29        'fa-solid fa-box'            => 'Box',
     30        'fa-solid fa-user'           => 'User',
     31        'fa-solid fa-clock'          => 'Clock',
     32        'fa-solid fa-calendar'       => 'Calendar',
     33        'fa-solid fa-store'          => 'Store',
     34        'fa-solid fa-shipping-fast'  => 'Fast Shipping',
     35        'fa-solid fa-globe'          => 'Globe',
     36        'fa-solid fa-clipboard-list' => 'Checklist',
     37        'fa-solid fa-undo'           => 'Returns',
     38        'fa-solid fa-check-circle'   => 'Check Circle',
     39    );
    4040}
  • uniqselprotb/trunk/includes/constants/class-uniqselprotb-options-constant.php

    r3329159 r3357146  
    1414
    1515if ( ! defined( 'ABSPATH' ) ) {
    16     exit;
     16    exit;
    1717}
    1818
     
    2222class UNIQSELPROTB_Options_Constant {
    2323
    24     const OPTIONS = [
    25         'uniqselprotb_settings',
    26         'uniqselprotb_style',
    27     ];
     24    const OPTIONS = array(
     25        'uniqselprotb_settings',
     26        'uniqselprotb_style',
     27    );
    2828}
  • uniqselprotb/trunk/includes/constants/class-uniqselprotb-plugin-constant.php

    r3329159 r3357146  
    1515
    1616if ( ! defined( 'ABSPATH' ) ) {
    17     exit;
     17    exit;
    1818}
    1919
     
    2323class UNIQSELPROTB_Plugin_Constant {
    2424
    25     const PLUGIN_PREFIX = 'uniqselprotb';
     25    const PLUGIN_PREFIX = 'uniqselprotb';
    2626
    27     const DEFAULT_METHOD = 'render_settings_page';
     27    const DEFAULT_METHOD = 'render_settings_page';
    2828
    29     const NONCE_SETTINGS_FIELD = 'uniqselprotb_saving_settings_nonce';
     29    const NONCE_SETTINGS_FIELD = 'uniqselprotb_saving_settings_nonce';
    3030
    31     const NONCE_SETTINGS_ACTION = 'uniqselprotb_saving_settings';
     31    const NONCE_SETTINGS_ACTION = 'uniqselprotb_saving_settings';
    3232
    33     const NONCE_STYLE_FIELD = 'uniqselprotb_saving_style_nonce';
     33    const NONCE_STYLE_FIELD = 'uniqselprotb_saving_style_nonce';
    3434
    35     const PLUGIN_SLUG = 'uniqselprotb';
     35    const PLUGIN_SLUG = 'uniqselprotb';
    3636
    37     const ALLOWED_CONTROLLERS = [ 'admin' ];
    38     const ALLOWED_METHODS     = [ 'uniqselprotb_render_settings_page' ];
     37    const ALLOWED_CONTROLLERS = array( 'admin' );
     38    const ALLOWED_METHODS     = array( 'uniqselprotb_render_settings_page' );
    3939
    40     const DEFAULT_BACKGROUND_COLOR = '#0e2a36';
     40    const DEFAULT_BACKGROUND_COLOR = '#0e2a36';
    4141
    42     const DEFAULT_TEXT_COLOR = '#FFFFFF';
     42    const DEFAULT_TEXT_COLOR = '#FFFFFF';
    4343
    44     const DEFAULT_FONT_SIZE = '18';
     44    const DEFAULT_FONT_SIZE = '18';
    4545
    46     const DEFAULT_FONT_SIZE_UNIT = 'px';
     46    const DEFAULT_FONT_SIZE_UNIT = 'px';
    4747
    48     const DEFAULT_FONT_WEIGHT = 'normal';
     48    const DEFAULT_FONT_WEIGHT = 'normal';
    4949
    50     const DEFAULT_FONT_STYLE = 'normal';
     50    const DEFAULT_FONT_STYLE = 'normal';
    5151
    52     const DEFAULT_PADDING_BOTTOM = '0';
     52    const DEFAULT_PADDING_BOTTOM = '0';
    5353
    54     const DEFAULT_PADDING_TOP = '0';
     54    const DEFAULT_PADDING_TOP = '0';
    5555
    56     const DEFAULT_PADDING_LEFT = '0';
     56    const DEFAULT_PADDING_LEFT = '0';
    5757
    58     const DEFAULT_PADDING_RIGHT = '0';
     58    const DEFAULT_PADDING_RIGHT = '0';
    5959
    60     const DEFAULT_PADDING_BOTTOM_UNIT = 'px';
     60    const DEFAULT_PADDING_BOTTOM_UNIT = 'px';
    6161
    62     const DEFAULT_PADDING_TOP_UNIT = 'px';
     62    const DEFAULT_PADDING_TOP_UNIT = 'px';
    6363
    64     const DEFAULT_PADDING_LEFT_UNIT = 'px';
     64    const DEFAULT_PADDING_LEFT_UNIT = 'px';
    6565
    66     const DEFAULT_PADDING_RIGHT_UNIT = 'px';
     66    const DEFAULT_PADDING_RIGHT_UNIT = 'px';
    6767
    68     const ALLOWED_SETTINGS_FIELDS = [ 'usp_0', 'usp_1', 'usp_2', 'usp_icon_0', 'usp_icon_1', 'usp_icon_2' ];
     68    const ALLOWED_SETTINGS_FIELDS = array( 'usp_0', 'usp_1', 'usp_2', 'usp_icon_0', 'usp_icon_1', 'usp_icon_2' );
    6969
    70     const ALLOWED_STYLE_FIELDS = [ 'background_color', 'text_color', 'font_size', 'font_size_unit', 'font_weight', 'font_style', 'padding_bottom', 'padding_top', 'padding_left', 'padding_right', 'padding_bottom_unit', 'padding_top_unit', 'padding_left_unit', 'padding_right_unit' ];
     70    const ALLOWED_STYLE_FIELDS = array( 'background_color', 'text_color', 'font_size', 'font_size_unit', 'font_weight', 'font_style', 'padding_bottom', 'padding_top', 'padding_left', 'padding_right', 'padding_bottom_unit', 'padding_top_unit', 'padding_left_unit', 'padding_right_unit' );
    7171}
  • uniqselprotb/trunk/includes/controllers/class-uniqselprotb-admin-controller.php

    r3329172 r3357146  
    1212
    1313if ( ! defined( 'ABSPATH' ) ) {
    14     exit;
     14    exit;
    1515}
    1616
     
    2121
    2222
    23     /**
    24      * @since     1.0.0
    25      * @since     1.1.0 Include constants
    26      */
    27     public function __construct()
    28     {
    29         // Load the class with the constant
    30         require_once plugin_dir_path(__DIR__) . 'constants/class-uniqselprotb-font-awesome-constant.php';
    31         require_once plugin_dir_path(__DIR__) . 'constants/class-uniqselprotb-plugin-constant.php';
    32         require_once plugin_dir_path(__DIR__) . 'constants/class-uniqselprotb-options-constant.php';
    33 
    34         /* Hook to handle form submissions */
    35         add_action( 'admin_post_uniqselprotb_saving_settings', [ $this, 'uniqselprotb_save_settings_handler' ] );
    36         add_action( 'admin_post_uniqselprotb_saving_style', [ $this, 'uniqselprotb_save_style_handler' ] );
    37     }
    38 
    39     /**
    40      * The available languages of the installation
    41      *
    42      * @var array
    43      */
    44     private array $available_languages;
    45 
    46     /**
    47      * Enqueue styles.
    48      *
    49      * @since     1.1.0
    50      *
    51      * @return void
    52      */
    53     public function uniqselprotb_enqueue_styles() {
    54         wp_enqueue_style(
    55             'uniqselprotb-admin-style',
    56             plugin_dir_url( __FILE__ ) . '../../assets/css/uniqselprotb-admin.css',
    57             [],
    58             '1.1.0'
    59         );
    60 
    61         wp_enqueue_style( 'wp-color-picker' );
    62     }
    63 
    64     /**
    65      * Enqueue scripts.
    66      *
    67      * @since     1.1.0
    68      *
    69      * @param $hook_suffix
    70      * @return void
    71      */
    72     public function uniqselprotb_enqueue_scripts($hook_suffix) {
    73 
    74         if ( 'toplevel_page_' . UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG === $hook_suffix ) {
    75             if (version_compare(get_bloginfo('version'), '6.3', '>=')) {
    76                 wp_enqueue_script(
    77                     'uniqselprotb-admin-script',
    78                     UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-admin.js',
    79                     ['jquery'],
    80                     '1.1.0',
    81                     ['strategy' => 'defer']
    82                 );
    83             } else {
    84                 wp_enqueue_script(
    85                     'uniqselprotb-admin-script',
    86                     UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-admin.js',
    87                     ['jquery'],
    88                     '1.1.0',
    89                     true
    90                 );
    91                 /* Add defer attribute manually using filter for versions < 6.3 */
    92                 add_filter('script_loader_tag', [$this, 'uniqselprotb_add_admin_defer_attribute'], 10, 2);
    93             }
    94 
    95             wp_enqueue_script('wp-color-picker');
    96         }
    97     }
    98 
    99     /**
    100      * Adds the 'defer' attribute to a specific admin script for WordPress < 6.3.
    101      *
    102      * @since     1.1.0
    103      *
    104      * @param string $tag    The HTML script tag.
    105      * @param string $handle The script handle.
    106      * @return string Modified script tag with 'defer', or original tag.
    107      */
    108     public function uniqselprotb_add_admin_defer_attribute( string $tag, string $handle ): string {
    109         /* Check if this is the script handle you want to apply 'defer' to */
    110         if ( 'uniqselprotb-admin-script' === $handle ) {
    111             return str_replace( ' src', ' defer="defer" src', $tag );
    112         }
    113         return $tag;
    114     }
    115 
    116     /**
    117      * Register menu
    118      *
    119      * @since     1.1.0
    120      *
    121      * @return void
    122      */
    123     public function uniqselprotb_register_menu() {
    124         add_menu_page(
    125             'Unique Selling Propositions',
    126             'Unique Selling Propositions',
    127             'manage_options',
    128             'uniqselprotb',
    129             [ $this, 'uniqselprotb_render_admin_page' ],
    130             'dashicons-star-filled'
    131         );
    132     }
    133 
    134     /**
    135      * Render admin page.
    136      *
    137      * @since     1.1.0
    138      *
    139      * @return void
    140      */
    141     public function uniqselprotb_render_admin_page() {
    142         $optionsSettings = get_option( 'uniqselprotb_settings', array() );
    143 
    144         if ( ! is_array( $optionsSettings ) ) {
    145             $optionsSettings = array();
    146         }
    147 
    148         $icons = UNIQSELPROTB_Font_Awesome_Constant::ICONS_LIST;
    149 
    150         $usps_value = [];
    151         $usps_icon = [];
    152 
    153         for ( $i = 0; $i < 3; $i++ ) {
    154             $usps_value['usp_' . $i] = $optionsSettings['usp_' . $i] ?? '';
    155             $usps_icon['usp_' . $i] = $optionsSettings['usp_icon_' . $i] ?? $icons[array_key_first($icons)];
    156         }
    157 
    158         $optionsStyle = get_option( 'uniqselprotb_style', [] );
    159 
    160         if ( ! is_array( $optionsStyle ) ) {
    161             $optionsStyle = [];
    162         }
    163 
    164         $background_color = $optionsStyle['background_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
    165         $text_color       = $optionsStyle['text_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
    166 
    167         $font_size = $optionsStyle['font_size'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
    168         $font_size_unit = $optionsStyle['font_size_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
    169         $font_weight = $optionsStyle['font_weight'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
    170         $font_style = $optionsStyle['font_style'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
    171         $padding_bottom = $optionsStyle['padding_bottom'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM;
    172         $padding_top = $optionsStyle['padding_top'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP;
    173         $padding_bottom_unit = $optionsStyle['padding_bottom_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
    174         $padding_top_unit = $optionsStyle['padding_top_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
    175         $padding_left = $optionsStyle['padding_left'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT;
    176         $padding_right = $optionsStyle['padding_right'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT;
    177         $padding_left_unit= $optionsStyle['padding_left_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
    178         $padding_right_unit = $optionsStyle['padding_right_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
    179 
    180         echo '<div class="wrap">';
    181 
    182         require plugin_dir_path( __DIR__ ) . 'views/uniqselprotb-admin-nav-settings.php';
    183         require plugin_dir_path( __DIR__ ) . 'views/uniqselprotb-form-settings.php';
    184         require plugin_dir_path(__DIR__) . 'views/uniqselprotb-form-style.php';
    185 
    186         echo  '</div>';
    187     }
    188 
    189     /**
    190      * Settings Form Submission.
    191      *
    192      * @since     1.0.0
    193      *
    194      * @return void
    195      */
    196     public function uniqselprotb_save_settings_handler() {
    197 
    198         $this->verify_user_permission();
    199 
    200         if ( ! isset( $_POST['uniqselprotb_saving_settings_nonce'] ) ) {
    201             wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
    202         }
    203 
    204         if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['uniqselprotb_saving_settings_nonce'] ) ), 'uniqselprotb_saving_settings' ) ) {
    205             wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
    206         }
     23    /**
     24     * The construct of the class
     25     *
     26     * @since     1.0.0
     27     * @since     1.1.0 Include constants
     28     */
     29    public function __construct() {
     30        // Load the class with the constant.
     31        require_once plugin_dir_path( __DIR__ ) . 'constants/class-uniqselprotb-font-awesome-constant.php';
     32        require_once plugin_dir_path( __DIR__ ) . 'constants/class-uniqselprotb-plugin-constant.php';
     33        require_once plugin_dir_path( __DIR__ ) . 'constants/class-uniqselprotb-options-constant.php';
     34
     35        /* Hook to handle form submissions */
     36        add_action( 'admin_post_uniqselprotb_saving_settings', array( $this, 'uniqselprotb_save_settings_handler' ) );
     37        add_action( 'admin_post_uniqselprotb_saving_style', array( $this, 'uniqselprotb_save_style_handler' ) );
     38    }
     39
     40    /**
     41     * The available languages of the installation
     42     *
     43     * @var array
     44     */
     45    private array $available_languages;
     46
     47    /**
     48     * Enqueue styles.
     49     *
     50     * @since     1.1.0
     51     *
     52     * @return void
     53     */
     54    public function uniqselprotb_enqueue_styles() {
     55        wp_enqueue_style(
     56            'uniqselprotb-admin-style',
     57            plugin_dir_url( __FILE__ ) . '../../assets/css/uniqselprotb-admin.css',
     58            array(),
     59            '1.1.0'
     60        );
     61
     62        wp_enqueue_style( 'wp-color-picker' );
     63    }
     64
     65    /**
     66     * Enqueue scripts.
     67     *
     68     * @since     1.1.0
     69     *
     70     * @param string $hook_suffix The suffix of the hook.
     71     * @return void
     72     */
     73    public function uniqselprotb_enqueue_scripts( string $hook_suffix ): void {
     74
     75        if ( 'toplevel_page_' . UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG === $hook_suffix ) {
     76            if ( version_compare( get_bloginfo( 'version' ), '6.3', '>=' ) ) {
     77                wp_enqueue_script(
     78                    'uniqselprotb-admin-script',
     79                    UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-admin.js',
     80                    array( 'jquery' ),
     81                    '1.1.0',
     82                    array( 'strategy' => 'defer' )
     83                );
     84            } else {
     85                wp_enqueue_script(
     86                    'uniqselprotb-admin-script',
     87                    UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-admin.js',
     88                    array( 'jquery' ),
     89                    '1.1.0',
     90                    true
     91                );
     92                /* Add defer attribute manually using filter for versions < 6.3 */
     93                add_filter( 'script_loader_tag', array( $this, 'uniqselprotb_add_admin_defer_attribute' ), 10, 2 );
     94            }
     95
     96            wp_enqueue_script( 'wp-color-picker' );
     97        }
     98    }
     99
     100    /**
     101     * Adds the 'defer' attribute to a specific admin script for WordPress < 6.3.
     102     *
     103     * @since     1.1.0
     104     *
     105     * @param string $tag    The HTML script tag.
     106     * @param string $handle The script handle.
     107     * @return string Modified script tag with 'defer', or original tag.
     108     */
     109    public function uniqselprotb_add_admin_defer_attribute( string $tag, string $handle ): string {
     110        /* Check if this is the script handle you want to apply 'defer' to */
     111        if ( 'uniqselprotb-admin-script' === $handle ) {
     112            return str_replace( ' src', ' defer="defer" src', $tag );
     113        }
     114        return $tag;
     115    }
     116
     117    /**
     118     * Register menu
     119     *
     120     * @since     1.1.0
     121     *
     122     * @return void
     123     */
     124    public function uniqselprotb_register_menu() {
     125        add_menu_page(
     126            'Unique Selling Propositions',
     127            'Unique Selling Propositions',
     128            'manage_options',
     129            'uniqselprotb',
     130            array( $this, 'uniqselprotb_render_admin_page' ),
     131            'dashicons-star-filled'
     132        );
     133    }
     134
     135    /**
     136     * Render admin page.
     137     *
     138     * @since     1.1.0
     139     *
     140     * @return void
     141     */
     142    public function uniqselprotb_render_admin_page() {
     143        $options_settings = get_option( 'uniqselprotb_settings', array() );
     144
     145        if ( ! is_array( $options_settings ) ) {
     146            $options_settings = array();
     147        }
     148
     149        $icons = UNIQSELPROTB_Font_Awesome_Constant::ICONS_LIST;
     150
     151        $usps_value = array();
     152        $usps_icon  = array();
     153
     154        $usp_count = $this->get_usps_count( $options_settings );
     155
     156        for ( $i = 0; $i < $usp_count; $i++ ) {
     157            $usps_value[ 'usp_' . $i ] = $options_settings[ 'usp_' . $i ] ?? '';
     158            $usps_icon[ 'usp_' . $i ]  = $options_settings[ 'usp_icon_' . $i ] ?? $icons[ array_key_first( $icons ) ];
     159        }
     160
     161        $options_style = get_option( 'uniqselprotb_style', array() );
     162
     163        if ( ! is_array( $options_style ) ) {
     164            $options_style = array();
     165        }
     166
     167        $background_color = $options_style['background_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
     168        $text_color       = $options_style['text_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
     169
     170        $font_size           = $options_style['font_size'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
     171        $font_size_unit      = $options_style['font_size_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
     172        $font_weight         = $options_style['font_weight'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
     173        $font_style          = $options_style['font_style'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
     174        $padding_bottom      = $options_style['padding_bottom'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM;
     175        $padding_top         = $options_style['padding_top'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP;
     176        $padding_bottom_unit = $options_style['padding_bottom_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
     177        $padding_top_unit    = $options_style['padding_top_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
     178        $padding_left        = $options_style['padding_left'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT;
     179        $padding_right       = $options_style['padding_right'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT;
     180        $padding_left_unit   = $options_style['padding_left_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
     181        $padding_right_unit  = $options_style['padding_right_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
     182
     183        if ( 0 === $usp_count ) {
     184            $usp_count = 1;
     185        }
     186
     187        echo '<div class="wrap">';
     188
     189        require plugin_dir_path( __DIR__ ) . 'views/uniqselprotb-admin-nav-settings.php';
     190        require plugin_dir_path( __DIR__ ) . 'views/uniqselprotb-form-settings.php';
     191        require plugin_dir_path( __DIR__ ) . 'views/uniqselprotb-form-style.php';
     192
     193        echo '</div>';
     194    }
     195
     196    /**
     197     * Get the count of existing usps
     198     *
     199     * @param array $options_settings  The usps settings.
     200     * @return int
     201     */
     202    private function get_usps_count( array $options_settings ): int {
     203        $usp_count = 0;
     204
     205        foreach ( $options_settings as $key => $value ) {
     206            if ( str_starts_with( $key, 'usp_' ) && ! str_starts_with( $key, 'usp_icon_' ) ) {
     207                ++$usp_count;
     208            }
     209        }
     210        return $usp_count;
     211    }
     212
     213    /**
     214     * Settings Form Submission.
     215     *
     216     * @since     1.0.0
     217     *
     218     * @return void
     219     */
     220    public function uniqselprotb_save_settings_handler() {
     221
     222        $this->verify_user_permission();
     223
     224        if ( ! isset( $_POST['uniqselprotb_saving_settings_nonce'] ) ) {
     225            wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
     226        }
     227
     228        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['uniqselprotb_saving_settings_nonce'] ) ), 'uniqselprotb_saving_settings' ) ) {
     229            wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
     230        }
    207231
    208232        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
    209         $raw_inputs = isset( $_POST['uniqselprotb_settings'] ) ? wp_unslash( $_POST['uniqselprotb_settings'] ) : [];
    210 
    211         $sanitized_settings = [];
    212         $allowed_keys = UNIQSELPROTB_Plugin_Constant::ALLOWED_SETTINGS_FIELDS;
    213         foreach ( $raw_inputs as $key => $value ) {
    214             if ( in_array( $key, $allowed_keys, true ) ) {
    215                 $sanitized_settings[ $key ] = sanitize_text_field( $value );
    216             }
    217         }
    218 
    219         update_option( 'uniqselprotb_settings', $sanitized_settings );
    220 
    221         // Redirect after saving settings.
    222         $redirect_url = add_query_arg(
    223             [
    224                 'page'                          => UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG,
    225                 'uniqselprotb_settings_updated' => '1',
    226                 '_wpnonce'                      => wp_create_nonce( 'uniqselprotb_router_method' ),
    227             ],
    228             admin_url( 'admin.php' )
    229         );
    230 
    231         wp_safe_redirect( $redirect_url );
    232         exit;
    233     }
    234 
    235     /**
    236      * Style Form Submission
    237      *
    238      * @since     1.0.0
    239      * @since     1.1.0 Add new style attributes (font_size, font_size_unit, font_weight, font_style, padding_bottom, padding_top, padding_left, padding_right, padding_bottom_unit, padding_top_unit, padding_left_unit, padding_right_unit)
    240      *
    241      * @return void
    242      */
    243     public function uniqselprotb_save_style_handler() {
    244 
    245         $this->verify_user_permission();
    246 
    247         if ( ! isset( $_POST['uniqselprotb_saving_style_nonce'] ) ) {
    248             wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
    249         }
    250 
    251         if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['uniqselprotb_saving_style_nonce'] ) ), 'uniqselprotb_saving_style' ) ) {
    252             wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
    253         }
    254 
    255         $raw_styles = isset( $_POST['uniqselprotb_style'] ) && is_array( $_POST['uniqselprotb_style'] )
    256             ? wp_unslash( $_POST['uniqselprotb_style'] ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized per-item in loop
    257             : array();
    258 
    259         $sanitized_style = [];
    260         $allowed_keys = UNIQSELPROTB_Plugin_Constant::ALLOWED_STYLE_FIELDS;
    261 
    262         foreach ( $raw_styles as $key => $value ) {
    263             if ( in_array( $key, $allowed_keys, true ) ) {
    264 
    265                 if ( 'text_color' === $key ) {
    266                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
    267                     $sanitized_value = sanitize_hex_color( $value );
    268                 } else if ( 'background_color' === $key ) {
    269                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
    270                     $sanitized_value = sanitize_hex_color( $value );
    271                 } else if ( 'font_size' === $key ) {
    272                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
    273                     $sanitized_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE );
    274                 } else if ( 'font_size_unit' === $key ) {
    275                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
    276                     $sanitized_value = sanitize_text_field( $value );
    277                 } else if ( 'font_weight' === $key ) {
    278                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
    279                     $sanitized_value = sanitize_text_field( $value );
    280                 } else if ( 'font_style' === $key ) {
    281                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
    282                     $sanitized_value = sanitize_text_field( $value );
    283                 } else if ( 'padding_bottom' === $key ) {
    284                     $default_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM );
    285                     $sanitized_value = sanitize_text_field( $value );
    286                 } else if ( 'padding_top' === $key ) {
    287                     $default_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP );
    288                     $sanitized_value = sanitize_text_field( $value );
    289                 } else if ( 'padding_left' === $key ) {
    290                     $default_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT );
    291                     $sanitized_value = sanitize_text_field( $value );
    292                 } else if ( 'padding_right' === $key ) {
    293                     $default_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT );
    294                     $sanitized_value = sanitize_text_field( $value );
    295                 } else if ( 'padding_bottom_unit' === $key ) {
    296                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
    297                     $sanitized_value = sanitize_text_field( $value );
    298                 } else if ( 'padding_top_unit' === $key ) {
    299                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
    300                     $sanitized_value = sanitize_text_field( $value );
    301                 } else if ( 'padding_left_unit' === $key ) {
    302                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
    303                     $sanitized_value = sanitize_text_field( $value );
    304                 } else if ( 'padding_right_unit' === $key ) {
    305                     $default_value = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
    306                     $sanitized_value = sanitize_text_field( $value );
    307                 }
    308                 $sanitized_style[ $key ] = $sanitized_value ?? $default_value;
    309             }
    310         }
    311 
    312         update_option( 'uniqselprotb_style', $sanitized_style );
    313 
    314         $redirect_url = add_query_arg(
    315             [
    316                 'page'                        => UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG,
    317                 'uniqselprotb_style_updated' => '1',
    318                 '_wpnonce'                   => wp_create_nonce( 'uniqselprotb_router_method' ),
    319             ],
    320             admin_url( 'admin.php' )
    321         );
    322 
    323         wp_safe_redirect( $redirect_url );
    324         exit;
    325     }
    326 
    327     /**
    328      * Sanitize decimal.
    329      *
    330      * @since     1.1.0
    331      *
    332      * @param $value
    333      * @param $default_value
    334      * @return float|mixed
    335      */
    336     private function uniqselprotb_sanitize_decimal($value, $default_value): mixed
    337     {
    338         if (!is_numeric($value)) {
    339             return $default_value;
    340         }
    341         return floatval($value);
    342     }
    343 
    344     /**
    345      * Verify if the user has permission.
    346      *
    347      * @since     1.1.0
    348      *
    349      * @return void
    350      */
    351     private function verify_user_permission(): void {
    352         if ( ! current_user_can( 'manage_options' ) ) {
    353             wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
    354         }
    355     }
     233        $raw_inputs = isset( $_POST['uniqselprotb_settings'] ) ? wp_unslash( $_POST['uniqselprotb_settings'] ) : array();
     234
     235        $this->remove_empty_usps( $raw_inputs );
     236
     237        $sanitized_settings = array();
     238        foreach ( $raw_inputs as $key => $value ) {
     239            if ( str_starts_with( $key, 'usp_' ) ) {
     240                $sanitized_settings[ $key ] = sanitize_text_field( $value );
     241            }
     242        }
     243
     244        update_option( 'uniqselprotb_settings', $sanitized_settings );
     245
     246        // Redirect after saving settings.
     247        $redirect_url = add_query_arg(
     248            array(
     249                'page'                          => UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG,
     250                'uniqselprotb_settings_updated' => '1',
     251                '_wpnonce'                      => wp_create_nonce( 'uniqselprotb_router_method' ),
     252            ),
     253            admin_url( 'admin.php' )
     254        );
     255
     256        wp_safe_redirect( $redirect_url );
     257        exit;
     258    }
     259
     260    /**
     261     * Removes empty USP entries and their associated icons from the input array.
     262     *
     263     * @param array $raw_inputs Array of raw USP input values keyed by field name.
     264     * @return void
     265     */
     266    private function remove_empty_usps( array $raw_inputs ): void {
     267        foreach ( $raw_inputs as $key => $value ) {
     268            if ( str_starts_with( $key, 'usp_' ) && ! str_starts_with( $key, 'usp_icon_' ) ) {
     269                if ( '' === $value ) {
     270                    $exploded_key = explode( '_', $key );
     271                    unset( $raw_inputs[ $key ] );
     272                    unset( $raw_inputs[ 'usp_icon_' . $exploded_key[1] ] );
     273                }
     274            }
     275        }
     276    }
     277
     278    /**
     279     * Style Form Submission
     280     *
     281     * @since     1.0.0
     282     * @since     1.1.0 Add new style attributes (font_size, font_size_unit, font_weight, font_style, padding_bottom, padding_top, padding_left, padding_right, padding_bottom_unit, padding_top_unit, padding_left_unit, padding_right_unit)
     283     *
     284     * @return void
     285     */
     286    public function uniqselprotb_save_style_handler() {
     287
     288        $this->verify_user_permission();
     289
     290        if ( ! isset( $_POST['uniqselprotb_saving_style_nonce'] ) ) {
     291            wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
     292        }
     293
     294        if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['uniqselprotb_saving_style_nonce'] ) ), 'uniqselprotb_saving_style' ) ) {
     295            wp_die( esc_html__( 'Something went wrong. Please try again.', 'uniqselprotb' ) );
     296        }
     297
     298        $raw_styles = isset( $_POST['uniqselprotb_style'] ) && is_array( $_POST['uniqselprotb_style'] )
     299            ? wp_unslash( $_POST['uniqselprotb_style'] ) // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized per-item in loop
     300            : array();
     301
     302        $sanitized_style = array();
     303        $allowed_keys    = UNIQSELPROTB_Plugin_Constant::ALLOWED_STYLE_FIELDS;
     304
     305        foreach ( $raw_styles as $key => $value ) {
     306            if ( in_array( $key, $allowed_keys, true ) ) {
     307
     308                if ( 'text_color' === $key ) {
     309                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
     310                    $sanitized_value = sanitize_hex_color( $value );
     311                } elseif ( 'background_color' === $key ) {
     312                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
     313                    $sanitized_value = sanitize_hex_color( $value );
     314                } elseif ( 'font_size' === $key ) {
     315                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
     316                    $sanitized_value = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE );
     317                } elseif ( 'font_size_unit' === $key ) {
     318                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
     319                    $sanitized_value = sanitize_text_field( $value );
     320                } elseif ( 'font_weight' === $key ) {
     321                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
     322                    $sanitized_value = sanitize_text_field( $value );
     323                } elseif ( 'font_style' === $key ) {
     324                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
     325                    $sanitized_value = sanitize_text_field( $value );
     326                } elseif ( 'padding_bottom' === $key ) {
     327                    $default_value   = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM );
     328                    $sanitized_value = sanitize_text_field( $value );
     329                } elseif ( 'padding_top' === $key ) {
     330                    $default_value   = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP );
     331                    $sanitized_value = sanitize_text_field( $value );
     332                } elseif ( 'padding_left' === $key ) {
     333                    $default_value   = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT );
     334                    $sanitized_value = sanitize_text_field( $value );
     335                } elseif ( 'padding_right' === $key ) {
     336                    $default_value   = $this->uniqselprotb_sanitize_decimal( $value, UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT );
     337                    $sanitized_value = sanitize_text_field( $value );
     338                } elseif ( 'padding_bottom_unit' === $key ) {
     339                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
     340                    $sanitized_value = sanitize_text_field( $value );
     341                } elseif ( 'padding_top_unit' === $key ) {
     342                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
     343                    $sanitized_value = sanitize_text_field( $value );
     344                } elseif ( 'padding_left_unit' === $key ) {
     345                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
     346                    $sanitized_value = sanitize_text_field( $value );
     347                } elseif ( 'padding_right_unit' === $key ) {
     348                    $default_value   = UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
     349                    $sanitized_value = sanitize_text_field( $value );
     350                }
     351                $sanitized_style[ $key ] = $sanitized_value ?? $default_value;
     352            }
     353        }
     354
     355        update_option( 'uniqselprotb_style', $sanitized_style );
     356
     357        $redirect_url = add_query_arg(
     358            array(
     359                'page'                       => UNIQSELPROTB_Plugin_Constant::PLUGIN_SLUG,
     360                'uniqselprotb_style_updated' => '1',
     361                '_wpnonce'                   => wp_create_nonce( 'uniqselprotb_router_method' ),
     362            ),
     363            admin_url( 'admin.php' )
     364        );
     365
     366        wp_safe_redirect( $redirect_url );
     367        exit;
     368    }
     369
     370    /**
     371     * Sanitizes a decimal value by ensuring it's numeric and converting it to float.
     372     *
     373     * @param string|int $value The value to sanitize.
     374     * @param string|int $default_value The fallback value to return if $value is not numeric.
     375     *
     376     * @return string|int|float Sanitized decimal value as float, or the default if invalid.
     377     * @since     1.1.0
     378     */
     379    private function uniqselprotb_sanitize_decimal( string|int $value, string|int $default_value ): string|int|float {
     380        if ( ! is_numeric( $value ) ) {
     381            return $default_value;
     382        }
     383        return floatval( $value );
     384    }
     385
     386    /**
     387     * Verify if the user has permission.
     388     *
     389     * @since     1.1.0
     390     *
     391     * @return void
     392     */
     393    private function verify_user_permission(): void {
     394        if ( ! current_user_can( 'manage_options' ) ) {
     395            wp_die( esc_html__( 'Something went wrong. Please try again later.', 'uniqselprotb' ) );
     396        }
     397    }
    356398}
  • uniqselprotb/trunk/includes/controllers/class-uniqselprotb-frontend-controller.php

    r3329172 r3357146  
    1313
    1414if ( ! defined( 'ABSPATH' ) ) {
    15     exit;
     15    exit;
    1616}
    1717
     
    2121class UNIQSELPROTB_Frontend_Controller {
    2222
    23     /**
    24      * The available languages of the installation
    25      *
    26      * @var array
    27      */
    28     private array $available_languages;
    29 
    30     /**
    31      * @since 1.1.0
    32      */
    33     public function __construct()
    34     {
    35         require_once plugin_dir_path(__DIR__) . 'constants/class-uniqselprotb-plugin-constant.php';
    36     }
    37 
    38     /**
    39      * Register assets of plugins
    40      *
    41      * @since 1.1.0
    42      *
    43      * @return void
    44      */
    45     public function uniqselprotb_register_frontend_assets() {
    46 
    47         // Enqueue Font Awesome if not already loaded
    48         if ( ! wp_style_is( 'font-awesome-6', 'enqueued' ) ) {
    49             wp_enqueue_style(
    50                 'font-awesome-6',
    51                 UNIQSELPROTB_PLUGIN_URL . 'assets/font-awesome/css/all.min.css',
    52                 [],
    53                 '6.7.2'
    54             );
    55         }
    56 
    57         // Register and enqueue frontend style
    58         wp_register_style(
    59             'uniqselprotb-frontend-style',
    60             UNIQSELPROTB_PLUGIN_URL . 'assets/css/uniqselprotb.css',
    61             [],
    62             '1.1.0',
    63             'all'
    64         );
    65         wp_enqueue_style( 'uniqselprotb-frontend-style' );
    66 
    67         // Register and enqueue frontend script
    68         if ( version_compare( get_bloginfo( 'version' ), '6.3', '>=' ) ) {
    69             wp_register_script(
    70                 'uniqselprotb-frontend-script',
    71                 UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-frontend.js',
    72                 [ 'jquery' ],
    73                 '1.1.0',
    74                 array( 'strategy' => 'defer' )
    75             );
    76         } else {
    77             wp_register_script(
    78                 'uniqselprotb-frontend-script',
    79                 UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-frontend.js',
    80                 [ 'jquery' ],
    81                 '1.1.0',
    82                 true
    83             );
    84             // Add defer attribute manually for WP < 6.3
    85             add_filter( 'script_loader_tag', [ $this, 'add_defer_attribute' ], 10, 2 );
    86         }
    87 
    88         wp_enqueue_script( 'uniqselprotb-frontend-script' );
    89 
    90         // Add inline styles dynamically
    91         $this->uniqselprotb_add_inline_styles();
    92     }
    93 
    94     /**
    95      * Add inline style
    96      *
    97      * @since 1.1.0
    98      *
    99      * @return void
    100      */
    101     public function uniqselprotb_add_inline_styles() {
    102         $style_options    = $this->uniqselprotb_get_style_options();
    103         $background_color = esc_attr( $this->uniqselprotb_get_background_color( $style_options ) );
    104         $text_color       = esc_attr( $this->uniqselprotb_get_text_color( $style_options ) );
    105         $font_size = esc_attr( $this->uniqselprotb_get_font_size( $style_options ) );
    106         $font_size_unit =  esc_attr( $this->uniqselprotb_get_font_size_unit( $style_options ) );
    107         $font_weight = esc_attr( $this->uniqselprotb_get_font_weight( $style_options ) );
    108         $font_style = esc_attr( $this->uniqselprotb_get_font_style( $style_options ) );
    109         $padding_bottom = esc_attr( $this->uniqselprotb_get_padding_bottom( $style_options ) );
    110         $padding_top = esc_attr( $this->uniqselprotb_get_padding_top( $style_options ) );
    111         $padding_left = esc_attr( $this->uniqselprotb_get_padding_left( $style_options ) );
    112         $padding_right = esc_attr( $this->uniqselprotb_get_padding_right( $style_options ) );
    113         $padding_bottom_unit = esc_attr( $this->uniqselprotb_get_padding_bottom_unit( $style_options ) );
    114         $padding_top_unit = esc_attr( $this->uniqselprotb_get_padding_top_unit( $style_options ) );
    115         $padding_left_unit = esc_attr( $this->uniqselprotb_get_padding_left_unit( $style_options ) );
    116         $padding_right_unit = esc_attr( $this->uniqselprotb_get_padding_right_unit( $style_options ) );
    117 
    118         $custom_css = "
     23    /**
     24     * The available languages of the installation
     25     *
     26     * @var array
     27     */
     28    private array $available_languages;
     29
     30    /**
     31     * The construct of the class
     32     *
     33     * @since 1.1.0
     34     */
     35    public function __construct() {
     36        require_once plugin_dir_path( __DIR__ ) . 'constants/class-uniqselprotb-plugin-constant.php';
     37    }
     38
     39    /**
     40     * Register assets of plugins
     41     *
     42     * @since 1.1.0
     43     *
     44     * @return void
     45     */
     46    public function uniqselprotb_register_frontend_assets() {
     47
     48        // Enqueue Font Awesome if not already loaded.
     49        if ( ! wp_style_is( 'font-awesome-6', 'enqueued' ) ) {
     50            wp_enqueue_style(
     51                'font-awesome-6',
     52                UNIQSELPROTB_PLUGIN_URL . 'assets/font-awesome/css/all.min.css',
     53                array(),
     54                '6.7.2'
     55            );
     56        }
     57
     58        // Register and enqueue frontend style.
     59        wp_register_style(
     60            'uniqselprotb-frontend-style',
     61            UNIQSELPROTB_PLUGIN_URL . 'assets/css/uniqselprotb.css',
     62            array(),
     63            '1.1.0',
     64            'all'
     65        );
     66        wp_enqueue_style( 'uniqselprotb-frontend-style' );
     67
     68        // Register and enqueue frontend script.
     69        if ( version_compare( get_bloginfo( 'version' ), '6.3', '>=' ) ) {
     70            wp_register_script(
     71                'uniqselprotb-frontend-script',
     72                UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-frontend.js',
     73                array( 'jquery' ),
     74                '1.1.0',
     75                array( 'strategy' => 'defer' )
     76            );
     77        } else {
     78            wp_register_script(
     79                'uniqselprotb-frontend-script',
     80                UNIQSELPROTB_PLUGIN_URL . 'assets/js/uniqselprotb-frontend.js',
     81                array( 'jquery' ),
     82                '1.1.0',
     83                true
     84            );
     85            // Add defer attribute manually for WP < 6.3.
     86            add_filter( 'script_loader_tag', array( $this, 'add_defer_attribute' ), 10, 2 );
     87        }
     88
     89        wp_enqueue_script( 'uniqselprotb-frontend-script' );
     90
     91        // Add inline styles dynamically.
     92        $this->uniqselprotb_add_inline_styles();
     93    }
     94
     95    /**
     96     * Add inline style
     97     *
     98     * @since 1.1.0
     99     *
     100     * @return void
     101     */
     102    public function uniqselprotb_add_inline_styles() {
     103        $style_options       = $this->uniqselprotb_get_style_options();
     104        $background_color    = esc_attr( $this->uniqselprotb_get_background_color( $style_options ) );
     105        $text_color          = esc_attr( $this->uniqselprotb_get_text_color( $style_options ) );
     106        $font_size           = esc_attr( $this->uniqselprotb_get_font_size( $style_options ) );
     107        $font_size_unit      = esc_attr( $this->uniqselprotb_get_font_size_unit( $style_options ) );
     108        $font_weight         = esc_attr( $this->uniqselprotb_get_font_weight( $style_options ) );
     109        $font_style          = esc_attr( $this->uniqselprotb_get_font_style( $style_options ) );
     110        $padding_bottom      = esc_attr( $this->uniqselprotb_get_padding_bottom( $style_options ) );
     111        $padding_top         = esc_attr( $this->uniqselprotb_get_padding_top( $style_options ) );
     112        $padding_left        = esc_attr( $this->uniqselprotb_get_padding_left( $style_options ) );
     113        $padding_right       = esc_attr( $this->uniqselprotb_get_padding_right( $style_options ) );
     114        $padding_bottom_unit = esc_attr( $this->uniqselprotb_get_padding_bottom_unit( $style_options ) );
     115        $padding_top_unit    = esc_attr( $this->uniqselprotb_get_padding_top_unit( $style_options ) );
     116        $padding_left_unit   = esc_attr( $this->uniqselprotb_get_padding_left_unit( $style_options ) );
     117        $padding_right_unit  = esc_attr( $this->uniqselprotb_get_padding_right_unit( $style_options ) );
     118
     119        $custom_css = "
    119120            .usps-top-banner {
    120121                background-color: {$background_color};
     
    138139        ";
    139140
    140         wp_add_inline_style( 'uniqselprotb-frontend-style', $custom_css );
    141     }
    142 
    143     /**
    144      * Get style options
    145      *
    146      * @since 1.1.0
    147      *
    148      * @return mixed
    149      */
    150     private function uniqselprotb_get_style_options(): mixed {
    151         return get_option( 'uniqselprotb_style', array() );
    152     }
    153 
    154     /**
    155      * Get background color
    156      *
    157      * @since 1.1.0
    158      *
    159      * @param array $style_options  Style options.
    160      * @return string
    161      */
    162     private function uniqselprotb_get_background_color( array $style_options ): string {
    163         return $style_options['background_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
    164     }
    165 
    166     /**
    167      * Get text color
    168      *
    169      * @since 1.1.0
    170      *
    171      * @param array $style_options  Style options.
    172      * @return string
    173      */
    174     private function uniqselprotb_get_text_color( array $style_options ): string {
    175         return $style_options['text_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
    176     }
    177 
    178     /**
    179      * Get font size
    180      *
    181      * @since 1.1.0
    182      *
    183      * @param array $style_options
    184      * @return string
    185      */
    186     private function uniqselprotb_get_font_size( array $style_options ): string {
    187         return $style_options['font_size'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
    188     }
    189 
    190     /**
    191      * Get font size unit
    192      *
    193      * @since 1.1.0
    194      *
    195      * @param array $style_options
    196      * @return string
    197      */
    198     private function uniqselprotb_get_font_size_unit( array $style_options ): string {
    199         return $style_options['font_size_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
    200     }
    201 
    202     /**
    203      * Get font weight
    204      *
    205      * @since 1.1.0
    206      *
    207      * @param array $style_options
    208      * @return string
    209      */
    210     private function uniqselprotb_get_font_weight( array $style_options ): string {
    211         return $style_options['font_weight'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
    212     }
    213 
    214     /**
    215      * Get font style
    216      *
    217      * @since 1.1.0
    218      *
    219      * @param array $style_options
    220      * @return string
    221      */
    222     private function uniqselprotb_get_font_style( array $style_options ): string {
    223         return $style_options['font_style'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
    224     }
    225 
    226     /**
    227      * Get padding bottom
    228      *
    229      * @since 1.1.0
    230      *
    231      * @param array $style_options
    232      * @return string
    233      */
    234     private function uniqselprotb_get_padding_bottom( array $style_options ): string {
    235         return $style_options['padding_bottom'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM;
    236     }
    237 
    238     /**
    239      * Get padding bottom unit
    240      *
    241      * @since 1.1.0
    242      *
    243      * @param array $style_options
    244      * @return string
    245      */
    246     private function uniqselprotb_get_padding_bottom_unit( array $style_options ): string {
    247         return $style_options['padding_bottom_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
    248     }
    249 
    250     /**
    251      * Get padding top
    252      *
    253      * @since 1.1.0
    254      *
    255      * @param array $style_options
    256      * @return string
    257      */
    258     private function uniqselprotb_get_padding_top( array $style_options ): string {
    259         return $style_options['padding_top'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP;
    260     }
    261 
    262     /**
    263      * Get padding left
    264      *
    265      * @since 1.1.0
    266      *
    267      * @param array $style_options
    268      * @return string
    269      */
    270     private function uniqselprotb_get_padding_left( array $style_options ): string {
    271         return $style_options['padding_left'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT;
    272     }
    273 
    274     /**
    275      * Get padding right
    276      *
    277      * @since 1.1.0
    278      *
    279      * @param array $style_options
    280      * @return string
    281      */
    282     private function uniqselprotb_get_padding_right( array $style_options ): string {
    283         return $style_options['padding_right'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT;
    284     }
    285 
    286     /**
    287      * Get padding top unit
    288      *
    289      * @since 1.1.0
    290      *
    291      * @param array $style_options
    292      * @return string
    293      */
    294     private function uniqselprotb_get_padding_top_unit( array $style_options ): string {
    295         return $style_options['padding_top_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
    296     }
    297 
    298     /**
    299      * Get padding left unit
    300      *
    301      * @since 1.1.0
    302      *
    303      * @param array $style_options
    304      * @return string
    305      */
    306     private function uniqselprotb_get_padding_left_unit( array $style_options ): string {
    307         return $style_options['padding_left_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
    308     }
    309 
    310     /**
    311      * Get padding right unit
    312      *
    313      * @since 1.1.0
    314      *
    315      * @param array $style_options
    316      * @return string
    317      */
    318     private function uniqselprotb_get_padding_right_unit( array $style_options ): string {
    319         return $style_options['padding_right_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
    320     }
    321 
    322     /**
    323      * Adding 'defer' attribute for WordPress < 6.3
    324      *
    325      * @since 1.1.0
    326      *
    327      * @param string $tag    The HTML script tag.
    328      * @param string $handle The script handle.
    329      * @return string Modified script tag with 'defer', or original tag.
    330      */
    331     public function add_defer_attribute( string $tag, string $handle ): string {
    332         /* Check if this is the script handle you want to apply 'defer' to */
    333         if ( 'uniqselprotb-frontend-script' === $handle ) {
    334             return str_replace( ' src', ' defer="defer" src', $tag );
    335         }
    336         return $tag;
    337     }
    338 
    339     /**
    340      * Render the usps top banner.
    341      *
    342      * @since 1.0.0
    343      * @since 1.1.0 Fix support displaying fewer than three USPs
    344      *
    345      * @return void
    346      */
    347     public function uniqselprotb_render_banner(): void {
    348         $current_locale   = get_locale();
    349         $current_language = $this->uniqselprotb_get_current_language( $current_locale );
    350 
    351         $usps    = array();
    352         $options = get_option( 'uniqselprotb_settings', array() );
    353 
    354         if ( ! is_array( $options ) ) {
    355             $options = array();
    356         }
    357 
    358         if ( ! empty( $options ) ) {
    359             $usps[ $current_language ] = $this->uniqselprotb_build_unique_selling_propositions_by_options( $options );
    360         }
    361 
    362         $current_usps = $usps[ $current_language ] ?? [];
    363 
    364         if ( ! empty( $current_usps ) ) {
    365             $usp_count = count( $current_usps['usps'] );
    366 
    367             $html       = '<div class="usps-top-banner header-usps">';
    368             $html      .= '<div class="header-usps-column column-center full-width">';
    369 
    370             $class_rtl = is_rtl() ? 'rtl' : '';
    371 
    372 
    373             for ( $i = 0; $i < $usp_count; $i++ ) {
    374                 if ( !empty($current_usps['usps'][ $i ]) ) {
    375                     $raw_classes = $current_usps['icons'][$i];
    376                     $classes_array = explode(' ', $raw_classes);
    377                     $sanitized_classes = array_map('sanitize_html_class', $classes_array);
    378                     $final_class_string = implode(' ', $sanitized_classes);
    379 
    380                     $html .= '<span class="usp-item item"><i class="' . esc_attr($final_class_string) . '"></i>';
    381 
    382                     $html .= '<span' . ($class_rtl ? ' class="' . esc_attr($class_rtl) . '"' : '') . '>' . esc_html($current_usps['usps'][$i]) . '</span>';
    383 
    384                     $html .= '</span>';
    385                 }
    386             }
    387 
    388             $html .= '</div>';
    389             $html .= '</div>';
    390 
    391             echo wp_kses(
    392                 $html,
    393                 array(
    394                     'div'  => array(
    395                         'class' => array(),
    396                     ),
    397                     'i'    => array(
    398                         'class' => array(),
    399                     ),
    400                     'span' => array(
    401                         'class' => array(),
    402                     ),
    403                 )
    404             );
    405         }
    406     }
    407 
    408     /**
    409      * Build the unique selling propositions markup based on given style and content options.
    410      *
    411      * @since 1.0.0
    412      *
    413      * @param array $options options  Array of options (e.g., usps, icons).
    414      * @return array
    415      */
    416     private function uniqselprotb_build_unique_selling_propositions_by_options( array $options ): array {
    417         return array(
    418             'usps'  => array(
    419                 $options['usp_0'] ?? '',
    420                 $options['usp_1'] ?? '',
    421                 $options['usp_2'] ?? '',
    422             ),
    423             'icons' => array(
    424                 $options['usp_icon_0'] ?? '',
    425                 $options['usp_icon_1'] ?? '',
    426                 $options['usp_icon_2'] ?? '',
    427             ),
    428         );
    429     }
    430 
    431     /**
    432      * Get the current language
    433      *
    434      * since 1.0.0
    435      *
    436      * @param  string $current_locale The current language.
    437      * @return string
    438      */
    439     private function uniqselprotb_get_current_language( string $current_locale ): string {
    440         return substr( $current_locale, 0, 2 );
    441     }
     141        wp_add_inline_style( 'uniqselprotb-frontend-style', $custom_css );
     142    }
     143
     144    /**
     145     * Get style options
     146     *
     147     * @since 1.1.0
     148     *
     149     * @return mixed
     150     */
     151    private function uniqselprotb_get_style_options(): mixed {
     152        return get_option( 'uniqselprotb_style', array() );
     153    }
     154
     155    /**
     156     * Get background color
     157     *
     158     * @since 1.1.0
     159     *
     160     * @param array $style_options  Style options.
     161     * @return string
     162     */
     163    private function uniqselprotb_get_background_color( array $style_options ): string {
     164        return $style_options['background_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_BACKGROUND_COLOR;
     165    }
     166
     167    /**
     168     * Get text color
     169     *
     170     * @since 1.1.0
     171     *
     172     * @param array $style_options  Style options.
     173     * @return string
     174     */
     175    private function uniqselprotb_get_text_color( array $style_options ): string {
     176        return $style_options['text_color'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_TEXT_COLOR;
     177    }
     178
     179    /**
     180     * Get font size
     181     *
     182     * @since 1.1.0
     183     *
     184     * @param array $style_options The style settings of the usps.
     185     *
     186     * @return string
     187     */
     188    private function uniqselprotb_get_font_size( array $style_options ): string {
     189        return $style_options['font_size'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE;
     190    }
     191
     192    /**
     193     * Get font size unit
     194     *
     195     * @since 1.1.0
     196     *
     197     * @param array $style_options The style settings of the usps.
     198     *
     199     * @return string
     200     */
     201    private function uniqselprotb_get_font_size_unit( array $style_options ): string {
     202        return $style_options['font_size_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_SIZE_UNIT;
     203    }
     204
     205    /**
     206     * Get font weight
     207     *
     208     * @since 1.1.0
     209     *
     210     * @param array $style_options The style settings of the usps.
     211     *
     212     * @return string
     213     */
     214    private function uniqselprotb_get_font_weight( array $style_options ): string {
     215        return $style_options['font_weight'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_WEIGHT;
     216    }
     217
     218    /**
     219     * Get font style
     220     *
     221     * @since 1.1.0
     222     *
     223     * @param array $style_options The style settings of the usps.
     224     *
     225     * @return string
     226     */
     227    private function uniqselprotb_get_font_style( array $style_options ): string {
     228        return $style_options['font_style'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_FONT_STYLE;
     229    }
     230
     231    /**
     232     * Get padding bottom
     233     *
     234     * @since 1.1.0
     235     *
     236     * @param array $style_options The style settings of the usps.
     237     *
     238     * @return string
     239     */
     240    private function uniqselprotb_get_padding_bottom( array $style_options ): string {
     241        return $style_options['padding_bottom'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM;
     242    }
     243
     244    /**
     245     * Get padding bottom unit
     246     *
     247     * @since 1.1.0
     248     *
     249     * @param array $style_options The style settings of the usps.
     250     *
     251     * @return string
     252     */
     253    private function uniqselprotb_get_padding_bottom_unit( array $style_options ): string {
     254        return $style_options['padding_bottom_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_BOTTOM_UNIT;
     255    }
     256
     257    /**
     258     * Get padding top
     259     *
     260     * @since 1.1.0
     261     *
     262     * @param array $style_options The style settings of the usps.
     263     *
     264     * @return string
     265     */
     266    private function uniqselprotb_get_padding_top( array $style_options ): string {
     267        return $style_options['padding_top'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP;
     268    }
     269
     270    /**
     271     * Get padding left
     272     *
     273     * @since 1.1.0
     274     *
     275     * @param array $style_options The style settings of the usps.
     276     * @return string
     277     */
     278    private function uniqselprotb_get_padding_left( array $style_options ): string {
     279        return $style_options['padding_left'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT;
     280    }
     281
     282    /**
     283     * Get padding right
     284     *
     285     * @since 1.1.0
     286     *
     287     * @param array $style_options The style settings of the usps.
     288     *
     289     * @return string
     290     */
     291    private function uniqselprotb_get_padding_right( array $style_options ): string {
     292        return $style_options['padding_right'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT;
     293    }
     294
     295    /**
     296     * Get padding top unit
     297     *
     298     * @since 1.1.0
     299     *
     300     * @param array $style_options The style settings of the usps.
     301     * @return string
     302     */
     303    private function uniqselprotb_get_padding_top_unit( array $style_options ): string {
     304        return $style_options['padding_top_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_TOP_UNIT;
     305    }
     306
     307    /**
     308     * Get padding left unit
     309     *
     310     * @since 1.1.0
     311     *
     312     * @param array $style_options The style settings of the usps.
     313     * @return string
     314     */
     315    private function uniqselprotb_get_padding_left_unit( array $style_options ): string {
     316        return $style_options['padding_left_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_LEFT_UNIT;
     317    }
     318
     319    /**
     320     * Get padding right unit
     321     *
     322     * @since 1.1.0
     323     *
     324     * @param array $style_options The style settings of the usps.
     325     * @return string
     326     */
     327    private function uniqselprotb_get_padding_right_unit( array $style_options ): string {
     328        return $style_options['padding_right_unit'] ?? UNIQSELPROTB_Plugin_Constant::DEFAULT_PADDING_RIGHT_UNIT;
     329    }
     330
     331    /**
     332     * Adding 'defer' attribute for WordPress < 6.3
     333     *
     334     * @since 1.1.0
     335     *
     336     * @param string $tag    The HTML script tag.
     337     * @param string $handle The script handle.
     338     * @return string Modified script tag with 'defer', or original tag.
     339     */
     340    public function add_defer_attribute( string $tag, string $handle ): string {
     341        /* Check if this is the script handle you want to apply 'defer' to */
     342        if ( 'uniqselprotb-frontend-script' === $handle ) {
     343            return str_replace( ' src', ' defer="defer" src', $tag );
     344        }
     345        return $tag;
     346    }
     347
     348    /**
     349     * Render the usps top banner.
     350     *
     351     * @since 1.0.0
     352     * @since 1.1.0 Fix support displaying fewer than three USPs
     353     *
     354     * @return void
     355     */
     356    public function uniqselprotb_render_banner(): void {
     357        $current_locale   = get_locale();
     358        $current_language = $this->uniqselprotb_get_current_language( $current_locale );
     359
     360        $usps    = array();
     361        $options = get_option( 'uniqselprotb_settings', array() );
     362
     363        if ( ! is_array( $options ) ) {
     364            $options = array();
     365        }
     366
     367        if ( ! empty( $options ) ) {
     368            $usps[ $current_language ] = $this->uniqselprotb_build_unique_selling_propositions_by_options( $options );
     369        }
     370
     371        $current_usps = $usps[ $current_language ] ?? array();
     372
     373        if ( ! empty( $current_usps ) ) {
     374            $usp_count = count( $current_usps['usps'] );
     375
     376            $html  = '<div class="usps-top-banner header-usps">';
     377            $html .= '<div class="header-usps-column column-center full-width">';
     378
     379            $class_rtl = is_rtl() ? 'rtl' : '';
     380
     381            for ( $i = 0; $i < $usp_count; $i++ ) {
     382                if ( ! empty( $current_usps['usps'][ $i ] ) ) {
     383                    $raw_classes        = $current_usps['icons'][ $i ];
     384                    $classes_array      = explode( ' ', $raw_classes );
     385                    $sanitized_classes  = array_map( 'sanitize_html_class', $classes_array );
     386                    $final_class_string = implode( ' ', $sanitized_classes );
     387
     388                    $html .= '<span class="usp-item item"><i class="' . esc_attr( $final_class_string ) . '"></i>';
     389
     390                    $html .= '<span' . ( $class_rtl ? ' class="' . esc_attr( $class_rtl ) . '"' : '' ) . '>' . esc_html( $current_usps['usps'][ $i ] ) . '</span>';
     391
     392                    $html .= '</span>';
     393                }
     394            }
     395
     396            $html .= '</div>';
     397            $html .= '</div>';
     398
     399            echo wp_kses(
     400                $html,
     401                array(
     402                    'div'  => array(
     403                        'class' => array(),
     404                    ),
     405                    'i'    => array(
     406                        'class' => array(),
     407                    ),
     408                    'span' => array(
     409                        'class' => array(),
     410                    ),
     411                )
     412            );
     413        }
     414    }
     415
     416    /**
     417     * Build the unique selling propositions markup based on given style and content options.
     418     *
     419     * @since 1.0.0
     420     *
     421     * @param array $options options  Array of options (e.g., usps, icons).
     422     * @return array
     423     */
     424    private function uniqselprotb_build_unique_selling_propositions_by_options( array $options ): array {
     425
     426        $usps       = array();
     427        $usps_icons = array();
     428        foreach ( $options as $key => $value ) {
     429            if ( str_starts_with( $key, 'usp_' ) && ! str_starts_with( $key, 'usp_icon_' ) ) {
     430                $usps[] = $value ?? '';
     431            } elseif ( str_starts_with( $key, 'usp_icon_' ) ) {
     432                $usps_icons[] = $value ?? '';
     433            }
     434        }
     435
     436        return array(
     437            'usps'  => $usps,
     438            'icons' => $usps_icons,
     439        );
     440    }
     441
     442    /**
     443     * Get the current language
     444     *
     445     * Since 1.0.0
     446     *
     447     * @param  string $current_locale The current language.
     448     * @return string
     449     */
     450    private function uniqselprotb_get_current_language( string $current_locale ): string {
     451        return substr( $current_locale, 0, 2 );
     452    }
    442453}
  • uniqselprotb/trunk/includes/views/uniqselprotb-admin-nav-settings.php

    r3329159 r3357146  
    1313
    1414if ( ! defined( 'ABSPATH' ) ) {
    15     exit;
     15    exit;
    1616}
    1717
     
    2222<!-- Tabs -->
    2323<div class="nav-tab-wrapper">
    24     <a href="#form-settings" class="nav-tab nav-tab-active">USPs</a>
    25     <a href="#form-style" class="nav-tab">Style</a>
    26     <input type="hidden" value="false" id="is-multilang">
     24    <a href="#form-settings" class="nav-tab nav-tab-active">USPs</a>
     25    <a href="#form-style" class="nav-tab">Style</a>
     26    <input type="hidden" value="false" id="is-multilang">
    2727</div>
  • uniqselprotb/trunk/includes/views/uniqselprotb-form-settings.php

    r3329159 r3357146  
    1515
    1616/**
     17 * View for form settings in admin panel
     18 *
    1719 * @var array $usps_value
    1820 * @var array $usps_icon
    1921 * @var array $icons
     22 * @var int $usp_count
    2023 */
    2124if ( ! defined( 'ABSPATH' ) ) {
    22     exit;
     25    exit;
    2326}
    2427
     
    2831?>
    2932<div class="wrap">
    30     <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="form-settings" id="form-settings">
    31         <?php wp_nonce_field( UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_ACTION, UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ); ?>
     33    <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="form-settings" id="form-settings">
     34        <?php wp_nonce_field( UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_ACTION, UNIQSELPROTB_Plugin_Constant::NONCE_SETTINGS_FIELD ); ?>
    3235
    33         <!-- Custom action and nonce fields -->
    34         <input type="hidden" name="action" value="uniqselprotb_saving_settings">
     36        <!-- Custom action and nonce fields -->
     37        <input type="hidden" name="action" value="uniqselprotb_saving_settings">
    3538
    36         <div id="tab-usps" class="tab-content">
    37             <h3 id="h3-style">USPs</h3>
    38             <p>Configure your Unique Selling Propositions to be displayed in the top banner.</p>
     39        <div id="tab-usps" class="tab-content">
     40            <h3 id="h3-style">USPs</h3>
     41            <p>Configure your Unique Selling Propositions to be displayed in the top banner.</p>
    3942
    40             <div class="container-table">
    41                 <table class="form-table form-table-settings">
     43            <div class="container-table">
     44                <table class="form-table form-table-settings" id="form-table-settings">
     45                    <tbody>
     46                    <?php
     47                    /* Loop over $usp_count USPs */
     48                    for ( $i = 0; $i < $usp_count; $i++ ) {
     49                        $usp  = $usps_value[ 'usp_' . $i ] ?? '';
     50                        $icon = $usps_icon[ 'usp_' . $i ] ?? 'fa-solid fa-truck';
     51                        ?>
     52                        <tr class="tr-heading">
     53                            <th class="th-usp"><label for="<?php echo esc_attr( 'uniqselprotb_usp_' . $i ); ?>">USP <?php echo esc_html( $i + 1 ); ?></label></th>
     54                            <th class="th-icon"><label for="<?php echo esc_attr( 'uniqselprotb_usp_icon_' . $i ); ?>">Icon</label></th>
     55                        </tr>
     56                        <tr class="tr-inputs">
     57                            <td>
     58                                <input type="text"
     59                                        id="<?php echo esc_attr( 'uniqselprotb_settings_usp_' . $i ); ?>"
     60                                        name="<?php echo esc_attr( 'uniqselprotb_settings[usp_' . $i . ']' ); ?>"
     61                                        value="<?php echo esc_attr( $usp ); ?>" />
     62                            </td>
     63                            <td>
     64                                <?php
     65                                $name   = 'uniqselprotb_settings[usp_icon_' . $i . ']';
     66                                $css_id = 'icon-' . $i;
     67                                ?>
     68                                <select name="<?php echo esc_attr( $name ); ?>" id="<?php echo esc_attr( $css_id ); ?>">
     69                                    <?php
     70                                    foreach ( $icons as $icon_class => $icon_name ) {
     71                                        $selected = false;
     72                                        if ( $icon_class === $icon ) {
     73                                            $selected = true;
     74                                        }
     75                                        if ( $selected ) {
     76                                            echo '<option value="' . esc_attr( $icon_class ) . '" selected><i class="' . sanitize_html_class( $icon_class ) . '"></i>' . esc_html( $icon_name ) . '</option>';
     77                                        } else {
     78                                            echo '<option value="' . esc_attr( $icon_class ) . '">' . esc_html( $icon_name ) . '</option>';
     79                                        }
     80                                    }
     81                                    ?>
     82                                </select>
     83                                <span class="dashicons dashicons-trash delete-usp"></span>
     84                            </td>
     85                        </tr>
    4286
    43                     <?php
    44                     /* Loop over 3 USPs */
    45                     for ( $i = 0; $i < 3; $i++ ) {
    46                         $usp = $usps_value[ 'usp_' . $i ];
    47                         $icon  = $usps_icon[ 'usp_' . $i ];
    48                         ?>
    49                         <tr>
    50                             <th><label for="<?php echo esc_attr( 'uniqselprotb_usp_' . $i ); ?>">USP <?php echo esc_html( $i + 1 ); ?></label></th>
    51                             <th><label for="<?php echo esc_attr( 'uniqselprotb_usp_icon_' . $i ); ?>">Icon</label></th>
    52                         </tr>
    53                         <tr>
    54                             <td>
    55                                 <input type="text"
    56                                        id="<?php echo esc_attr( 'uniqselprotb_settings_usp_' . $i ); ?>"
    57                                        name="<?php echo esc_attr( 'uniqselprotb_settings[usp_' . $i . ']' ); ?>"
    58                                        value="<?php echo esc_attr( $usp ); ?>" />
    59                             </td>
    60                             <td>
    61                                 <select name="<?php echo esc_attr( 'uniqselprotb_settings[usp_icon_' . $i . ']' ); ?>" id="icon">
    62                                     <?php
    63                                     foreach ( $icons as $icon_class => $icon_name ) {
    64                                         $selected = false;
    65                                         if ( $icon_class === $icon ) {
    66                                             $selected = true;
    67                                         }
    68                                         if ( $selected ) {
    69                                             echo '<option value="' . esc_attr( $icon_class ) . '" selected><i class="' . sanitize_html_class( $icon_class ) . '"></i>' . esc_html( $icon_name ) . '</option>';
    70                                         } else {
    71                                             echo '<option value="' . esc_attr( $icon_class ) . '">' . esc_html( $icon_name ) . '</option>';
    72                                         }
    73                                     }
    74                                     ?>
    75                             </td>
    76                         </tr>
    77 
    78                         <?php
    79                     }
    80                     ?>
    81 
    82                 </table>
    83             </div>
    84         </div>
    85         <?php submit_button( 'Save Changes' ); ?>
    86     </form>
     87                        <?php
     88                    }
     89                    ?>
     90                    </tbody>
     91                </table>
     92            </div>
     93            <button id="add-new-usp" class="button button-secondary">Add New</button>
     94        </div>
     95        <?php submit_button( 'Save Changes' ); ?>
     96    </form>
    8797</div>
  • uniqselprotb/trunk/includes/views/uniqselprotb-form-style.php

    r3330306 r3357146  
    1616
    1717/**
     18 * View for form style in admin panel
     19 *
    1820 * @var string $background_color
    1921 * @var string $text_color
     
    3032 * @var string $padding_left_unit
    3133 * @var string $padding_right_unit
    32  *
    3334 */
    3435if ( ! defined( 'ABSPATH' ) ) {
    35 exit;
     36    exit;
    3637}
    3738
     
    3940
    4041<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="form-style" id="form-style">
    41     <?php wp_nonce_field( 'uniqselprotb_saving_style', 'uniqselprotb_saving_style_nonce' ); ?>
     42    <?php wp_nonce_field( 'uniqselprotb_saving_style', 'uniqselprotb_saving_style_nonce' ); ?>
    4243
    43     <!-- Custom action and nonce fields -->
    44     <input type="hidden" name="action" value="uniqselprotb_saving_style">
     44    <!-- Custom action and nonce fields -->
     45    <input type="hidden" name="action" value="uniqselprotb_saving_style">
    4546
    46     <div id="tab-usps-style" class="tab-content">
    47         <h3>Style</h3>
    48         <p id="style-description">Customize the look of your USP banner with options for text color and background color.</p>
    49         <div class="container-table">
    50             <table class="form-table form-table-style">
    51                 <tr>
    52                     <th style="width: 200px;">Colors</th>
    53                     <th style="width: auto;"></th>
    54                 </tr>
    55                 <tr>
    56                     <td><label for="<?php echo esc_attr( 'uniqselprotb_background_color' ); ?>">Background Color</label></td>
    57                     <td>
    58                         <input type="text" id="uniqselprotb_background_color" class="unique-selling-propositions-top-banner-color-field" name="uniqselprotb_style[background_color]" value="<?php echo esc_attr( $background_color ); ?>" data-default-color="<?php echo esc_attr( $background_color ); ?>" />
    59                     </td>
    60                 </tr>
    61                 <tr>
    62                     <td><label for="<?php echo esc_attr( 'uniqselprotb_text_color' ); ?>">Color</label></td>
    63                     <td>
    64                         <input type="text" id="uniqselprotb_text_color" class="unique-selling-propositions-top-banner-color-field" name="uniqselprotb_style[text_color]" value="<?php echo esc_attr( $text_color ); ?>" data-default-color="<?php echo esc_attr( $text_color ); ?>" />
    65                     </td>
    66                 </tr>
    67             </table>
    68         </div>
    69         <div class="container-table">
    70             <table class="form-table form-table-style">
    71                 <tr>
    72                     <th style="width: 200px;">Font</th>
    73                     <th style="width: auto;"></th>
    74                 </tr>
    75                 <tr>
    76                     <td><label for="<?php echo esc_attr( 'uniqselprotb_font_size' ); ?>">Font Size</label></td>
    77                     <td>
    78                         <input type="number" id="uniqselprotb_font_size" step="0.1" class="unique-selling-propositions-top-banner-font-size-field" name="uniqselprotb_style[font_size]" value="<?php echo esc_attr( $font_size ); ?>" data-default-color="<?php echo esc_attr( $font_size ); ?>" />
    79                         <select name="uniqselprotb_style[font_size_unit]" class="unique-selling-propositions-top-banner-select-font-size-unit">
    80                             <option value="px" <?php selected($font_size_unit, 'px'); ?>>px</option>
    81                             <option value="em" <?php selected($font_size_unit, 'em'); ?>>em</option>
    82                             <option value="rem" <?php selected($font_size_unit, 'rem'); ?>>rem</option>
    83                             <option value="%" <?php selected($font_size_unit, '%'); ?>>%</option>
    84                         </select>
    85                     </td>
    86                 </tr>
    87                 <tr>
    88                     <td><label for="<?php echo esc_attr( 'uniqselprotb_font_weight' ); ?>">Font Weight</label></td>
    89                     <td>
    90                         <select name="uniqselprotb_style[font_weight]" class="unique-selling-propositions-top-banner-select-font-weight">
    91                             <option value="300" <?php selected($font_weight, '300'); ?>>300 (Light)</option>
    92                             <option value="400" <?php selected($font_weight, '400'); ?>>400 (Normal)</option>
    93                             <option value="500" <?php selected($font_weight, '500'); ?>>500 (Medium)</option>
    94                             <option value="700" <?php selected($font_weight, '700'); ?>>700 (Bold)</option>
    95                         </select>
    96                     </td>
    97                 </tr>
    98                 <tr>
    99                     <td><label for="<?php echo esc_attr( 'uniqselprotb_font_style' ); ?>">Font Style</label></td>
    100                     <td>
    101                         <select name="uniqselprotb_style[font_style]" class="unique-selling-propositions-top-banner-select-font-style">
    102                             <option value="normal" <?php selected($font_style, 'normal'); ?>>Normal</option>
    103                             <option value="italic" <?php selected($font_style, 'italic'); ?>>Italic</option>
    104                             <option value="oblique" <?php selected($font_style, 'oblique'); ?>>Oblique</option>
    105                         </select>
    106                     </td>
    107                 </tr>
    108             </table>
    109         </div>
    110         <div class="container-table">
    111             <table class="form-table form-table-padding">
    112                 <tr>
    113                     <th style="width: 200px;">Padding</th>
    114                     <th style="width: auto;"></th>
    115                 </tr>
    116                 <tr>
    117                     <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_bottom' ); ?>">Padding Bottom</label></td>
    118                     <td>
    119                         <input type="number" id="uniqselprotb_padding_bottom" step="0.1" class="unique-selling-propositions-top-banner-padding-bottom-field" name="uniqselprotb_style[padding_bottom]" value="<?php echo esc_attr( $padding_bottom ); ?>" data-default-color="<?php echo esc_attr( $padding_bottom ); ?>" />
    120                         <select name="uniqselprotb_style[padding_bottom_unit]" class="unique-selling-propositions-top-banner-select-padding-bottom-unit">
    121                             <option value="px" <?php selected($padding_bottom_unit, 'px'); ?>>px</option>
    122                             <option value="em" <?php selected($padding_bottom_unit, 'em'); ?>>em</option>
    123                             <option value="rem" <?php selected($padding_bottom_unit, 'rem'); ?>>rem</option>
    124                             <option value="%" <?php selected($padding_bottom_unit, '%'); ?>>%</option>
    125                         </select>
    126                     </td>
    127                 </tr>
    128                 <tr>
    129                     <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_top' ); ?>">Padding Top</label></td>
    130                     <td>
    131                         <input type="number" id="uniqselprotb_padding_top" step="0.1" class="unique-selling-propositions-top-banner-padding-top-field" name="uniqselprotb_style[padding_top]" value="<?php echo esc_attr( $padding_top ); ?>" data-default-color="<?php echo esc_attr( $padding_top ); ?>" />
    132                         <select name="uniqselprotb_style[padding_top_unit]" class="unique-selling-propositions-top-banner-select-padding-top-unit">
    133                             <option value="px" <?php selected($padding_top_unit, 'px'); ?>>px</option>
    134                             <option value="em" <?php selected($padding_top_unit, 'em'); ?>>em</option>
    135                             <option value="rem" <?php selected($padding_top_unit, 'rem'); ?>>rem</option>
    136                             <option value="%" <?php selected($padding_top_unit, '%'); ?>>%</option>
    137                         </select>
    138                     </td>
    139                 </tr>
    140                 <tr>
    141                     <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_left' ); ?>">Padding Left</label></td>
    142                     <td>
    143                         <input type="number" id="uniqselprotb_padding_left" step="0.1" class="unique-selling-propositions-top-banner-padding-left-field" name="uniqselprotb_style[padding_left]" value="<?php echo esc_attr( $padding_left ); ?>" data-default-color="<?php echo esc_attr( $padding_left ); ?>" />
    144                         <select name="uniqselprotb_style[padding_left_unit]" class="unique-selling-propositions-top-banner-select-padding-left-unit">
    145                             <option value="px" <?php selected($padding_left_unit, 'px'); ?>>px</option>
    146                             <option value="em" <?php selected($padding_left_unit, 'em'); ?>>em</option>
    147                             <option value="rem" <?php selected($padding_left_unit, 'rem'); ?>>rem</option>
    148                             <option value="%" <?php selected($padding_left_unit, '%'); ?>>%</option>
    149                         </select>
    150                     </td>
    151                 </tr>
     47    <div id="tab-usps-style" class="tab-content">
     48        <h3>Style</h3>
     49        <p id="style-description">Customize the look of your USP banner with options for text color and background color.</p>
     50        <div class="container-table">
     51            <table class="form-table form-table-style">
     52                <tr>
     53                    <th style="width: 200px;">Colors</th>
     54                    <th style="width: auto;"></th>
     55                </tr>
     56                <tr>
     57                    <td><label for="<?php echo esc_attr( 'uniqselprotb_background_color' ); ?>">Background Color</label></td>
     58                    <td>
     59                        <input type="text" id="uniqselprotb_background_color" class="unique-selling-propositions-top-banner-color-field" name="uniqselprotb_style[background_color]" value="<?php echo esc_attr( $background_color ); ?>" data-default-color="<?php echo esc_attr( $background_color ); ?>" />
     60                    </td>
     61                </tr>
     62                <tr>
     63                    <td><label for="<?php echo esc_attr( 'uniqselprotb_text_color' ); ?>">Color</label></td>
     64                    <td>
     65                        <input type="text" id="uniqselprotb_text_color" class="unique-selling-propositions-top-banner-color-field" name="uniqselprotb_style[text_color]" value="<?php echo esc_attr( $text_color ); ?>" data-default-color="<?php echo esc_attr( $text_color ); ?>" />
     66                    </td>
     67                </tr>
     68            </table>
     69        </div>
     70        <div class="container-table">
     71            <table class="form-table form-table-style">
     72                <tr>
     73                    <th style="width: 200px;">Font</th>
     74                    <th style="width: auto;"></th>
     75                </tr>
     76                <tr>
     77                    <td><label for="<?php echo esc_attr( 'uniqselprotb_font_size' ); ?>">Font Size</label></td>
     78                    <td>
     79                        <input type="number" id="uniqselprotb_font_size" step="0.1" class="unique-selling-propositions-top-banner-font-size-field" name="uniqselprotb_style[font_size]" value="<?php echo esc_attr( $font_size ); ?>" data-default-color="<?php echo esc_attr( $font_size ); ?>" />
     80                        <select name="uniqselprotb_style[font_size_unit]" class="unique-selling-propositions-top-banner-select-font-size-unit">
     81                            <option value="px" <?php selected( $font_size_unit, 'px' ); ?>>px</option>
     82                            <option value="em" <?php selected( $font_size_unit, 'em' ); ?>>em</option>
     83                            <option value="rem" <?php selected( $font_size_unit, 'rem' ); ?>>rem</option>
     84                            <option value="%" <?php selected( $font_size_unit, '%' ); ?>>%</option>
     85                        </select>
     86                    </td>
     87                </tr>
     88                <tr>
     89                    <td><label for="<?php echo esc_attr( 'uniqselprotb_font_weight' ); ?>">Font Weight</label></td>
     90                    <td>
     91                        <select name="uniqselprotb_style[font_weight]" class="unique-selling-propositions-top-banner-select-font-weight">
     92                            <option value="300" <?php selected( $font_weight, '300' ); ?>>300 (Light)</option>
     93                            <option value="400" <?php selected( $font_weight, '400' ); ?>>400 (Normal)</option>
     94                            <option value="500" <?php selected( $font_weight, '500' ); ?>>500 (Medium)</option>
     95                            <option value="700" <?php selected( $font_weight, '700' ); ?>>700 (Bold)</option>
     96                        </select>
     97                    </td>
     98                </tr>
     99                <tr>
     100                    <td><label for="<?php echo esc_attr( 'uniqselprotb_font_style' ); ?>">Font Style</label></td>
     101                    <td>
     102                        <select name="uniqselprotb_style[font_style]" class="unique-selling-propositions-top-banner-select-font-style">
     103                            <option value="normal" <?php selected( $font_style, 'normal' ); ?>>Normal</option>
     104                            <option value="italic" <?php selected( $font_style, 'italic' ); ?>>Italic</option>
     105                            <option value="oblique" <?php selected( $font_style, 'oblique' ); ?>>Oblique</option>
     106                        </select>
     107                    </td>
     108                </tr>
     109            </table>
     110        </div>
     111        <div class="container-table">
     112            <table class="form-table form-table-padding">
     113                <tr>
     114                    <th style="width: 200px;">Padding</th>
     115                    <th style="width: auto;"></th>
     116                </tr>
     117                <tr>
     118                    <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_bottom' ); ?>">Padding Bottom</label></td>
     119                    <td>
     120                        <input type="number" id="uniqselprotb_padding_bottom" step="0.1" class="unique-selling-propositions-top-banner-padding-bottom-field" name="uniqselprotb_style[padding_bottom]" value="<?php echo esc_attr( $padding_bottom ); ?>" data-default-color="<?php echo esc_attr( $padding_bottom ); ?>" />
     121                        <select name="uniqselprotb_style[padding_bottom_unit]" class="unique-selling-propositions-top-banner-select-padding-bottom-unit">
     122                            <option value="px" <?php selected( $padding_bottom_unit, 'px' ); ?>>px</option>
     123                            <option value="em" <?php selected( $padding_bottom_unit, 'em' ); ?>>em</option>
     124                            <option value="rem" <?php selected( $padding_bottom_unit, 'rem' ); ?>>rem</option>
     125                            <option value="%" <?php selected( $padding_bottom_unit, '%' ); ?>>%</option>
     126                        </select>
     127                    </td>
     128                </tr>
     129                <tr>
     130                    <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_top' ); ?>">Padding Top</label></td>
     131                    <td>
     132                        <input type="number" id="uniqselprotb_padding_top" step="0.1" class="unique-selling-propositions-top-banner-padding-top-field" name="uniqselprotb_style[padding_top]" value="<?php echo esc_attr( $padding_top ); ?>" data-default-color="<?php echo esc_attr( $padding_top ); ?>" />
     133                        <select name="uniqselprotb_style[padding_top_unit]" class="unique-selling-propositions-top-banner-select-padding-top-unit">
     134                            <option value="px" <?php selected( $padding_top_unit, 'px' ); ?>>px</option>
     135                            <option value="em" <?php selected( $padding_top_unit, 'em' ); ?>>em</option>
     136                            <option value="rem" <?php selected( $padding_top_unit, 'rem' ); ?>>rem</option>
     137                            <option value="%" <?php selected( $padding_top_unit, '%' ); ?>>%</option>
     138                        </select>
     139                    </td>
     140                </tr>
     141                <tr>
     142                    <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_left' ); ?>">Padding Left</label></td>
     143                    <td>
     144                        <input type="number" id="uniqselprotb_padding_left" step="0.1" class="unique-selling-propositions-top-banner-padding-left-field" name="uniqselprotb_style[padding_left]" value="<?php echo esc_attr( $padding_left ); ?>" data-default-color="<?php echo esc_attr( $padding_left ); ?>" />
     145                        <select name="uniqselprotb_style[padding_left_unit]" class="unique-selling-propositions-top-banner-select-padding-left-unit">
     146                            <option value="px" <?php selected( $padding_left_unit, 'px' ); ?>>px</option>
     147                            <option value="em" <?php selected( $padding_left_unit, 'em' ); ?>>em</option>
     148                            <option value="rem" <?php selected( $padding_left_unit, 'rem' ); ?>>rem</option>
     149                            <option value="%" <?php selected( $padding_left_unit, '%' ); ?>>%</option>
     150                        </select>
     151                    </td>
     152                </tr>
    152153
    153                 <tr>
    154                     <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_right' ); ?>">Padding Right</label></td>
    155                     <td>
    156                         <input type="number" id="uniqselprotb_padding_right" step="0.1" class="unique-selling-propositions-top-banner-padding-right-field" name="uniqselprotb_style[padding_right]" value="<?php echo esc_attr( $padding_right ); ?>" data-default-color="<?php echo esc_attr( $padding_right ); ?>" />
    157                         <select name="uniqselprotb_style[padding_right_unit]" class="unique-selling-propositions-top-banner-select-padding-right-unit">
    158                             <option value="px" <?php selected($padding_right_unit, 'px'); ?>>px</option>
    159                             <option value="em" <?php selected($padding_right_unit, 'em'); ?>>em</option>
    160                             <option value="rem" <?php selected($padding_right_unit, 'rem'); ?>>rem</option>
    161                             <option value="%" <?php selected($padding_right_unit, '%'); ?>>%</option>
    162                         </select>
    163                     </td>
    164                 </tr>
    165             </table>
    166         </div>
    167     </div>
    168     <!-- Submit Button -->
    169     <?php submit_button( 'Save Changes' ); ?>
     154                <tr>
     155                    <td><label for="<?php echo esc_attr( 'uniqselprotb_padding_right' ); ?>">Padding Right</label></td>
     156                    <td>
     157                        <input type="number" id="uniqselprotb_padding_right" step="0.1" class="unique-selling-propositions-top-banner-padding-right-field" name="uniqselprotb_style[padding_right]" value="<?php echo esc_attr( $padding_right ); ?>" data-default-color="<?php echo esc_attr( $padding_right ); ?>" />
     158                        <select name="uniqselprotb_style[padding_right_unit]" class="unique-selling-propositions-top-banner-select-padding-right-unit">
     159                            <option value="px" <?php selected( $padding_right_unit, 'px' ); ?>>px</option>
     160                            <option value="em" <?php selected( $padding_right_unit, 'em' ); ?>>em</option>
     161                            <option value="rem" <?php selected( $padding_right_unit, 'rem' ); ?>>rem</option>
     162                            <option value="%" <?php selected( $padding_right_unit, '%' ); ?>>%</option>
     163                        </select>
     164                    </td>
     165                </tr>
     166            </table>
     167        </div>
     168    </div>
     169    <!-- Submit Button -->
     170    <?php submit_button( 'Save Changes' ); ?>
    170171</form>
  • uniqselprotb/trunk/readme.txt

    r3330306 r3357146  
    44Tags: unique selling propositions, banner
    55Requires at least: 6.0
    6 Tested up to: 6.8
     6Tested up to: 6.8.2
    77Requires PHP: 8.0
    8 Stable tag: 1.2.0
     8Stable tag: 1.3.0
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
    1111
    12 Display up to 3 rotating unique selling points in a stylish top banner — fully responsive, mobile-friendly carousel with customizable colors and text.
     12Showcase rotating USPs in a sleek, responsive top banner
    1313
    1414== Description ==
     
    1818### Features
    1919
    20 * Add and edit three unique selling propositions directly from the WordPress admin panel.
     20* Add and edit multiple unique selling propositions directly from the WordPress admin panel.
    2121* Banners are displayed prominently at the top of the site for maximum visibility.
    2222* Fully responsive design — displays in a carousel on mobile devices for better user experience.
     
    4848= What does this plugin do? =
    4949
    50 This plugin displays a customizable top banner across your entire website to showcase three Unique Selling Propositions (USPs). You can define the USP texts, select icons and customize the banner’s text and background colors from the admin settings.
     50This plugin displays a customizable top banner across your entire website to showcase Unique Selling Propositions (USPs). You can define the USP texts, select icons and customize the banner’s text, colors and padding from the admin settings.
    5151
    5252= How many USPs can I add? =
    5353
    54 You can add three USPs in the plugin’s settings panel.
     54You can add multiple USPs in the plugin’s settings panel.
    5555
    5656= Can I change the colors of the banner? =
     
    71711. Unique Selling Propositions Configure
    72722. Unique Selling Propositions Top Banner Style
     733. Unique Selling Propositions Top Banner Frontend
    7374
    7475== License ==
     
    9394== Changelog ==
    9495
     96= 1.3.0 =
     97* Added support for more than 3 USPs
     98* Enabled USP carousel layout for tablets
     99
    95100= 1.2.0 =
    96101* Added support for decimal values for font size and padding.
  • uniqselprotb/trunk/uninstall.php

    r3329159 r3357146  
    1212 * @link      https://iomitroulaki.dev
    1313 * Requires PHP:      8.0
    14  *
    1514 */
    1615
    1716if ( ! defined( 'ABSPATH' ) ) {
    18     exit;
     17    exit;
    1918}
    2019
    2120/* if uninstall.php is not called by WordPress, die */
    2221if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    23     die;
     22    die;
    2423}
    2524
    2625require_once plugin_dir_path( __FILE__ ) .
    27     'includes/constants/class-uniqselprotb-options-constant.php';
     26    'includes/constants/class-uniqselprotb-options-constant.php';
    2827
    2928$options = UNIQSELPROTB_Options_Constant::OPTIONS;
    3029
    3130foreach ( $options as $option_name ) {
    32     delete_option( $option_name );
     31    delete_option( $option_name );
    3332}
  • uniqselprotb/trunk/uniqselprotb.php

    r3330306 r3357146  
    2020 * Description:      Unique Selling Propositions Top Banner for WordPress
    2121 *                   with configurable USPs and icons.
    22  * Version:          1.2.0
     22 * Version:          1.3.0
    2323 * Requires at least: 6.0
    2424 * Requires PHP:      8.0
    25  * Tested up to:      6.8
     25 * Tested up to:      6.8.2
    2626 * Created: April 4, 2025
    2727 * Author:          Ioanna Mitroulaki
     
    4444
    4545if ( ! defined( 'ABSPATH' ) ) {
    46     exit;
     46    exit;
    4747}
    4848
    4949if ( ! defined( 'UNIQSELPROTB_PLUGIN_URL' ) ) {
    50     define( 'UNIQSELPROTB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
     50    define( 'UNIQSELPROTB_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
    5151}
    5252
     
    5959 */
    6060function uniqselprotb_run_plugin(): void {
    61     new UNIQSELPROTB_Plugin();
     61    new UNIQSELPROTB_Plugin();
    6262}
    6363
Note: See TracChangeset for help on using the changeset viewer.