Plugin Directory

Changeset 3354315


Ignore:
Timestamp:
09/02/2025 03:16:32 AM (7 months ago)
Author:
bibliatodo
Message:

actualizacion

Location:
verselinker
Files:
70 added
2 deleted
8 edited

Legend:

Unmodified
Added
Removed
  • verselinker/trunk/assets/js/admin-script.js

    r3232333 r3354315  
    8888        });
    8989});
     90
     91(function(){
     92  'use strict';
     93
     94  function $(sel){ return document.querySelector(sel); }
     95  function setText(el, s){ el.textContent = s == null ? '' : String(s); }
     96  // Sólo letras, números, guion y guion_bajo (defensa en profundidad para values)
     97  function sanitizeValue(v){ return String(v).replace(/[^\w-]/g, ''); }
     98
     99  document.addEventListener('DOMContentLoaded', function(){
     100    var input   = $('#verselinker_language_search');
     101    var select  = $('#verselinker_language');
     102    var vSelect = $('#verselinker_version');
     103    var counter = $('#verselinker_language_counter');
     104
     105    if(!select || !vSelect) return;
     106
     107    var LANGS  = (window.verselinkerData && Array.isArray(verselinkerData.languages)) ? verselinkerData.languages : [];
     108    var LABELS = (window.verselinkerData && verselinkerData.labels) || {tb:'Complete Bibles',at:'Old Testament Only',nt:'New Testament Only',no_versions:'No versions found.'};
     109
     110    var ALL = LANGS.map(function(l){
     111      return { value: String(l.abreviacion||'').trim(), label: String(l.nombre||'').trim() };
     112    });
     113    if (!ALL.length) {
     114      ALL = Array.prototype.map.call(select.options, function(op){
     115        return { value: op.value, label: op.text };
     116      });
     117    }
     118
     119    function rebuildVersionSelectFor(langCode){
     120      while(vSelect.firstChild){ vSelect.removeChild(vSelect.firstChild); }
     121
     122      var lang = LANGS.find(function(l){ return String(l.abreviacion) === String(langCode); });
     123      if(!lang || !Array.isArray(lang.versiones) || !lang.versiones.length){
     124        var no = document.createElement('option');
     125        no.value = '';
     126        setText(no, LABELS.no_versions || 'No versions found.');
     127        vSelect.appendChild(no);
     128        return;
     129      }
     130
     131      var order = ['tb','at','nt'];
     132      var firstValue = null;
     133
     134      order.forEach(function(cat){
     135        var list = lang.versiones.filter(function(v){ return v.categoria === cat; });
     136        if(!list.length) return;
     137
     138        var og = document.createElement('optgroup');
     139        og.label = LABELS[cat] || cat.toUpperCase();
     140
     141        list.forEach(function(v){
     142          var op = document.createElement('option');
     143          op.value = sanitizeValue(v.abreviacion);
     144          setText(op, v.nombre_version);
     145          if(firstValue === null) firstValue = op.value;
     146          og.appendChild(op);
     147        });
     148
     149        vSelect.appendChild(og);
     150      });
     151
     152      if (!vSelect.value && firstValue !== null){
     153        vSelect.value = firstValue; // evita guardar versión de otro idioma
     154      }
     155    }
     156
     157    function render(list){
     158      var before = select.value;
     159      var hadCurrent = false;
     160      while(select.options.length){ select.remove(0); }
     161
     162      list.forEach(function(it){
     163        var opt = document.createElement('option');
     164        opt.value = sanitizeValue(it.value);
     165        setText(opt, it.label);
     166        if (opt.value === before){ opt.selected = true; hadCurrent = true; }
     167        select.add(opt);
     168      });
     169
     170      if (!hadCurrent && select.options.length){
     171        select.selectedIndex = 0;
     172      }
     173
     174      var after = select.value;
     175      if (after !== before){
     176        rebuildVersionSelectFor(after);
     177      }
     178
     179      if (counter){
     180        counter.textContent = list.length + ' ' + (list.length === 1 ? 'result' : 'results');
     181      }
     182    }
     183
     184    function filter(q){
     185      q = String(q||'').toLowerCase().trim();
     186      if (!q){ render(ALL); return; }
     187      var parts = q.split(/\s+/);
     188      var out = ALL.filter(function(it){
     189        var hay = (it.label + ' ' + it.value).toLowerCase();
     190        return parts.every(function(p){ return hay.indexOf(p) !== -1; });
     191      });
     192      render(out);
     193    }
     194
     195    // inicial
     196    render(ALL);
     197    rebuildVersionSelectFor(select.value);
     198
     199    // eventos
     200    var t;
     201    if (input){
     202      input.addEventListener('input', function(){
     203        clearTimeout(t);
     204        var q = this.value;
     205        t = setTimeout(function(){ filter(q); }, 120);
     206      });
     207      input.addEventListener('keydown', function(e){
     208        if (e.key === 'Enter'){
     209          var first = select.options[0];
     210          if (first){
     211            select.value = first.value;
     212            select.dispatchEvent(new Event('change'));
     213            this.value = first.text + ' (' + first.value + ')';
     214          }
     215          e.preventDefault();
     216        }
     217      });
     218    }
     219
     220    select.addEventListener('change', function(){
     221      rebuildVersionSelectFor(this.value);
     222      if (input) {
     223        var op = select.options[select.selectedIndex];
     224        if (op){ input.value = op.text + ' (' + op.value + ')'; }
     225      }
     226    });
     227  });
     228})();
  • verselinker/trunk/includes/admin-settings.php

    r3238438 r3354315  
    1717        'default'           => 'kjv'
    1818    ));
     19    register_setting('verselinker_options', 'verselinker_version', array(
     20        'type'              => 'string',
     21        'sanitize_callback' => 'verselinker_sanitize_version_for_language',
     22        'default'           => ''
     23    ));
     24
    1925    register_setting(
    2026        'verselinker_options',
  • verselinker/trunk/includes/helpers.php

    r3232333 r3354315  
    6969    return (in_array($input, array(true, 'true', '1', 'on', 'yes'), true));
    7070}
     71
     72
     73// Evita usar $_POST directamente y satisface el chequeo de nonce.
     74add_filter('pre_update_option_verselinker_language', 'verselinker_capture_language_before_update', 10, 3);
     75function verselinker_capture_language_before_update($new_value, $old_value, $option) {
     76    // options.php ya valida nonce; aun así comprobamos capacidad.
     77    if ( ! current_user_can('manage_options') ) {
     78        return $old_value;
     79    }
     80    // Desescapar + sanear
     81    $GLOBALS['verselinker_pending_language'] = sanitize_text_field( wp_unslash( $new_value ) );
     82    return $GLOBALS['verselinker_pending_language'];
     83}
     84
     85function verselinker_sanitize_version_for_language( $input ) {
     86    $input = sanitize_text_field( wp_unslash( $input ) );
     87
     88    // Idioma que se está guardando en esta misma petición (si existe),
     89    // si no, usamos el que ya está almacenado.
     90    $lang = '';
     91    if ( ! empty( $GLOBALS['verselinker_pending_language'] ) ) {
     92        $lang = sanitize_text_field( $GLOBALS['verselinker_pending_language'] );
     93    } else {
     94        $lang = sanitize_text_field( get_option( 'verselinker_language', 'en' ) );
     95    }
     96
     97    $data = verselinker_fetch_languages_json();
     98    if ( ! $data || empty( $data['languages'] ) || ! is_array( $data['languages'] ) ) {
     99        return '';
     100    }
     101
     102    foreach ( $data['languages'] as $l ) {
     103        if ( empty( $l['abreviacion'] ) || $l['abreviacion'] !== $lang ) {
     104            continue;
     105        }
     106        if ( ! empty( $l['versiones'] ) && is_array( $l['versiones'] ) ) {
     107            // ¿La versión enviada pertenece a este idioma?
     108            foreach ( $l['versiones'] as $v ) {
     109                if ( isset( $v['abreviacion'] ) && $v['abreviacion'] === $input ) {
     110                    return $input;
     111                }
     112            }
     113            // Fallback: primera versión disponible del idioma
     114            return isset( $l['versiones'][0]['abreviacion'] )
     115                ? sanitize_text_field( $l['versiones'][0]['abreviacion'] )
     116                : '';
     117        }
     118    }
     119    return '';
     120}
  • verselinker/trunk/includes/scripts.php

    r3238438 r3354315  
    6767    }
    6868
     69    // ➕ Pasar idiomas al JS para filtrar sin AJAX
     70    $idiomas_data = verselinker_fetch_languages_json();
     71    $langs = isset($idiomas_data['languages']) && is_array($idiomas_data['languages']) ? $idiomas_data['languages'] : [];
     72
     73     global $verseLinkerTranslations;
     74    $labels = [
     75        'tb'          => esc_html($verseLinkerTranslations['tb'] ?? 'Complete Bibles'),
     76        'at'          => esc_html($verseLinkerTranslations['solo_at'] ?? 'Old Testament Only'),
     77        'nt'          => esc_html($verseLinkerTranslations['solo_nt'] ?? 'New Testament Only'),
     78        'no_versions' => esc_html($verseLinkerTranslations['no_versions_found'] ?? 'No versions found.')
     79    ];
     80
     81
    6982    // Cargar el script de administración
    7083    wp_enqueue_script(
     
    7790
    7891    // Pasar datos dinámicos al script
    79     wp_localize_script('verselinker-admin-script', 'verselinkerData', array(
    80         'json_url' => esc_url(VERSELINKER_URL . 'json/idiomas.json'), // Ruta del JSON
    81     ));
     92    wp_localize_script('verselinker-admin-script', 'verselinkerData', [
     93        'json_url' => esc_url(VERSELINKER_URL . 'json/idiomas.json'),
     94        'languages'=> $langs,
     95        'labels'   => $labels,
     96        // opcional, por si los quieres en JS:
     97        'selected' => [
     98            'lang' => sanitize_text_field(get_option('verselinker_language', 'en')),
     99            'ver'  => sanitize_text_field(get_option('verselinker_version', ''))
     100        ],
     101    ]);
    82102
    83103    // Cargar el script para detección de referencias bíblicas
  • verselinker/trunk/includes/templates/admin-options.php

    r3238438 r3354315  
    2020                </th>
    2121                <td>
     22                     <!-- 🔎 BUSCADOR -->
     23                    <input type="text"
     24                        id="verselinker_language_search"
     25                        placeholder="<?php echo esc_attr($verseLinkerTranslations['search_language_placeholder'] ?? 'Type to search language… (name or code)'); ?>"
     26                        style="width:100%;padding:8px 10px;margin-bottom:8px;font-size:1em;max-width: 20rem;" />
     27
    2228                    <select name="verselinker_language" id="verselinker_language" style="width: 100%; padding: 10px; font-size: 1em;">
    2329                        <?php foreach ($idiomas['languages'] as $idioma) : ?>
     
    2834                        <?php endforeach; ?>
    2935                    </select>
     36
     37                    <!-- contador opcional de resultados -->
     38                    <small id="verselinker_language_counter" style="display:block;margin-top:6px;color:#666"></small>
    3039                </td>
    3140            </tr>
  • verselinker/trunk/includes/translations/en.php

    r3238438 r3354315  
    3535    'data_trueLinks' => 'Replace existing Bible reference URLs',
    3636    'data_trueLinks_description' => 'Enable this option to automatically replace existing Bible reference URLs with the VerseLinker format. By doing so, all references on your site will benefit from the tooltip feature and other functions. If you disable this checkbox, VerseLinker will not convert any existing URLs, allowing you to preserve the original links or use a different referencing system. Only uncheck this box if you truly want to keep your current URLs intact.',
     37    'search_language_placeholder' => 'Type to search language… (name or code)222',
     38
    3739];
  • verselinker/trunk/readme.txt

    r3354095 r3354315  
    44Tags: bible, Bible references, Bible Links, RefTagger, ScriptTagger
    55Tested up to: 6.8
    6 Stable tag: 1.1.3
     6Stable tag: 1.1.4
    77License: GPLv2 or later
    88License URI: http://www.gnu.org/licenses/gpl-2.0.html
  • verselinker/trunk/verselinker.php

    r3354091 r3354315  
    44 * Plugin URI: https://wordpress.org/plugins/verselinker/
    55 * Description: Automatically link Bible verses in your WordPress content. VerseLinker detects scripture references and transforms them into interactive links, allowing users to view verse text directly on your site or access additional context on Bibliatodo.com. Enhance your content with seamless Bible integration!
    6  * Version: 1.1.3
     6 * Version: 1.1.4
    77 * Requires at least: 5.2
    88 * Author: BibliaTodo.com
     
    2020define('VERSELINKER_PATH', plugin_dir_path(__FILE__));
    2121define('VERSELINKER_URL', plugin_dir_url(__FILE__));
    22 define('VERSELINKER_VERSION', '1.1.3');
     22define('VERSELINKER_VERSION', '1.1.4');
    2323
    2424// Incluir archivos
Note: See TracChangeset for help on using the changeset viewer.