Plugin Directory

Changeset 3667117


Ignore:
Timestamp:
08/26/2026 01:32:05 PM (2 months ago)
Author:
fkdarven
Message:

Tag Darven Preços Parcelados 4.0.0

Location:
darven-multiplos-precos-informativos/tags/4.0.0
Files:
19 added
5 deleted
21 edited
1 copied

Legend:

Unmodified
Added
Removed
  • darven-multiplos-precos-informativos/tags/4.0.0/darven-extra-price-info.php

    r3627241 r3667117  
    11<?php
    22/*
    3  * Plugin Name: Darven Múltiplos Preços Informativos
     3 * Plugin Name: Darven Preços Parcelados
    44 * @package darven-extra-price-info
    55 * Plugin URI: wordpress.org/plugins/darven-multiplos-precos-informativos/
    6  * Description: This plugin is used to show multiple prices for a product. Incash and installments price.
    7  * Version: 3.3.1
     6 * Description: Displays cash and installment prices in WooCommerce. Previously: Darven Múltiplos Preços Informativos.
     7 * Version: 4.0.0
    88 * Author: Leticia Moreira
    99 * Author URI: https://darven.wtf
    10  * Text Domain: darven-epi
    11  * Domain Path: /i18n/languages/
    12  * Requires PHP: 7.4
     10 * Text Domain: darven-multiplos-precos-informativos
     11 * Domain Path: /languages/
     12 * Requires at least: 5.0
     13 * Requires PHP: 8.0
    1314 * Requires Plugins: woocommerce
    1415*/
    … …  
    2021define( 'DARVEN_EPI_STYLES_PATH', '/' . str_replace( site_url() . '/', '', plugin_dir_url( __FILE__ ) ) );
    2122const DARVEN_EPI_ADMIN_PAGE = 'darven-epi-admin';
    22 const DARVEN_EPI_LANGUAGE_DOMAIN = 'darven-epi';
     23const DARVEN_EPI_LANGUAGE_DOMAIN = 'darven-multiplos-precos-informativos';
    2324if ( ! defined( 'WPINC' ) ) {
    2425        die;
    2526}
    2627
    27 const DARVEN_EPI_VERSION = '3.3.1';
     28const DARVEN_EPI_VERSION = '4.0.0';
    2829
    2930$darven_epi_autoload_file = DARVEN_EPI_DIR_PATH . 'vendor/autoload.php';
    … …  
    3435                static function (): void {
    3536                        echo '<div class="notice notice-error"><p>'
    36                                 . esc_html__( 'Darven Extra Price Info is missing its runtime dependencies.', 'darven-epi' )
     37                                . esc_html__( 'Darven Extra Price Info is missing its runtime dependencies.', DARVEN_EPI_LANGUAGE_DOMAIN )
    3738                                . '</p></div>';
    3839                }
  • darven-multiplos-precos-informativos/tags/4.0.0/public/css/styles.css

    r3627068 r3667117  
    8787}
    8888
     89.darven-epi-installments-toggle:focus-visible {
     90        outline: 3px solid #1f75cc;
     91        outline-offset: 3px;
     92}
     93
    8994.darven-epi-installments-popup {
    90     background-color:#FFFFFF;
    91     border: dotted 1px black;
    92 
    93     cursor:default;
    94     display:none;
    95     margin-top: 15px;
    96     position:absolute;
    97     text-align:left;
    98     z-index:50;
    99     padding: 25px 25px 20px;
    100 }
    101 
    102 label {
    103     display: block;
    104     margin-bottom: 3px;
    105     padding-left: 15px;
    106     text-indent: -15px;
    107 }
    108 
    109 .darven-epi-installments-popup p,
    110 .darven-epi-installments-popup.div {
     95        align-items: center;
     96        cursor: default;
     97        display: grid;
     98        inset: 0;
     99        justify-items: center;
     100        padding: 20px;
     101        position: fixed;
     102        text-align: left;
     103        z-index: 99999999;
     104}
     105
     106.darven-epi-installments-popup[hidden] {
     107        display: none;
     108}
     109
     110.darven-epi-installments-backdrop {
     111        background: rgba(0, 0, 0, 0.58);
     112        cursor: pointer;
     113        inset: 0;
     114        position: absolute;
     115}
     116
     117.darven-epi-installments-dialog {
     118        animation: darven-epi-popup-in 160ms ease-out;
     119        background-color: #fff;
     120        border: 1px solid #d7d7d7;
     121        border-radius: 8px;
     122        box-shadow: 0 12px 36px rgba(0, 0, 0, 0.3);
     123        box-sizing: border-box;
     124        max-height: calc(100vh - 40px);
     125        max-width: 520px;
     126        overflow: hidden;
     127        padding: 48px 24px 24px;
     128        position: relative;
     129        width: 100%;
     130        z-index: 1;
     131}
     132
     133.darven-epi-installments-close {
     134        align-items: center;
     135        background: transparent;
     136        border: 0;
     137        border-radius: 4px;
     138        color: inherit;
     139        cursor: pointer;
     140        display: flex;
     141        font: inherit;
     142        font-size: 28px;
     143        height: 40px;
     144        justify-content: center;
     145        padding: 0;
     146        position: absolute;
     147        right: 8px;
     148        top: 8px;
     149        width: 40px;
     150}
     151
     152.darven-epi-installments-close:focus-visible {
     153        outline: 3px solid #1f75cc;
     154        outline-offset: 3px;
     155}
     156
     157.darven-epi-installments-table-wrap {
     158        max-height: calc(100vh - 136px);
     159        overflow: auto;
     160        overscroll-behavior: contain;
     161}
     162
     163.darven-epi-installments-title {
     164        border: 0;
     165        clip: rect(1px, 1px, 1px, 1px);
     166        clip-path: inset(50%);
     167        height: 1px;
     168        margin: -1px;
     169        overflow: hidden;
     170        padding: 0;
     171        position: absolute;
     172        width: 1px;
     173        word-wrap: normal;
     174}
     175
     176.darven-epi-installments-popup p {
    111177    border-bottom: 1px solid #EFEFEF;
    112178    margin: 8px 0;
    113179    padding-bottom: 8px;
    114180}
     181
     182@keyframes darven-epi-popup-in {
     183
     184        from {
     185                opacity: 0;
     186                transform: translateY(8px);
     187        }
     188
     189        to {
     190                opacity: 1;
     191                transform: translateY(0);
     192        }
     193}
     194
     195@media (max-width: 480px) {
     196
     197        .darven-epi-installments-popup {
     198                padding: 12px;
     199        }
     200
     201        .darven-epi-installments-dialog {
     202                max-height: calc(100vh - 24px);
     203                padding: 48px 16px 16px;
     204        }
     205
     206        .darven-epi-installments-table-wrap {
     207                max-height: calc(100vh - 112px);
     208        }
     209}
     210
     211@media (prefers-reduced-motion: reduce) {
     212
     213        .darven-epi-installments-dialog {
     214                animation: none;
     215                scroll-behavior: auto;
     216        }
     217}
  • darven-multiplos-precos-informativos/tags/4.0.0/public/js/frontend.js

    r3627068 r3667117  
    1 ( function( $ ) {
     1( function () {
    22        'use strict';
    33
    4         var toggleSelector = '.darven-epi-installments-toggle';
     4        const toggleSelector = '.darven-epi-installments-toggle';
     5        const popupSelector = '.darven-epi-installments-popup';
     6        const closeSelector = '.darven-epi-installments-close';
     7        const backdropSelector = '.darven-epi-installments-backdrop';
     8        let activeModal = null;
     9        let activeTrigger = null;
    510
    6         function setExpanded( $toggle, expanded ) {
    7                 var $statement = $toggle.closest( '.darven-epi-installments-price-statement' );
    8                 var $popup = $statement.find( '.darven-epi-installments-popup' ).first();
    9 
    10                 $toggle
    11                         .toggleClass( 'selected', expanded )
    12                         .attr( 'aria-expanded', expanded ? 'true' : 'false' );
    13 
    14                 $popup
    15                         .attr( 'aria-hidden', expanded ? 'false' : 'true' )
    16                         .stop( true, true )[ expanded ? 'slideDown' : 'slideUp' ]( 'fast' );
     11        if ( document.__darvenEpiInstallmentsModalBound ) {
     12                return;
    1713        }
    1814
    19         $( document ).on( 'click', toggleSelector, function() {
    20                 var $toggle = $( this );
    21                 var expanded = 'true' === $toggle.attr( 'aria-expanded' );
     15        document.__darvenEpiInstallmentsModalBound = true;
    2216
    23                 setExpanded( $toggle, ! expanded );
     17        function closest( element, selector ) {
     18                let current = element;
     19
     20                while ( current && current.nodeType === 1 ) {
     21                        if ( current.matches( selector ) ) {
     22                                return current;
     23                        }
     24
     25                        current = current.parentElement;
     26                }
     27
     28                return null;
     29        }
     30
     31        function getModal( trigger ) {
     32                const modalId = trigger.getAttribute( 'aria-controls' );
     33                const statement = closest(
     34                        trigger,
     35                        '.darven-epi-installments-price-statement'
     36                );
     37
     38                return Array.prototype.find.call(
     39                        statement ? statement.querySelectorAll( popupSelector ) : [],
     40                        ( candidate ) => candidate.id === modalId
     41                );
     42        }
     43
     44        function getFocusableElements( modal ) {
     45                const selector = [
     46                        'a[href]',
     47                        'button:not([disabled])',
     48                        'input:not([disabled])',
     49                        'select:not([disabled])',
     50                        'textarea:not([disabled])',
     51                        '[tabindex]:not([tabindex="-1"])',
     52                ].join( ',' );
     53
     54                return Array.prototype.filter.call(
     55                        modal.querySelectorAll( selector ),
     56                        function ( element ) {
     57                                return (
     58                                        ! element.hidden &&
     59                                        'true' !== element.getAttribute( 'aria-hidden' )
     60                                );
     61                        }
     62                );
     63        }
     64
     65        function closeActiveModal( returnFocus ) {
     66                const trigger = activeTrigger;
     67
     68                if ( ! activeModal || ! trigger ) {
     69                        return;
     70                }
     71
     72                activeModal.hidden = true;
     73                activeModal.setAttribute( 'aria-hidden', 'true' );
     74                trigger.setAttribute( 'aria-expanded', 'false' );
     75                trigger.classList.remove( 'selected' );
     76                activeModal = null;
     77                activeTrigger = null;
     78
     79                if ( returnFocus && document.contains( trigger ) ) {
     80                        trigger.focus();
     81                }
     82        }
     83
     84        function openModal( trigger ) {
     85                const modal = getModal( trigger );
     86
     87                if ( ! modal ) {
     88                        return;
     89                }
     90
     91                const closeButton = modal.querySelector( closeSelector );
     92
     93                if ( activeModal && activeModal !== modal ) {
     94                        closeActiveModal( false );
     95                }
     96
     97                activeModal = modal;
     98                activeTrigger = trigger;
     99                modal.hidden = false;
     100                modal.setAttribute( 'aria-hidden', 'false' );
     101                trigger.setAttribute( 'aria-expanded', 'true' );
     102                trigger.classList.add( 'selected' );
     103
     104                if ( closeButton ) {
     105                        closeButton.focus();
     106                }
     107        }
     108
     109        function toggleModal( trigger ) {
     110                if ( 'true' === trigger.getAttribute( 'aria-expanded' ) ) {
     111                        closeActiveModal( true );
     112                        return;
     113                }
     114
     115                openModal( trigger );
     116        }
     117
     118        function trapFocus( event ) {
     119                const focusable = getFocusableElements( activeModal );
     120
     121                if ( 0 === focusable.length ) {
     122                        event.preventDefault();
     123                        return;
     124                }
     125
     126                const first = focusable[ 0 ];
     127                const last = focusable[ focusable.length - 1 ];
     128                const activeElement = activeModal.ownerDocument.activeElement;
     129
     130                if (
     131                        event.shiftKey &&
     132                        ( activeElement === first ||
     133                                ! activeModal.contains( activeElement ) )
     134                ) {
     135                        event.preventDefault();
     136                        last.focus();
     137                } else if (
     138                        ! event.shiftKey &&
     139                        ( activeElement === last ||
     140                                ! activeModal.contains( activeElement ) )
     141                ) {
     142                        event.preventDefault();
     143                        first.focus();
     144                }
     145        }
     146
     147        document.addEventListener( 'click', function ( event ) {
     148                const target = event.target;
     149
     150                if ( ! target || ! target.matches ) {
     151                        return;
     152                }
     153
     154                const toggle = closest( target, toggleSelector );
     155                if ( toggle ) {
     156                        toggleModal( toggle );
     157                        return;
     158                }
     159
     160                if ( activeModal && closest( target, closeSelector ) ) {
     161                        closeActiveModal( true );
     162                        return;
     163                }
     164
     165                if ( activeModal && target.matches( backdropSelector ) ) {
     166                        closeActiveModal( true );
     167                }
    24168        } );
    25169
    26         $( document ).on( 'blur', toggleSelector, function() {
    27                 setExpanded( $( this ), false );
    28         } );
     170        document.addEventListener( 'keydown', function ( event ) {
     171                const target = event.target;
     172                const toggle =
     173                        target && target.matches
     174                                ? closest( target, toggleSelector )
     175                                : null;
    29176
    30         $( document ).on( 'keydown', toggleSelector, function( event ) {
     177                if (
     178                        toggle &&
     179                        ( 'Enter' === event.key ||
     180                                ' ' === event.key ||
     181                                'Spacebar' === event.key )
     182                ) {
     183                        event.preventDefault();
     184                        toggleModal( toggle );
     185                        return;
     186                }
     187
     188                if ( ! activeModal ) {
     189                        return;
     190                }
     191
    31192                if ( 'Escape' === event.key ) {
    32                         setExpanded( $( this ), false );
     193                        event.preventDefault();
     194                        closeActiveModal( true );
     195                } else if ( 'Tab' === event.key ) {
     196                        trapFocus( event );
    33197                }
    34198        } );
    35 }( jQuery ) );
     199} )();
  • darven-multiplos-precos-informativos/tags/4.0.0/readme.txt

    r3627241 r3667117  
    1 === Plugin Name ===
     1=== Darven Preços Parcelados ===
    22Contributors: fkdarven
    3 Tags: parcelas, parcelamento, preços, installments, price, woocommerce
    4 Requires at least: 4.7
    5 Tested up to: 7.0
    6 Stable tag: 3.3.1
    7 Requires PHP: 7.4
     3Tags: parcelas, parcelamento, preços, preço à vista, preço parcelado
     4Requires at least: 5.0
     5Tested up to: 7.1
     6Stable tag: 4.0.0
     7Requires PHP: 8.0
    88License: GPLv2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
    … …  
    1212
    1313Mostra múltiplos preços em um produto. Preço á vista e com parcelamento (preço parcelado).
     14
     15Anteriormente: Darven Múltiplos Preços Informativos.
    1416
    1517== Description ==
    … …  
    6870== Screenshots ==
    6971
    70 1. Catálogo de produtos com o preço á vista e com parcelamento ativados
    71 2. Configurações do preço com parcelamento
    72 3. Configurações do preço á vista
    73 4. Produto individual com o preço á vista e com parcelamento ativados
     721. Configurações do Darven Preços Parcelados no menu do WooCommerce.
     732. Opções do Darven no editor de produto do WooCommerce.
     743. Lista acessível de parcelas aberta na página do produto.
    7475
    7576== Changelog ==
     77= 4.0.0 =
     78    • Nova identidade pública: Darven Preços Parcelados. Anteriormente: Darven Múltiplos Preços Informativos.
     79    • Preparada a infraestrutura de ativos administrativos separados para configurações e opções de produto.
     80
    7681= 3.3.1 =
    7782    • Validado com WordPress 7.0.2 e WooCommerce 10.9.4.
    … …  
    137142Ajustes para melhorar a compatibilidade com versões anteriores do PHP.
    138143
    139 
    140 
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Admin/Assets.php

    r3627068 r3667117  
    77                $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : null;
    88
    9                 if ( 'darven-epi-admin' !== $page ) {
    10                         return;
    11                 }
    12 
    13                 $plugin_url = plugin_dir_url( DARVEN_EPI_DIR_PATH . 'darven-extra-price-info.php' );
    14                 $version    = defined( 'DARVEN_EPI_VERSION' ) ? DARVEN_EPI_VERSION : '1.0.0';
    15 
    16                 wp_enqueue_style( 'darven-epi', $plugin_url . 'admin/css/admin_styles.css', array(), $version, 'all' );
    17 
    18                 $tab = isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : null;
    19                 if ( 'colorsandstyles' === $tab ) {
    20                         wp_enqueue_script(
    21                                 'darven-epi',
    22                                 $plugin_url . 'admin/js/colorsandstyles.js',
    23                                 array( 'jquery', 'wp-color-picker' ),
    24                                 $version,
    25                                 false
    26                         );
     9                if ( 'darven-epi-admin' === $page ) {
     10                        $this->enqueueSettingsAssets();
    2711
    2812                        return;
    2913                }
    3014
    31                 if ( 'positions' !== $tab ) {
    32                         wp_enqueue_script( 'darven-epi', $plugin_url . 'admin/js/general.js', array( 'jquery' ), $version, false );
     15                if ( $this->isProductEditor() ) {
     16                        $this->enqueueProductOptionsAssets();
    3317                }
    3418        }
     19
     20        private function enqueueSettingsAssets(): void {
     21                $this->enqueueBundle(
     22                        'settings', 'darven-precos-parcelados-settings', 'DarvenPrecosParceladosSettings', array(
     23                                'restUrl'   => rest_url( 'darven-precos-parcelados/v1/' ),
     24                                'nonce'     => wp_create_nonce( 'wp_rest' ),
     25                                'screen'    => 'settings',
     26                                'productId' => 0,
     27                        )
     28                );
     29        }
     30
     31        private function enqueueProductOptionsAssets(): void {
     32                $this->enqueueBundle(
     33                        'product-options', 'darven-precos-parcelados-product-options', 'DarvenPrecosParceladosProductOptions', array(
     34                                'restUrl'   => rest_url( 'darven-precos-parcelados/v1/' ),
     35                                'nonce'     => wp_create_nonce( 'wp_rest' ),
     36                                'screen'    => 'product',
     37                                'productId' => isset( $_GET['post'] ) ? absint( $_GET['post'] ) : 0,
     38                        )
     39                );
     40                wp_enqueue_media();
     41        }
     42
     43        private function enqueueBundle( string $bundle, string $handle, string $object_name, array $config ): void {
     44                $asset = $this->getAssetMetadata( $bundle );
     45                $url   = plugin_dir_url( DARVEN_EPI_DIR_PATH . 'darven-extra-price-info.php' ) . 'build/' . $bundle . '/';
     46                $deps  = isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : array();
     47                $deps  = array_values( array_unique( array_merge( $deps, array( 'wp-api-fetch', 'wp-element', 'wp-i18n' ) ) ) );
     48                $version = isset( $asset['version'] ) && is_string( $asset['version'] )
     49                        ? $asset['version']
     50                        : ( defined( 'DARVEN_EPI_VERSION' ) ? DARVEN_EPI_VERSION : '1.0.0' );
     51
     52                wp_enqueue_style( $handle, $url . 'style-index.css', array(), $version, 'all' );
     53                wp_style_add_data( $handle, 'rtl', 'replace' );
     54                wp_enqueue_script( $handle, $url . 'index.js', $deps, $version, true );
     55                wp_localize_script( $handle, $object_name, $config );
     56                if ( function_exists( 'wp_set_script_translations' ) ) {
     57                        wp_set_script_translations( $handle, \DARVEN_EPI_LANGUAGE_DOMAIN, \DARVEN_EPI_DIR_PATH . 'languages' );
     58                }
     59        }
     60
     61        private function getAssetMetadata( string $bundle ): array {
     62                $asset_file = DARVEN_EPI_DIR_PATH . 'build/' . $bundle . '/index.asset.php';
     63                if ( ! file_exists( $asset_file ) ) {
     64                        return array();
     65                }
     66
     67                $asset = require $asset_file;
     68
     69                return is_array( $asset ) ? $asset : array();
     70        }
     71
     72        private function isProductEditor(): bool {
     73                $screen = get_current_screen();
     74
     75                return is_object( $screen )
     76                        && isset( $screen->post_type, $screen->base )
     77                        && 'product' === $screen->post_type
     78                        && 'post' === $screen->base;
     79        }
    3580}
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Admin/ProductOptionsController.php

    r3627068 r3667117  
    1616
    1717        public function register(): void {
     18                add_filter(
     19                        'woocommerce_product_data_tabs', array( $this, 'addTab' )
     20                );
    1821                add_action(
    19                         'woocommerce_product_options_general_product_data',
    20                         array( $this, 'renderFields' )
     22                        'woocommerce_product_data_panels', array( $this, 'renderPanel' )
    2123                );
    2224                add_action(
    … …  
    2628        }
    2729
    28         public function renderFields(): void {
    29                 echo '<div class="product_custom_field">';
    30                 woocommerce_wp_checkbox(
    31                         array(
    32                                 'id'          => '_darven_epi_is_incash_enabled',
    33                                 'placeholder' => '',
    34                                 'label'       => __( 'Disable in cash price for this product', 'woocommerce' ),
    35                                 'type'        => 'boolean',
    36                         )
     30        public function addTab( array $tabs ): array {
     31                $tabs['darven-precos-parcelados'] = array(
     32                        'label'  => __( 'Darven', 'darven-multiplos-precos-informativos' ),
     33                        'target' => 'darven-precos-parcelados-product-options-panel',
     34                        'class'  => array(),
    3735                );
    38                 woocommerce_wp_checkbox(
    39                         array(
    40                                 'id'          => '_darven_epi_is_installment_enabled',
    41                                 'placeholder' => '',
    42                                 'label'       => __( 'Disable installments price for this product', 'woocommerce' ),
    43                                 'type'        => 'boolean',
    44                         )
     36
     37                return $tabs;
     38        }
     39
     40        public function renderPanel(): void {
     41                global $post;
     42
     43                $product_id = isset( $post->ID ) ? absint( $post->ID ) : 0;
     44                $product    = $product_id > 0 ? wc_get_product( $product_id ) : false;
     45                $settings   = $product instanceof \WC_Product
     46                        ? $this->repository->getSettings( $product )
     47                        : array(
     48                                'disable_incash'       => false,
     49                                'disable_installments' => false,
     50                        );
     51
     52                printf(
     53                        '<div id="darven-precos-parcelados-product-options-panel" class="panel woocommerce_options_panel hidden"><div id="darven-precos-parcelados-product-options-root" data-product-id="%s"></div></div>', esc_attr( (string) $product_id )
    4554                );
    46                 echo '</div>';
     55                echo '<noscript><div class="options_group">';
     56                $this->renderFallbackCheckbox(
     57                        '_darven_epi_is_incash_enabled', __( 'Disable cash price for this product', 'darven-multiplos-precos-informativos' ), true === $settings['disable_incash']
     58                );
     59                $this->renderFallbackCheckbox(
     60                        '_darven_epi_is_installment_enabled', __( 'Disable installment price for this product', 'darven-multiplos-precos-informativos' ), true === $settings['disable_installments']
     61                );
     62                echo '</div></noscript>';
     63        }
     64
     65        private function renderFallbackCheckbox( string $name, string $label, bool $is_checked ): void {
     66                printf(
     67                        '<p class="form-field"><input type="hidden" name="%1$s" value="no"><label><input type="checkbox" name="%1$s" value="yes"%2$s> %3$s</label></p>', esc_attr( $name ), $is_checked ? ' checked' : '', esc_html( $label )
     68                );
    4769        }
    4870
    4971        public function save( \WC_Product $product ): void {
     72                if ( ! array_key_exists( '_darven_epi_is_incash_enabled', $_POST )
     73                        && ! array_key_exists( '_darven_epi_is_installment_enabled', $_POST ) ) {
     74                        return;
     75                }
     76
    5077                if ( ! current_user_can( 'edit_post', $product->get_id() ) ) {
    5178                        return;
    52                 }
    53                 if ( ! isset( $_POST['woocommerce_meta_nonce'] ) ) {
    54                         return;
    55                 }
     79        }
     80        if ( ! isset( $_POST['woocommerce_meta_nonce'] ) ) {
     81                return;
     82        }
    5683                $nonce = sanitize_text_field( wp_unslash( $_POST['woocommerce_meta_nonce'] ) );
    57                 if ( ! wp_verify_nonce( $nonce, 'woocommerce_save_data' ) ) {
    58                         return;
    59                 }
     84        if ( ! wp_verify_nonce( $nonce, 'woocommerce_save_data' ) ) {
     85                return;
     86        }
    6087
    6188                $incash_value = isset( $_POST['_darven_epi_is_incash_enabled'] ) && is_string( $_POST['_darven_epi_is_incash_enabled'] )
    … …  
    7198                );
    7299
    73                 $this->repository->save( $product, $settings );
     100                $this->repository->save( $product, $settings, false );
    74101        }
    75102
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Admin/SettingsPage.php

    r3627068 r3667117  
    33namespace Darven\ExtraPriceInfo\Admin;
    44
    5 use Darven\ExtraPriceInfo\Admin\SettingsFields\CompatibilityFields;
    6 use Darven\ExtraPriceInfo\Admin\SettingsFields\DisplayFields;
    7 use Darven\ExtraPriceInfo\Admin\SettingsFields\GeneralFields;
    8 use Darven\ExtraPriceInfo\Admin\SettingsFields\PositionsFields;
    95
    106final class SettingsPage {
    11         public function register(): void {
    12                 add_action( 'admin_menu', array( $this, 'addMenuPage' ) );
    13                 add_action( 'admin_init', array( $this, 'initializeSettings' ) );
    14         }
    15 
    16         public function addMenuPage(): void {
    17                 add_submenu_page(
    18                         'woocommerce',
    19                         __( 'In Cash and Installments Price', 'darven-epi' ),
    20                         'Preço á Vista e com Parcelamento',
    21                         'manage_options',
    22                         'darven-epi-admin',
    23                         array( $this, 'renderPage' )
    24                 );
    25         }
    26 
    277        public function renderPage(): void {
    28                 $tab = filter_input( INPUT_GET, 'tab' );
    29 
    30                 include DARVEN_EPI_DIR_PATH . 'templates/admin/general-settings.php';
    31         }
    32 
    33         public function initializeSettings(): void {
    34                 $tab = filter_input( INPUT_GET, 'tab' );
    35 
    36                 if ( 'colorsandstyles' === $tab ) {
    37                         $this->addInCashSection( __( 'In Cash Settings', 'darven-epi' ) );
    38                         $this->addInstallmentsSection( __( 'Installments Settings', 'darven-epi' ) );
    39                         ( new DisplayFields() )->register();
    40 
    41                         return;
    42                 }
    43 
    44                 if ( 'positions' === $tab ) {
    45                         $this->addInCashSection( __( 'Statements Positions Settings', 'darven-epi' ) );
    46                         ( new PositionsFields() )->register();
    47 
    48                         return;
    49                 }
    50 
    51                 if ( 'compatibility' === $tab ) {
    52                         $this->addInCashSection( __( 'Compatibility Settings', 'darven-epi' ) );
    53                         ( new CompatibilityFields() )->register();
    54 
    55                         return;
    56                 }
    57 
    58                 $this->addInCashSection( __( 'In Cash Settings', 'darven-epi' ) );
    59                 $this->addInstallmentsSection( __( 'Installments Settings', 'darven-epi' ) );
    60                 add_settings_section(
    61                         'darven_epi_advanced_installments_settings_section',
    62                         __( 'Advanced Installments Settings Section', 'darven-epi' ),
    63                         array( $this, 'renderAdvancedInstallmentsSection' ),
    64                         'darven-epi-admin'
    65                 );
    66                 ( new GeneralFields() )->register();
    67         }
    68 
    69         public function renderSection(): void {
    70         }
    71 
    72         public function renderAdvancedInstallmentsSection(): void {
    73                 printf(
    74                         '<div class="wrap"> %s</div>',
    75                         esc_attr(
    76                                 __(
    77                                         'Use this section to set up customized interest fees. If your gateway has incremental fees (each month the same value is summed up), please use the incremental interest fee settings in the previous section for a better experience.',
    78                                         'darven-epi'
    79                                 )
    80                         )
    81                 );
    82         }
    83 
    84         private function addInCashSection( string $title ): void {
    85                 add_settings_section(
    86                         'darven_epi_incash_settings_section',
    87                         $title,
    88                         array( $this, 'renderSection' ),
    89                         'darven-epi-admin'
    90                 );
    91         }
    92 
    93         private function addInstallmentsSection( string $title ): void {
    94                 add_settings_section(
    95                         'darven_epi_installments_settings_section',
    96                         $title,
    97                         array( $this, 'renderSection' ),
    98                         'darven-epi-admin'
    99                 );
     8                echo '<div id="darven-precos-parcelados-settings-root"></div>';
    1009        }
    10110}
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Compatibility/LegacyProductSettingsAdapter.php

    r3627068 r3667117  
    66        public function fromLegacyMeta( $incash_value, $installments_value ): array {
    77                return array(
     8                        'schema_version'       => 1,
    89                        'disable_incash'       => 'yes' === $incash_value,
    910                        'disable_installments' => 'yes' === $installments_value,
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Compatibility/LegacySettingsAdapter.php

    r3627068 r3667117  
    1313        public function fromLegacyOptions( array $legacy_options ): array {
    1414                $settings = array(
    15                         'schema_version' => 1,
     15                        'schema_version' => 2,
    1616                );
    1717
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Frontend/Assets.php

    r3627068 r3667117  
    44
    55final class Assets {
     6        /**
     7         * @var InlineStyles
     8         */
     9        private $inline_styles;
     10
     11        public function __construct( InlineStyles $inline_styles ) {
     12                $this->inline_styles = $inline_styles;
     13        }
     14
    615        public function enqueue(): void {
    716                $plugin_url = plugin_dir_url( DARVEN_EPI_DIR_PATH . 'darven-extra-price-info.php' );
    … …  
    918
    1019                wp_enqueue_style( 'darven-epi', $plugin_url . 'public/css/styles.css', array(), $version, 'all' );
    11                 wp_enqueue_script( 'darven-epi', $plugin_url . 'public/js/frontend.js', array( 'jquery' ), $version, false );
     20                wp_add_inline_style( 'darven-epi', $this->inline_styles->render() );
     21                wp_enqueue_script( 'darven-epi', $plugin_url . 'public/js/frontend.js', array(), $version, false );
    1222        }
    1323}
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Frontend/InlineStyles.php

    r3627068 r3667117  
    1818                $display = $this->settings_repository->getSection( 'display' );
    1919
    20                 return str_replace( '\\n', "\n", '<style>\n\n'
    21                         . '    .darven-epi-incash-prefix {\n\n'
    22                         . '        color: ' . $this->getValue( $display, 'darven_epi_color_of_incash_prefix' ) . ';\n'
    23                         . '        font-size: ' . $this->getValue( $display, 'darven_epi_font_size_of_incash_prefix', '1' ) . 'em;\n'
    24                         . '    }\n\n'
    25                         . '    .darven-epi-incash-price {\n\n'
    26                         . '        color: ' . $this->getValue( $display, 'darven_epi_color_of_incash_price' ) . ' !important;\n'
     20                return str_replace( '\\n', "\n", '\n    .darven-epi-incash-prefix {\n\n        color: ' . $this->getValue( $display, 'darven_epi_color_of_incash_prefix' ) . ';\n        font-size: ' . $this->getValue( $display, 'darven_epi_font_size_of_incash_prefix', '1' ) . 'em;\n    }\n\n    .darven-epi-incash-price {\n\n        color: ' . $this->getValue( $display, 'darven_epi_color_of_incash_price' ) . ' !important;\n'
    2721                        . '        font-size: ' . $this->getValue( $display, 'darven_epi_font_size_of_incash_price', '1' ) . 'em;\n\n'
    2822                        . '    }\n\n'
    … …  
    4640                        . '        color: ' . $this->getValue( $display, 'darven_epi_color_of_installments_suffix' ) . ';\n'
    4741                        . '        font-size: ' . $this->getValue( $display, 'darven_epi_font_size_of_installments_suffix', '1' ) . 'em;\n'
    48                         . '    }\n\n\n'
    49                         . '</style>\n' );
     42                        . '    }\n\n\n' );
    5043        }
    5144
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Repositories/ProductSettingsRepository.php

    r3627068 r3667117  
    1616        private $adapter;
    1717
    18         public function __construct( LegacyProductSettingsAdapter $adapter ) {
    19                 $this->adapter = $adapter;
     18        /**
     19         * @var callable
     20         */
     21        private $product_reloader;
     22
     23        public function __construct( LegacyProductSettingsAdapter $adapter, ?callable $product_reloader = null ) {
     24                $this->adapter          = $adapter;
     25                $this->product_reloader = $product_reloader ?? static function ( int $product_id ) {
     26                        return function_exists( 'wc_get_product' ) ? wc_get_product( $product_id ) : false;
     27                };
    2028        }
    2129
    2230        public function getSettings( \WC_Product $product ): array {
     31                $direct_settings = $this->getDirectSettings( $product );
     32
     33                if ( null !== $direct_settings ) {
     34                        return $direct_settings;
     35                }
     36
     37                if ( $product->is_type( 'variation' ) ) {
     38                        $parent_id = (int) $product->get_parent_id();
     39                        $parent    = $parent_id > 0 ? wc_get_product( $parent_id ) : false;
     40
     41                        if ( $parent instanceof \WC_Product ) {
     42                                $parent_settings = $this->getDirectSettings( $parent );
     43
     44                                if ( null !== $parent_settings ) {
     45                                        return $parent_settings;
     46                                }
     47                        }
     48                }
     49
     50                return $this->adapter->fromLegacyMeta( '', '' );
     51        }
     52
     53        private function getDirectSettings( \WC_Product $product ): ?array {
    2354                $canonical_settings = $product->get_meta( self::META_KEY, true );
    2455
    2556                if ( $this->isCanonicalSettings( $canonical_settings ) ) {
    26                         return $canonical_settings;
     57                        return $this->normalizeSettings( $canonical_settings );
     58                }
     59
     60                $legacy_incash       = $product->get_meta( self::LEGACY_INCASH_META_KEY, true );
     61                $legacy_installments = $product->get_meta( self::LEGACY_INSTALLMENTS_META_KEY, true );
     62
     63                if ( '' === $legacy_incash && '' === $legacy_installments ) {
     64                        return null;
    2765                }
    2866
    2967                return $this->adapter->fromLegacyMeta(
    30                         $product->get_meta( self::LEGACY_INCASH_META_KEY, true ),
    31                         $product->get_meta( self::LEGACY_INSTALLMENTS_META_KEY, true )
     68                        $legacy_incash, $legacy_installments
    3269                );
    3370        }
    3471
    35         public function save( \WC_Product $product, array $settings ): bool {
     72        public function save( \WC_Product $product, array $settings, bool $persist = true ): bool {
     73                $current_settings = $this->getSettings( $product );
    3674                $canonical_settings = array(
    37                         'disable_incash'       => true === ( $settings['disable_incash'] ?? false ),
    38                         'disable_installments' => true === ( $settings['disable_installments'] ?? false ),
     75                        'schema_version'       => 1,
     76                        'disable_incash'       => array_key_exists( 'disable_incash', $settings )
     77                                ? true === $settings['disable_incash']
     78                                : $current_settings['disable_incash'],
     79                        'disable_installments' => array_key_exists( 'disable_installments', $settings )
     80                                ? true === $settings['disable_installments']
     81                                : $current_settings['disable_installments'],
    3982                );
    4083                $legacy_meta = $this->adapter->projectToLegacyMeta( $canonical_settings );
    … …  
    4386                $product->update_meta_data( self::LEGACY_INCASH_META_KEY, $legacy_meta[ self::LEGACY_INCASH_META_KEY ] );
    4487                $product->update_meta_data( self::LEGACY_INSTALLMENTS_META_KEY, $legacy_meta[ self::LEGACY_INSTALLMENTS_META_KEY ] );
     88                if ( $persist ) {
     89                        $product->save();
     90                        $saved_product = call_user_func( $this->product_reloader, (int) $product->get_id() );
     91                        if ( ! $saved_product instanceof \WC_Product ) {
     92                                return false;
     93                        }
     94                } else {
     95                        $saved_product = $product;
     96                }
    4597
    46                 return $canonical_settings === $product->get_meta( self::META_KEY, true )
    47                         && $legacy_meta[ self::LEGACY_INCASH_META_KEY ] === $product->get_meta( self::LEGACY_INCASH_META_KEY, true )
    48                         && $legacy_meta[ self::LEGACY_INSTALLMENTS_META_KEY ] === $product->get_meta( self::LEGACY_INSTALLMENTS_META_KEY, true );
     98                return $canonical_settings === $saved_product->get_meta( self::META_KEY, true )
     99                        && $legacy_meta[ self::LEGACY_INCASH_META_KEY ] === $saved_product->get_meta( self::LEGACY_INCASH_META_KEY, true )
     100                        && $legacy_meta[ self::LEGACY_INSTALLMENTS_META_KEY ] === $saved_product->get_meta( self::LEGACY_INSTALLMENTS_META_KEY, true );
    49101        }
    50102
    … …  
    55107                        && is_bool( $settings['disable_installments'] );
    56108        }
     109
     110        private function normalizeSettings( array $settings ): array {
     111                return array(
     112                        'schema_version'       => 1,
     113                        'disable_incash'       => $settings['disable_incash'],
     114                        'disable_installments' => $settings['disable_installments'],
     115                );
     116        }
    57117}
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Repositories/SettingsRepository.php

    r3627068 r3667117  
    3030        private $adapter;
    3131
    32         public function __construct( LegacySettingsAdapter $adapter ) {
    33                 $this->adapter = $adapter;
     32        /**
     33         * @var SettingsSanitizer
     34         */
     35        private $sanitizer;
     36
     37        public function __construct( LegacySettingsAdapter $adapter, ?SettingsSanitizer $sanitizer = null ) {
     38                $this->adapter   = $adapter;
     39                $this->sanitizer = $sanitizer ?? new SettingsSanitizer();
    3440        }
    3541
    3642        public function getSettings(): array {
    37                 $canonical = get_option( self::OPTION_NAME, array() );
    38 
    39                 if ( $this->isCanonicalDocument( $canonical ) ) {
    40                         return $canonical;
    41                 }
    42 
    43                 return $this->adapter->fromLegacyOptions( $this->getLegacyOptions() );
     43                return $this->getNormalizedSettings();
     44        }
     45
     46        /**
     47         * Returns a sanitized v2 document without migrating legacy or v1 storage.
     48         */
     49        public function getNormalizedSettings(): array {
     50                $canonical      = get_option( self::OPTION_NAME, null );
     51                $legacy_options = $this->getLegacyOptions();
     52                $has_persisted_darven_settings = null !== $canonical || $this->hasPersistedLegacySettings( $legacy_options );
     53
     54                if ( $this->isReadableDocument( $canonical ) ) {
     55                        return $this->normalizeDocument( $canonical, $has_persisted_darven_settings, $legacy_options );
     56                }
     57
     58                return $this->normalizeDocument( $this->adapter->fromLegacyOptions( $legacy_options ), $has_persisted_darven_settings, $legacy_options );
    4459        }
    4560
    … …  
    4762                $this->assertKnownSection( $section );
    4863
    49                 $settings = $this->getSettings();
     64                $settings = $this->getNormalizedSettings();
    5065
    5166                return $settings[ $section ];
    … …  
    5368
    5469        public function getYithDynamicPricingMode(): string {
    55                 $canonical                     = get_option( self::OPTION_NAME, null );
    56                 $has_persisted_darven_settings = null !== $canonical;
    57                 $legacy_options                 = array();
    58 
    59                 foreach ( self::LEGACY_OPTION_NAMES as $option_name ) {
    60                         $legacy_option = get_option( $option_name, null );
    61 
    62                         if ( null !== $legacy_option ) {
    63                                 $has_persisted_darven_settings = true;
    64                         }
    65 
    66                         $legacy_options[ $option_name ] = null === $legacy_option ? array() : $legacy_option;
    67                 }
    68 
    69                 $settings = $this->isCanonicalDocument( $canonical )
    70                         ? $canonical
    71                         : $this->adapter->fromLegacyOptions( $legacy_options );
    72 
    73                 $compatibility = isset( $settings['compatibility'] ) && is_array( $settings['compatibility'] )
    74                         ? $settings['compatibility']
    75                         : array();
    76 
    77                 $legacy_compatibility = $legacy_options['darven_epi_option_compatibility'];
    78 
    79                 if ( ! isset( $compatibility[ YithDynamicPricingMode::FIELD ] )
    80                         && is_array( $legacy_compatibility )
    81                         && isset( $legacy_compatibility[ YithDynamicPricingMode::LEGACY_FIELD ] ) ) {
    82                         $compatibility[ YithDynamicPricingMode::LEGACY_FIELD ] = $legacy_compatibility[ YithDynamicPricingMode::LEGACY_FIELD ];
    83                 }
    84 
    85                 return YithDynamicPricingMode::resolve( $compatibility, $has_persisted_darven_settings );
     70                $settings = $this->getNormalizedSettings();
     71
     72                return $settings['compatibility'][ YithDynamicPricingMode::FIELD ];
    8673        }
    8774
    … …  
    8976                $this->assertKnownSection( $section );
    9077
    91                 $settings                   = $this->getSettings();
    92                 $settings['schema_version'] = 1;
    93                 $settings[ $section ]       = $values;
     78                $settings             = $this->getNormalizedSettings();
     79                $settings[ $section ] = $values;
     80
     81                return $this->saveDocumentInternal( $settings, array( $section ), $deferred_legacy_option, array( $section ) );
     82        }
     83
     84        /**
     85         * Merges submitted sections with the normalized current state, stores v2,
     86         * and mirrors every legacy option.
     87         */
     88        public function saveDocument( array $document ): bool {
     89                $sections = array();
     90                foreach ( self::SECTION_NAMES as $section ) {
     91                        if ( isset( $document[ $section ] ) && is_array( $document[ $section ] ) ) {
     92                                $sections[] = $section;
     93                        }
     94                }
     95
     96                return $this->saveDocumentInternal( $document, $sections, '' );
     97        }
     98
     99        private function saveDocumentInternal( array $document, array $submitted_sections, string $deferred_legacy_option, array $replaced_sections = array() ): bool {
     100                $settings = $this->getNormalizedSettings();
     101
     102                foreach ( self::SECTION_NAMES as $section ) {
     103                        if ( isset( $document[ $section ] ) && is_array( $document[ $section ] ) ) {
     104                                $settings[ $section ] = in_array( $section, $replaced_sections, true )
     105                                        ? $document[ $section ]
     106                                        : array_merge( $settings[ $section ], $document[ $section ] );
     107                        }
     108                }
     109
     110                $settings = $this->normalizeDocument( $settings, true );
    94111
    95112                if ( ! $this->persistAndVerify( self::OPTION_NAME, $settings ) ) {
    … …  
    98115
    99116                return $this->persistLegacyOptions(
    100                         $this->adapter->projectToLegacyOptions( $settings, $this->getLegacyOptions() ),
    101                         $section,
    102                         $deferred_legacy_option
     117                        $this->adapter->projectToLegacyOptions( $settings, $this->getLegacyOptions() ), empty( $submitted_sections ) ? self::SECTION_NAMES : $submitted_sections, $deferred_legacy_option
    103118                );
    104119        }
    … …  
    116131        }
    117132
    118         private function isCanonicalDocument( $settings ): bool {
    119                 if ( ! is_array( $settings ) || ! isset( $settings['schema_version'] ) || 1 !== $settings['schema_version'] ) {
    120                         return false;
    121                 }
     133        private function isReadableDocument( $settings ): bool {
     134                if ( ! is_array( $settings ) || ! isset( $settings['schema_version'] ) || ! in_array( $settings['schema_version'], array( 1, 2 ), true ) ) {
     135                        return false;
     136        }
     137
     138        foreach ( self::SECTION_NAMES as $section ) {
     139                if ( ! array_key_exists( $section, $settings ) || ! is_array( $settings[ $section ] ) ) {
     140                        return false;
     141                }
     142        }
     143
     144                return true;
     145        }
     146
     147        private function normalizeDocument( array $document, bool $has_persisted_darven_settings, array $legacy_options = array() ): array {
     148                $normalized = array( 'schema_version' => 2 );
    122149
    123150                foreach ( self::SECTION_NAMES as $section ) {
    124                         if ( ! array_key_exists( $section, $settings ) || ! is_array( $settings[ $section ] ) ) {
    125                                 return false;
    126                         }
    127                 }
    128 
    129                 return true;
     151                        $values = isset( $document[ $section ] ) && is_array( $document[ $section ] ) ? $document[ $section ] : array();
     152                        if ( 'compatibility' === $section ) {
     153                                if ( ! isset( $values[ YithDynamicPricingMode::FIELD ] )
     154                                        && ! isset( $values[ YithDynamicPricingMode::LEGACY_FIELD ] )
     155                                        && isset( $legacy_options['darven_epi_option_compatibility'] )
     156                                        && is_array( $legacy_options['darven_epi_option_compatibility'] )
     157                                        && isset( $legacy_options['darven_epi_option_compatibility'][ YithDynamicPricingMode::LEGACY_FIELD ] ) ) {
     158                                        $values[ YithDynamicPricingMode::LEGACY_FIELD ] = $legacy_options['darven_epi_option_compatibility'][ YithDynamicPricingMode::LEGACY_FIELD ];
     159                                }
     160
     161                                $mode = YithDynamicPricingMode::resolve( $values, $has_persisted_darven_settings );
     162                                $normalized[ $section ] = array(
     163                                        YithDynamicPricingMode::FIELD => $mode,
     164                                );
     165                                continue;
     166                        }
     167
     168                        $normalized[ $section ] = $this->sanitizer->sanitizeSection( $section, $values );
     169                }
     170
     171                return $normalized;
    130172        }
    131173
    … …  
    134176
    135177                foreach ( self::LEGACY_OPTION_NAMES as $option_name ) {
    136                         $legacy_options[ $option_name ] = get_option( $option_name, array() );
     178                        $legacy_options[ $option_name ] = get_option( $option_name, null );
    137179                }
    138180
    139181                return $legacy_options;
     182        }
     183
     184        private function hasPersistedLegacySettings( array $legacy_options ): bool {
     185                foreach ( $legacy_options as $legacy_option ) {
     186                        if ( null !== $legacy_option ) {
     187                                return true;
     188                        }
     189                }
     190
     191                return false;
    140192        }
    141193
    … …  
    146198        }
    147199
    148         private function persistLegacyOptions( array $legacy_options, string $section, string $deferred_legacy_option ): bool {
     200        private function persistLegacyOptions( array $legacy_options, array $sections, string $deferred_legacy_option ): bool {
    149201                $failed_options = array();
    150202
    … …  
    161213                if ( ! empty( $failed_options ) ) {
    162214                        if ( ! $this->persistAndVerify(
    163                                 self::SYNC_STATE_OPTION,
    164                                 array(
    165                                         'pending_sections' => array( $section ),
     215                                self::SYNC_STATE_OPTION, array(
     216                                        'pending_sections' => $sections,
    166217                                        'failed_options'   => $failed_options,
    167218                                )
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Services/InstallmentPriceFormatter.php

    r3627068 r3667117  
    5757                );
    5858
    59                 if ( 'popup' === ( $this->general_settings['darven_epi_mode_of_view'] ?? '' ) ) {
    60                         $statement = $prefix
    61                                 . '<span class="darven-epi-installment-count">' . $number_of_installments . 'x de</span>'
    62                                 . '<span class="darven-epi-installment-price"> ' . wp_strip_all_tags( wc_price( $price_table[1] ) ) . '</span>'
    63                                 . $suffix;
     59                $mode = (string) ( $this->general_settings['darven_epi_mode_of_view'] ?? '' );
     60                $installment_count = sprintf(
     61                        /* translators: %1$s: number of installments. */
     62                        __( '%1$sx of', 'darven-multiplos-precos-informativos' ), $number_of_installments
     63                );
     64
     65                if ( 'popup' === $mode ) {
     66                        $statement = $this->getStatement(
     67                                $prefix, $installment_count, wp_strip_all_tags( wc_price( $price_table[1] ) ), $suffix
     68                        );
    6469
    6570                        return $this->markup_builder->div(
    6671                                'installments-price-statement darven-epi-installments-price-statement',
    67                                 $statement,
     72                                $statement . $this->getPopupMarkup( $price_table[0] ),
    6873                                'installments'
    6974                        );
    7075                }
    7176
    72                 if ( 'nofee' === ( $this->general_settings['darven_epi_mode_of_view'] ?? '' ) ) {
    73                         $statement = $prefix
    74                                 . '<span class="darven-epi-installment-count">' . $number_of_installments . 'x de</span>'
    75                                 . '<span class="darven-epi-installment-price"> ' . wp_strip_all_tags( wc_price( $installment_price ) ) . '</span>'
    76                                 . $suffix;
    77                         $popup_content = '<div class="messagepop pop darven-epi-installments-popup" aria-hidden="true">'
    78                                 . $price_table[0]
    79                                 . '</div>';
    80                         $popup_toggle = '<button type="button" class="darven-epi-installments-toggle" aria-expanded="false">'
    81                                 . (string) ( $this->general_settings['darven_epi_popup_text'] ?? '' )
    82                                 . '</button>';
     77                if ( 'nofee' === $mode ) {
     78                        $statement = $this->getStatement(
     79                                $prefix, $installment_count, wp_strip_all_tags( wc_price( $installment_price ) ), $suffix
     80                        );
    8381
    8482                        return $this->markup_builder->div(
    8583                                'installments-price-statement darven-epi-installments-price-statement',
    86                                 $statement . $popup_content . $popup_toggle,
     84                                $statement . $this->getPopupMarkup( $price_table[0] ),
    8785                                'installments'
    8886                        );
    8987                }
    9088
    91                 $statement = $prefix
    92                         . '<span class="darven-epi-installment-count">' . $number_of_installments . 'x de</span>'
    93                         . '<span class="darven-epi-installment-price"> ' . wp_strip_all_tags( wc_price( $price_table[1] ) ) . '</span>'
    94                         . $suffix;
     89                $statement = $this->getStatement(
     90                        $prefix, $installment_count, wp_strip_all_tags( wc_price( $price_table[1] ) ), $suffix
     91                );
    9592
    9693                return $this->markup_builder->div(
    … …  
    10198        }
    10299
     100        private function getStatement( string $prefix, string $count, string $price, string $suffix ): string {
     101                return sprintf(
     102                        '%s<span class="darven-epi-installment-count">%s</span><span class="darven-epi-installment-price"> %s</span>%s', $prefix, $count, $price, $suffix
     103                );
     104        }
     105
     106        private function getPopupMarkup( string $price_table ): string {
     107                $instance_id = $this->getPopupInstanceId();
     108                $dialog_id   = $instance_id . '-dialog';
     109                $title_id    = $instance_id . '-title';
     110                $popup_text  = wp_kses(
     111                        (string) ( $this->general_settings['darven_epi_popup_text'] ?? '' ),
     112                        array(
     113                                'br'   => array(),
     114                                'b'    => array(),
     115                                'em'   => array(),
     116                                'i'    => array(),
     117                                'span' => array(
     118                                        'class' => array(),
     119                                        'style' => array(),
     120                                ),
     121                        )
     122                );
     123                $popup_label = trim(
     124                        html_entity_decode( wp_strip_all_tags( $popup_text ), ENT_QUOTES | ENT_HTML5, 'UTF-8' )
     125                );
     126
     127                if ( '' === $popup_label ) {
     128                        $popup_label = __( 'View installment options', 'darven-multiplos-precos-informativos' );
     129                        $popup_text  = esc_html( $popup_label );
     130                }
     131
     132                $title       = esc_html( __( 'Installment options', 'darven-multiplos-precos-informativos' ) );
     133                $close_label = esc_attr( __( 'Close installment options', 'darven-multiplos-precos-informativos' ) );
     134
     135                $popup = '<div id="' . esc_attr( $dialog_id )
     136                        . '" class="messagepop pop darven-epi-installments-popup" hidden aria-hidden="true"'
     137                        . ' role="dialog" aria-modal="true" aria-labelledby="' . esc_attr( $title_id ) . '">'
     138                        . '<div class="darven-epi-installments-backdrop" aria-hidden="true"></div>'
     139                        . '<div class="darven-epi-installments-dialog" role="document">'
     140                        . '<h2 id="' . esc_attr( $title_id )
     141                        . '" class="screen-reader-text darven-epi-installments-title">' . $title . '</h2>'
     142                        . '<button type="button" class="darven-epi-installments-close" aria-label="' . $close_label . '">'
     143                        . '<span aria-hidden="true">&times;</span>'
     144                        . '</button>'
     145                        . '<div class="darven-epi-installments-table-wrap">' . $price_table . '</div>'
     146                        . '</div>'
     147                        . '</div>';
     148                $toggle = '<button type="button" class="darven-epi-installments-toggle" aria-expanded="false" aria-controls="'
     149                        . esc_attr( $dialog_id ) . '" aria-label="' . esc_attr( $popup_label ) . '">' . $popup_text . '</button>';
     150
     151                return $popup . $toggle;
     152        }
     153
     154        private function getPopupInstanceId(): string {
     155                $unique_id = function_exists( 'wp_generate_uuid4' )
     156                ? wp_generate_uuid4()
     157                : uniqid( '', true );
     158
     159                return 'darven-epi-installments-' . $unique_id;
     160        }
     161
    103162        public function getPriceTable( float $price ): array {
    104163                $install_count = $this->getInstallmentData( $price )['table_count'];
    … …  
    108167                if ( ! empty( $this->general_settings['darven_epi_installments_interest_fee_is_table_enabled'] ) ) {
    109168                        $customised_values = array_map(
    110                                 static function ( $value ): float {
    111                                         $value = str_replace( ',', '.', trim( $value ) );
    112 
    113                                         return is_numeric( $value ) ? (float) $value : 0.0;
    114                                 },
     169                        static function ( $value ): float {
     170                                $value = str_replace( ',', '.', trim( $value ) );
     171
     172                                return is_numeric( $value ) ? (float) $value : 0.0;
     173                        },
    115174                                explode( '|', (string) ( $this->general_settings['darven_epi_installments_interest_fee_table'] ?? '' ) )
    116175                        );
    117                         $interest_fee_from = max( 1, (int) ( $this->general_settings['darven_epi_installments_interest_fee_from'] ?? 0 ) );
     176                        $interest_fee_from = (int) ( $this->general_settings['darven_epi_installments_interest_fee_from'] ?? 0 );
    118177
    119178                        for ( $installment = 1; $installment <= $install_count; $installment++ ) {
    120179                                $interest_rate = 0.0;
    121180
    122                                 if ( $installment >= $interest_fee_from ) {
     181                                if ( 0 !== $interest_fee_from && $installment >= $interest_fee_from ) {
    123182                                        $interest_index = $installment - $interest_fee_from;
    124183                                        $interest_rate  = $customised_values[ $interest_index ] ?? 0.0;
    … …  
    128187                                $installment_price   = $total_with_interest / $installment;
    129188                                $html_result        .= '<tr>';
    130                                 $html_result        .= '<td>' . $installment . 'x de</td><td>' . wc_price( $installment_price ) . '</td>';
     189                                $installment_label   = sprintf(
     190                                /* translators: %1$s: number of installments. */
     191                                __( '%1$sx of', 'darven-multiplos-precos-informativos' ), $installment
     192                                );
     193                                $html_result        .= '<td>' . $installment_label . '</td><td>' . wc_price( $installment_price ) . '</td>';
    131194                                $html_result        .= '</tr>';
    132195                        }
    … …  
    145208                                if ( $first_install ) {
    146209                                        $price_for_interest = ( $price_for_interest
    147                                                 * (float) ( $this->general_settings['darven_epi_installments_interest_fee_first_install'] ?? 0 ) / 100 )
     210                                        * (float) ( $this->general_settings['darven_epi_installments_interest_fee_first_install'] ?? 0 ) / 100 )
    148211                                                + $price_for_interest;
    149212                                        $first_install = false;
    … …  
    152215                                $installment_price = $this->getTaxCalculation( $price_for_interest, 'second_period', $installment );
    153216                                $html_result      .= '<td>' . $installment . 'x</td><td>' . wc_price( $installment_price )
    154                                         . '  = ' . wc_price( $installment_price * $installment ) . '</td>';
     217                                . '  = ' . wc_price( $installment_price * $installment ) . '</td>';
    155218                        } else {
    156219                                $installment_price = $price_for_interest / $installment;
    … …  
    223286
    224287                if (
    225                         $price_count > $interest_fee_from
    226                         && $display_count > $interest_fee_from
    227                         && 'nofee' === ( $this->general_settings['darven_epi_mode_of_view'] ?? '' )
     288                0 !== $interest_fee_from
     289                && $price_count >= $interest_fee_from
     290                && $display_count >= $interest_fee_from
     291                && 'nofee' === ( $this->general_settings['darven_epi_mode_of_view'] ?? '' )
    228292                ) {
    229293                        $price_count   = $interest_fee_from - 1;
    … …  
    232296
    233297                return array(
    234                         'table_count'   => $table_count,
    235                         'display_count' => $display_count,
    236                         'price_count'   => $price_count,
     298                'table_count'   => $table_count,
     299                'display_count' => $display_count,
     300                'price_count'   => $price_count,
    237301                );
    238302        }
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Setup/Plugin.php

    r3627068 r3667117  
    55use Darven\ExtraPriceInfo\Admin\Assets as AdminAssets;
    66use Darven\ExtraPriceInfo\Admin\ProductOptionsController;
    7 use Darven\ExtraPriceInfo\Admin\SettingsPage;
     7use Darven\ExtraPriceInfo\Admin\ReactPage;
     8use Darven\ExtraPriceInfo\Admin\SettingsRestController;
    89use Darven\ExtraPriceInfo\Compatibility\LegacyProductSettingsAdapter;
    910use Darven\ExtraPriceInfo\Compatibility\LegacySettingsAdapter;
    1011use Darven\ExtraPriceInfo\Frontend\Assets as FrontendAssets;
     12use Darven\ExtraPriceInfo\Frontend\InlineStyles;
    1113use Darven\ExtraPriceInfo\Repositories\ProductSettingsRepository;
    1214use Darven\ExtraPriceInfo\Repositories\SettingsRepository;
    … …  
    3234                        $product_settings
    3335                );
    34                 $settings_page     = new SettingsPage();
     36                $settings_page     = new ReactPage( $settings );
     37                $settings_rest     = new SettingsRestController( $settings, $product_settings );
    3538                $product_options   = new ProductOptionsController( $product_settings );
    3639                $admin_assets      = new AdminAssets();
    37                 $frontend_assets   = new FrontendAssets();
     40                $frontend_assets   = new FrontendAssets( new InlineStyles( $settings ) );
    3841                $text_domain_loader = new TextDomainLoader();
    3942
    … …  
    4447
    4548                $settings_page->register();
     49                add_action( 'rest_api_init', array( $settings_rest, 'register' ) );
    4650                $product_options->register();
    4751        }
  • darven-multiplos-precos-informativos/tags/4.0.0/src/Setup/TextDomainLoader.php

    r3627068 r3667117  
    66        public function load(): void {
    77                load_plugin_textdomain(
    8                         'darven-epi',
    9                         false,
    10                         dirname( plugin_basename( DARVEN_EPI_DIR_PATH . 'darven-extra-price-info.php' ) ) . '/i18n/languages/'
     8                        \DARVEN_EPI_LANGUAGE_DOMAIN, false, dirname( plugin_basename( \DARVEN_EPI_DIR_PATH . 'darven-extra-price-info.php' ) ) . '/languages/'
    119                );
    1210        }
  • darven-multiplos-precos-informativos/tags/4.0.0/vendor/autoload.php

    r3627068 r3667117  
    2020require_once __DIR__ . '/composer/autoload_real.php';
    2121
    22 return ComposerAutoloaderInit20e0eb45e47b4ba6e645250a31f9ffef::getLoader();
     22return ComposerAutoloaderInitdb32075ee5d847d9dbbfd29562c8f5c8::getLoader();
  • darven-multiplos-precos-informativos/tags/4.0.0/vendor/composer/autoload_classmap.php

    r3627068 r3667117  
    99    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    1010    'Darven\\ExtraPriceInfo\\Admin\\Assets' => $baseDir . '/src/Admin/Assets.php',
    11     'Darven\\ExtraPriceInfo\\Admin\\LegacySettingsSync' => $baseDir . '/src/Admin/LegacySettingsSync.php',
    1211    'Darven\\ExtraPriceInfo\\Admin\\ProductOptionsController' => $baseDir . '/src/Admin/ProductOptionsController.php',
    13     'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\CompatibilityFields' => $baseDir . '/src/Admin/SettingsFields/CompatibilityFields.php',
    14     'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\DisplayFields' => $baseDir . '/src/Admin/SettingsFields/DisplayFields.php',
    15     'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\GeneralFields' => $baseDir . '/src/Admin/SettingsFields/GeneralFields.php',
    16     'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\PositionsFields' => $baseDir . '/src/Admin/SettingsFields/PositionsFields.php',
     12    'Darven\\ExtraPriceInfo\\Admin\\ReactPage' => $baseDir . '/src/Admin/ReactPage.php',
    1713    'Darven\\ExtraPriceInfo\\Admin\\SettingsPage' => $baseDir . '/src/Admin/SettingsPage.php',
     14    'Darven\\ExtraPriceInfo\\Admin\\SettingsRestController' => $baseDir . '/src/Admin/SettingsRestController.php',
    1815    'Darven\\ExtraPriceInfo\\Compatibility\\LegacyProductSettingsAdapter' => $baseDir . '/src/Compatibility/LegacyProductSettingsAdapter.php',
    1916    'Darven\\ExtraPriceInfo\\Compatibility\\LegacySettingsAdapter' => $baseDir . '/src/Compatibility/LegacySettingsAdapter.php',
    … …  
    2320    'Darven\\ExtraPriceInfo\\Repositories\\ProductSettingsRepository' => $baseDir . '/src/Repositories/ProductSettingsRepository.php',
    2421    'Darven\\ExtraPriceInfo\\Repositories\\SettingsRepository' => $baseDir . '/src/Repositories/SettingsRepository.php',
     22    'Darven\\ExtraPriceInfo\\Repositories\\SettingsSanitizer' => $baseDir . '/src/Repositories/SettingsSanitizer.php',
    2523    'Darven\\ExtraPriceInfo\\Services\\CashPriceFormatter' => $baseDir . '/src/Services/CashPriceFormatter.php',
    2624    'Darven\\ExtraPriceInfo\\Services\\FinalPriceFormatter' => $baseDir . '/src/Services/FinalPriceFormatter.php',
  • darven-multiplos-precos-informativos/tags/4.0.0/vendor/composer/autoload_real.php

    r3627068 r3667117  
    33// autoload_real.php @generated by Composer
    44
    5 class ComposerAutoloaderInit20e0eb45e47b4ba6e645250a31f9ffef
     5class ComposerAutoloaderInitdb32075ee5d847d9dbbfd29562c8f5c8
    66{
    77    private static $loader;
    … …  
    2525        require __DIR__ . '/platform_check.php';
    2626
    27         spl_autoload_register(array('ComposerAutoloaderInit20e0eb45e47b4ba6e645250a31f9ffef', 'loadClassLoader'), true, true);
     27        spl_autoload_register(array('ComposerAutoloaderInitdb32075ee5d847d9dbbfd29562c8f5c8', 'loadClassLoader'), true, true);
    2828        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
    29         spl_autoload_unregister(array('ComposerAutoloaderInit20e0eb45e47b4ba6e645250a31f9ffef', 'loadClassLoader'));
     29        spl_autoload_unregister(array('ComposerAutoloaderInitdb32075ee5d847d9dbbfd29562c8f5c8', 'loadClassLoader'));
    3030
    3131        require __DIR__ . '/autoload_static.php';
    32         call_user_func(\Composer\Autoload\ComposerStaticInit20e0eb45e47b4ba6e645250a31f9ffef::getInitializer($loader));
     32        call_user_func(\Composer\Autoload\ComposerStaticInitdb32075ee5d847d9dbbfd29562c8f5c8::getInitializer($loader));
    3333
    3434        $loader->register(true);
  • darven-multiplos-precos-informativos/tags/4.0.0/vendor/composer/autoload_static.php

    r3627068 r3667117  
    55namespace Composer\Autoload;
    66
    7 class ComposerStaticInit20e0eb45e47b4ba6e645250a31f9ffef
     7class ComposerStaticInitdb32075ee5d847d9dbbfd29562c8f5c8
    88{
    99    public static $prefixLengthsPsr4 = array (
    … …  
    2424        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
    2525        'Darven\\ExtraPriceInfo\\Admin\\Assets' => __DIR__ . '/../..' . '/src/Admin/Assets.php',
    26         'Darven\\ExtraPriceInfo\\Admin\\LegacySettingsSync' => __DIR__ . '/../..' . '/src/Admin/LegacySettingsSync.php',
    2726        'Darven\\ExtraPriceInfo\\Admin\\ProductOptionsController' => __DIR__ . '/../..' . '/src/Admin/ProductOptionsController.php',
    28         'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\CompatibilityFields' => __DIR__ . '/../..' . '/src/Admin/SettingsFields/CompatibilityFields.php',
    29         'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\DisplayFields' => __DIR__ . '/../..' . '/src/Admin/SettingsFields/DisplayFields.php',
    30         'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\GeneralFields' => __DIR__ . '/../..' . '/src/Admin/SettingsFields/GeneralFields.php',
    31         'Darven\\ExtraPriceInfo\\Admin\\SettingsFields\\PositionsFields' => __DIR__ . '/../..' . '/src/Admin/SettingsFields/PositionsFields.php',
     27        'Darven\\ExtraPriceInfo\\Admin\\ReactPage' => __DIR__ . '/../..' . '/src/Admin/ReactPage.php',
    3228        'Darven\\ExtraPriceInfo\\Admin\\SettingsPage' => __DIR__ . '/../..' . '/src/Admin/SettingsPage.php',
     29        'Darven\\ExtraPriceInfo\\Admin\\SettingsRestController' => __DIR__ . '/../..' . '/src/Admin/SettingsRestController.php',
    3330        'Darven\\ExtraPriceInfo\\Compatibility\\LegacyProductSettingsAdapter' => __DIR__ . '/../..' . '/src/Compatibility/LegacyProductSettingsAdapter.php',
    3431        'Darven\\ExtraPriceInfo\\Compatibility\\LegacySettingsAdapter' => __DIR__ . '/../..' . '/src/Compatibility/LegacySettingsAdapter.php',
    … …  
    3835        'Darven\\ExtraPriceInfo\\Repositories\\ProductSettingsRepository' => __DIR__ . '/../..' . '/src/Repositories/ProductSettingsRepository.php',
    3936        'Darven\\ExtraPriceInfo\\Repositories\\SettingsRepository' => __DIR__ . '/../..' . '/src/Repositories/SettingsRepository.php',
     37        'Darven\\ExtraPriceInfo\\Repositories\\SettingsSanitizer' => __DIR__ . '/../..' . '/src/Repositories/SettingsSanitizer.php',
    4038        'Darven\\ExtraPriceInfo\\Services\\CashPriceFormatter' => __DIR__ . '/../..' . '/src/Services/CashPriceFormatter.php',
    4139        'Darven\\ExtraPriceInfo\\Services\\FinalPriceFormatter' => __DIR__ . '/../..' . '/src/Services/FinalPriceFormatter.php',
    … …  
    5149    {
    5250        return \Closure::bind(function () use ($loader) {
    53             $loader->prefixLengthsPsr4 = ComposerStaticInit20e0eb45e47b4ba6e645250a31f9ffef::$prefixLengthsPsr4;
    54             $loader->prefixDirsPsr4 = ComposerStaticInit20e0eb45e47b4ba6e645250a31f9ffef::$prefixDirsPsr4;
    55             $loader->classMap = ComposerStaticInit20e0eb45e47b4ba6e645250a31f9ffef::$classMap;
     51            $loader->prefixLengthsPsr4 = ComposerStaticInitdb32075ee5d847d9dbbfd29562c8f5c8::$prefixLengthsPsr4;
     52            $loader->prefixDirsPsr4 = ComposerStaticInitdb32075ee5d847d9dbbfd29562c8f5c8::$prefixDirsPsr4;
     53            $loader->classMap = ComposerStaticInitdb32075ee5d847d9dbbfd29562c8f5c8::$classMap;
    5654
    5755        }, null, ClassLoader::class);
  • darven-multiplos-precos-informativos/tags/4.0.0/vendor/composer/platform_check.php

    r3627068 r3667117  
    55$issues = array();
    66
    7 if (!(PHP_VERSION_ID >= 70400)) {
    8     $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
     7if (!(PHP_VERSION_ID >= 80000)) {
     8    $issues[] = 'Your Composer dependencies require a PHP version ">= 8.0.0". You are running ' . PHP_VERSION . '.';
    99}
    1010
Note: See TracChangeset for help on using the changeset viewer.