Plugin Directory

Changeset 3301857


Ignore:
Timestamp:
05/27/2025 11:30:34 PM (10 months ago)
Author:
Milmor
Message:

Update to version 9.0 from GitHub

Location:
amministrazione-trasparente
Files:
10 added
10 edited
1 copied

Legend:

Unmodified
Added
Removed
  • amministrazione-trasparente/tags/9.0/README.md

    r3301628 r3301857  
    77## Credits
    88
    9 Copyright © 2012-2024 **Marco Milesi**
     9Copyright © 2012-2025 **Marco Milesi**
    1010www.marcomilesi.com - www.wpgov.it
  • amministrazione-trasparente/tags/9.0/amministrazionetrasparente.php

    r3301628 r3301857  
    44Plugin URI: https://wordpress.org/plugins/amministrazione-trasparente/
    55Description: Soluzione completa per la pubblicazione online dei documenti ai sensi del D.lgs. n. 33 del 14/03/2013
    6 Version: 8.1.4
     6Version: 9.0
    77Author: Marco Milesi
    88Author Email: [email protected]
     
    1212
    1313add_action( 'init', function() {
    14    
     14  // Only register if the option is enabled
     15  if ( !at_option('enable_ucc') ) {
     16    return;
     17  }
    1518  if ( !( function_exists('wpgov_register_taxonomy_areesettori') ) ){
    1619    $labels = array(
     
    4447      'query_var' => true
    4548    );
    46     register_taxonomy( 'areesettori', array('incarico', 'spesa', 'avcp' ), $args );
    47   }
    48 });
    49 
    50 add_action('init', function(){
    51   if ( at_option( 'enable_ucc' ) ) {
    52     register_taxonomy_for_object_type( 'areesettori', 'amm-trasparente' );
    53   }
    54 }, 200);
     49    register_taxonomy( 'areesettori', array('incarico', 'spesa', 'avcp', 'amm-trasparente' ), $args );
     50  }
     51});
    5552
    5653add_action( 'init', function() {
     
    313310$AmministrazioneTrasparente_Backend = new AmministrazioneTrasparente_Backend();
    314311
     312add_action( 'admin_enqueue_scripts', function( $hook ) {
     313    // Only load on your plugin settings page
     314    if ( isset($_GET['page']) && $_GET['page'] === 'wpgov_at' ) {
     315        wp_enqueue_script( 'jquery-ui-sortable' );
     316    }
     317});
     318
    315319add_action( 'admin_menu', function() {
    316   add_submenu_page( 'edit.php?post_type=amm-trasparente', 'Impostazioni', 'Impostazioni', 'manage_options', 'wpgov_at', function() {
    317     include(plugin_dir_path(__FILE__) . 'settings.php');
    318   } );
     320
     321    // Dashboard submenu (edit_amm-trasparente)
     322    $post_type_object = get_post_type_object('amm-trasparente');
     323    $capability = $post_type_object && isset($post_type_object->cap->edit_posts)
     324        ? $post_type_object->cap->edit_posts
     325        : 'edit_posts';
     326
     327    add_submenu_page(
     328        'edit.php?post_type=amm-trasparente',
     329        'Dashboard Amministrazione Trasparente',
     330        'Revisione',
     331        $capability,
     332        'at_tipologie_dashboard',
     333        function() {
     334            include(plugin_dir_path(__FILE__) . 'dashboard.php');
     335        }
     336    );
     337
     338    // Impostazioni submenu (manage_options)
     339    add_submenu_page(
     340        'edit.php?post_type=amm-trasparente',
     341        'Impostazioni',
     342        'Impostazioni',
     343        'manage_options',
     344        'wpgov_at',
     345        function() {
     346            include(plugin_dir_path(__FILE__) . 'settings.php');
     347        }
     348    );   
    319349} );
    320350
     
    349379}
    350380
    351 ?>
     381add_action('pre_get_posts', function($query) {
     382    if (
     383        is_admin() &&
     384        $query->is_main_query() &&
     385        isset($_GET['post_type']) &&
     386        $_GET['post_type'] === 'amm-trasparente' &&
     387        isset($_GET['at_older_than']) &&
     388        is_numeric($_GET['at_older_than'])
     389    ) {
     390        $years = intval($_GET['at_older_than']);
     391        $date = date('Y-m-d', strtotime('-' . $years . ' years'));
     392        $query->set('date_query', [
     393            [
     394                'column' => 'post_date',
     395                'before' => $date,
     396            ]
     397        ]);
     398    }
     399});
     400
     401// Breadcrumb filter for Design Comuni WordPress theme
     402add_filter( 'dci_get_breadcrumb_items', function( $items ) {
     403   
     404    if ( is_tax( array( 'tipologie' ) ) ) {
     405        // Add home link as first item
     406        $items[] = "<a href='" . home_url() . "'>" . __('Home', 'design-comuni-italia') . "</a>";
     407
     408        $term = get_queried_object();
     409        if ( $term && isset( $term->term_id ) ) {
     410            $group = function_exists('at_getGroupNameByTerm') ? at_getGroupNameByTerm( $term->term_id ) : '';
     411
     412            if ( at_option( 'page_id' ) ) {
     413                $items[] = "<a href='" . get_permalink( at_option( 'page_id' ) ) . "'>" . get_the_title( at_option( 'page_id' ) ) . "</a>";
     414                $items[] = '<a href="' . get_permalink( at_option( 'page_id' ) ) . '#' . sanitize_title( $group ) . '">' . $group . '</a>';
     415            }
     416            $taxonomy = get_queried_object();
     417            $items[] = $taxonomy->name;
     418            return $items;
     419        }
     420    } else if ( get_post_type() == 'amm-trasparente' ) {
     421        // Add home link as first item
     422        $items[] = "<a href='" . home_url() . "'>" . __('Home', 'design-comuni-italia') . "</a>";
     423       
     424        $terms = get_the_terms( get_the_ID(), 'tipologie' );
     425        if ( $terms && !is_wp_error( $terms ) ) {
     426            $group = function_exists('at_getGroupNameByTerm') ? at_getGroupNameByTerm( $terms[0]->term_id ) : '';
     427
     428            if ( at_option( 'page_id' ) ) {
     429                $items[] = "<a href='" . get_permalink( at_option( 'page_id' ) ) . "'>" . get_the_title( at_option( 'page_id' ) ) . "</a>";
     430                $items[] = '<a href="' . get_permalink( at_option( 'page_id' ) ) . '#' . sanitize_title( $group ) . '">' . $group . '</a>';
     431            }
     432
     433            $items[] = sprintf( '<a href="%s">%s</a>', esc_url( get_term_link( $terms[0] ) ), $terms[0]->name );
     434        }
     435        $items[] = get_the_title();
     436        return $items;
     437    }
     438    return $items;
     439}, 10, 2 );
     440
     441// Filter to change the archive title for 'tipologie' taxonomy
     442add_filter( 'get_the_archive_title', function( $title ) {
     443    if ( is_tax( 'tipologie' ) ) {
     444        $term = get_queried_object();
     445        if ( $term && isset( $term->name ) ) {
     446            return $term->name;
     447        }
     448    }
     449    return $title;
     450});
     451
     452// Show admin notice when filtering by date
     453add_action('admin_notices', function() {
     454    if (
     455        isset($_GET['post_type']) && $_GET['post_type'] === 'amm-trasparente' &&
     456        isset($_GET['at_older_than']) && is_numeric($_GET['at_older_than'])
     457    ) {
     458        $years = intval($_GET['at_older_than']);
     459        ?>
     460        <div class="notice notice-warning is-dismissible">
     461            <p>
     462                <strong>Filtro attivo:</strong>
     463                Stai visualizzando solo i documenti più vecchi di <?php echo esc_html($years); ?> anni.
     464                <a href="<?php echo esc_url( admin_url('edit.php?post_type=amm-trasparente') ); ?>" class="button" style="margin-left:8px;">Rimuovi filtro</a>
     465            </p>
     466        </div>
     467        <?php
     468    }
     469});
     470
     471require_once(plugin_dir_path(__FILE__) . 'gutenberg.php');
  • amministrazione-trasparente/tags/9.0/readme.txt

    r3301628 r3301857  
    55Requires at least: 4.2
    66Tested up to: 6.9
    7 Version: 8.1.4
    8 Stable tag: 8.1.4
     7Version: 9.0
     8Stable tag: 9.0
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    1212Plugin completo per la gestione documentale di Amministrazione Trasparente nelle Pubbliche Amministrazioni (D.lgs. 33/2013)
    1313
    14 == Description ==
    15 
    16 Plugin completo per la gestione documentale di **Amministrazione Trasparente** (D.lgs. 33 del 14/03/2013 e successive integrazioni), riguardante il riordino della disciplina degli obblighi di pubblicità, trasparenza e diffusione di informazioni da parte delle pubbliche amministrazioni.
    17 
    18 > Con questo plugin potrai gestire le sezioni richieste dalla normativa direttamente nel tuo sito WordPress, senza il bisogno di servizi esterni
    19 
    20 = Caratteristiche =
    21 * Aggiornamento costante, tecnico e normativo
    22 * Inserimento rapido e intuitivo
    23 * Supporto per la catalogazione avanzata delle voci (tassonomie e tag) e filtri amministrativi per la ricerca dei contenuti
    24 * Soluzione ideale per ogni tipo di contenuto (documenti, testo, link,...)
    25 * Gestione avanzata dei ruoli ("map-cap ready")
    26 * Funzione di reindirizzamento delle voci a link esterni
    27 * Personalizzazioni grafiche e numerosi shortcode
    28 * Widget personalizzabili
    29 * Compatibile con tutti i temi WordPress
    30 
    31 = CONTATTI & SUPPORTO =
    32 Per qualsiasi informazione, segnalare problemi o fornire feedback, seguici su [wpgov.it](https://www.wpgov.it/)
    33 
    34 == Installation ==
    35 
    36 http://www.youtube.com/watch?v=qWj9hvzNSlg
    37 
    38 Puoi trovare la documentazione su [docs.wpgov.it](https://docs.wpgov.it/docs/category/amministrazione-trasparente)
     14== Descrizione ==
     15
     16**Amministrazione Trasparente** è il plugin WordPress più completo per la gestione dei documenti e delle sezioni richieste dalla normativa italiana sulla trasparenza amministrativa (D.lgs. 33/2013 e successive integrazioni). 
     17Permette di pubblicare, organizzare e mantenere aggiornate tutte le informazioni obbligatorie direttamente dal tuo sito WordPress, senza servizi esterni.
     18
     19> Gestisci facilmente sezioni, documenti, allegati e filtri, con un'interfaccia intuitiva e aggiornata alle ultime disposizioni di legge.
     20
     21### Caratteristiche principali
     22
     23- **Aggiornamento costante** tecnico e normativo
     24- **Inserimento rapido** e intuitivo dei documenti
     25- **Catalogazione avanzata** tramite tassonomie, tag e filtri amministrativi
     26- **Soluzione ideale** per ogni tipo di contenuto (documenti, testo, link, allegati…)
     27- **Gestione avanzata dei ruoli** ("map-cap ready")
     28- **Reindirizzamento** delle voci a link esterni
     29- **Personalizzazione grafica** e numerosi shortcode
     30- **Widget personalizzabili**
     31- **Compatibilità** con tutti i temi WordPress, incluso supporto specifico per temi PA (PASW2013, Design Comuni, ecc.)
     32- **Dashboard avanzata** per la panoramica e la gestione delle tipologie e dei documenti
     33- **Filtri rapidi** per gruppi, ricerca e documenti vecchi (>5 anni)
     34- **Notifiche e avvisi** per una gestione più sicura e trasparente
     35
     36### Contatti & Supporto
     37
     38Per qualsiasi informazione, segnalazione di problemi o feedback, visita [wpgov.it](https://www.wpgov.it/) 
     39Documentazione completa: [docs.wpgov.it](https://docs.wpgov.it/docs/category/amministrazione-trasparente)
     40
     41== Installazione ==
     42
     431. Scarica e installa il plugin tramite la directory di WordPress o carica manualmente la cartella.
     442. Attiva il plugin tramite il menu 'Plugin' di WordPress.
     453. Configura le sezioni e le opzioni tramite il menu "Trasparenza" nel back-end.
     464. Consulta la [documentazione online](https://docs.wpgov.it/docs/category/amministrazione-trasparente) per tutte le funzionalità avanzate.
     47
     48Video guida: 
     49https://www.youtube.com/watch?v=qWj9hvzNSlg
    3950
    4051== Screenshots ==
     
    5061
    5162== Changelog ==
     63
    5264> Di seguito la lista completa di aggiornamenti, test e correzioni. Aggiornare il prima possibile per usufruire delle ultime migliorie!
     65
     66= 9.0 2025-05-28 =
     67
     68* **Nuovo**: Aggiunga funzionalità di dashboard (Trasparenza > Revisione) per una panoramica delle sezioni e dei contenuti (la dashboard è visibile a chiunque abbia diritti di pubblicazione sul post type)
     69* **Nuovo**: Dashboard: nuova visualizzazione voci senza tipologia associata
     70* **Nuovo**: La dashboard sarà nel tempo arricchita con consigli e funzionalità
     71* **Nuovo**: Benvenuto Gutenberg, addio shortcode (facoltativo)! Aggiunto blocco Gutenberg per visualizzare le sezioni e un nuovo stile grafico selezionabile!
     72* **Nuovo**: Blocco Gutenberg con diverse opzioni di stile e possibilità di avere voci "espandibili"
     73* **Nuovo**: Migliorata pagina delle impostazioni con layout moderno per la personalizzazione delle sezioni e possibilità di riordinare le categorie
     74* **Nuovo**: Aggiungo supporto per le breadcrumb del template "Design Comuni WordPress Theme" (modello PNRR) - Modifica applicata automaticamente
     75* **Nuovo**: Rimosso prefisso "Sezione:" dal titolo degli archivi delle sezioni
     76* **Migliorato**: Accessibilità e prestazioni generali
     77* **Corretto**: Bug minori, test e ottimizzazioni varie
     78
     79= 8.1.3 20240722 =
     80* **Migliorato**: Esperienza utente nella dashboard con filtri e notifiche più chiare
     81* **Corretto**: Bug minori e ottimizzazioni varie
    5382
    5483= 8.1.3 20240722 =
  • amministrazione-trasparente/tags/9.0/settings.php

    r3301628 r3301857  
    22
    33<?php
     4/**
     5 * Render settings tabs.
     6 */
    47function at_setting_tabs( $id ) {
    5 
    6   $id0 = $id1 = $id2 = '';
    7   switch ( $id ) {
    8     case 0:
    9       $id0 = ' nav-tab-active';
    10       break;
    11     case 1:
    12       $id1 = ' nav-tab-active';
    13       break;
    14     case 2:
    15       $id2 = ' nav-tab-active';
    16       break;
     8    $tabs = [
     9        0 => [ 'Generale', 'edit.php?post_type=amm-trasparente&page=wpgov_at' ],
     10        1 => [ 'Gestione sezioni', 'edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=config' ],
     11        2 => [ 'Debug', 'edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=debug' ],
     12    ];
     13    echo '<h2 class="nav-tab-wrapper wp-clearfix">';
     14    foreach ( $tabs as $i => $tab ) {
     15        $active = ( $i === $id ) ? ' nav-tab-active' : '';
     16        printf(
     17            '<a href="%s" class="nav-tab%s">%s</a>',
     18            esc_url( admin_url( $tab[1] ) ),
     19            esc_attr( $active ),
     20            esc_html( $tab[0] )
     21        );
    1722    }
    18   $r = '<h2 class="nav-tab-wrapper wp-clearfix">
    19     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at" class="nav-tab'.$id0.'">Generale</a>
    20     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=config" class="nav-tab'.$id1.'">Gestione sezioni</a>
    21     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=debug" class="nav-tab'.$id2.'">Debug</a>
    22   </h2>';
    23   echo $r;
     23    echo '</h2>';
    2424}
    2525?>
    2626
    2727<div class="wrap">
    28   <h1>Amministrazione Trasparente</h1>
    29   <div id="welcome-panel" class="welcome-panel">
    30     <div class="welcome-panel-column-container">
    31       <ul>
    32         <li><a href="https://github.com/WPGov/amministrazione-trasparente/wiki" class="welcome-icon welcome-write-blog">Documentazione del plugin</a></li>
    33         <li><a href="https://github.com/WPGov/amministrazione-trasparente" class="welcome-icon dashicons-editor-code">Migliora il codice su GitHub</a></li>
    34         <li><div class="welcome-icon dashicons-admin-users">Creato da <a href="https://www.marcomilesi.com/">Marco Milesi</a></div></li>
    35         <li><div class="welcome-icon dashicons-groups">Con il contributo di <a href="http://www.porteapertesulweb.it/">Porte Aperte sul Web</a></div></li>
    36       </ul>
     28    <?php
     29    $plugin_slug = 'amministrazione-trasparente';
     30    $wporg_logo_url = 'https://ps.w.org/' . $plugin_slug . '/assets/icon-256x256.jpg';
     31    ?>
     32    <div class="at-intro-banner" style="background:#fff;border:1px solid #e5e5e5;border-radius:8px;padding:24px 32px;margin-bottom:24px;box-shadow:0 2px 8px rgba(0,0,0,0.03);display:flex;align-items:center;gap:32px;">
     33        <div style="flex:0 0 auto;">
     34            <img src="<?php echo esc_url( $wporg_logo_url ); ?>"
     35                 alt="Amministrazione Trasparente"
     36                 style="width:64px;height:64px;padding:8px;">
     37        </div>
     38        <div style="flex:1 1 auto;">
     39            <h2 style="margin-top:0;margin-bottom:8px;font-size:1.5em;"><?php esc_html_e( 'Benvenuto in Amministrazione Trasparente', 'amministrazione-trasparente' ); ?></h2>
     40            <p style="margin:0 0 12px 0;color:#555;">
     41                <?php esc_html_e( 'Gestisci la trasparenza della tua amministrazione pubblica in modo semplice e conforme alle normative italiane. Consulta la documentazione, contribuisci allo sviluppo o scopri chi ha reso possibile questo progetto.', 'amministrazione-trasparente' ); ?>
     42            </p>
     43            <div style="display:flex;flex-wrap:wrap;gap:12px;">
     44                <a href="https://github.com/WPGov/amministrazione-trasparente/wiki" class="button button-primary" target="_blank" rel="noopener noreferrer">
     45                    <?php esc_html_e( 'Documentazione', 'amministrazione-trasparente' ); ?>
     46                </a>
     47                <a href="https://github.com/WPGov/amministrazione-trasparente" class="button" target="_blank" rel="noopener noreferrer">
     48                    <?php esc_html_e( 'Contribuisci su GitHub', 'amministrazione-trasparente' ); ?>
     49                </a>
     50                <a href="https://www.marcomilesi.com/" class="button" target="_blank" rel="noopener noreferrer">
     51                    <?php esc_html_e( 'Autore', 'amministrazione-trasparente' ); ?>
     52                </a>
     53                <a href="http://www.porteapertesulweb.it/" class="button" target="_blank" rel="noopener noreferrer">
     54                    <?php esc_html_e( 'Community Porte Aperte sul Web', 'amministrazione-trasparente' ); ?>
     55                </a>
     56            </div>
     57        </div>
    3758    </div>
    38   </div>
    39 
    40   <?php
    41 
    42   if ( isset($_GET['at_action']) && $_GET['at_action'] == 'debug'  ) {
    43 
    44     at_setting_tabs( 2 );
    45 
    46     echo '<pre>';
    47     $a = get_option('wpgov_at');
    48     if ( is_array( $a ) ) {
    49       $e = filter_var_array( get_option('wpgov_at'), FILTER_SANITIZE_SPECIAL_CHARS);
    50       print_r( $e );
     59
     60    <?php
     61    // Debug tab
     62    if ( isset($_GET['at_action']) && $_GET['at_action'] === 'debug' ) {
     63        at_setting_tabs( 2 );
     64        echo '<pre>';
     65        $a = get_option('wpgov_at');
     66        if ( is_array( $a ) ) {
     67            $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS );
     68            print_r( $e );
     69        } else {
     70            esc_html_e( 'Nessuna impostazione presente', 'amministrazione-trasparente' );
     71        }
     72        echo '</pre>';
     73
     74        echo '<pre>';
     75        $a = get_option('atGroupConf');
     76        if ( is_array( $a ) ) {
     77            $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS );
     78            print_r( $e );
     79        } else {
     80            esc_html_e( 'Nessuna configurazione presente', 'amministrazione-trasparente' );
     81        }
     82        echo '</pre>';
     83
     84    // Config tab
     85    } elseif ( isset($_GET['at_action']) ) {
     86        at_setting_tabs( 1 );
     87
     88        $selected_sections = [];
     89        $selected_sections_unique = [];
     90
     91        $atTerms = get_terms([
     92            'taxonomy'   => 'tipologie',
     93            'parent'     => 0,
     94            'hide_empty' => false,
     95        ]);
     96
     97        if ( is_array( at_getGroupConf() ) ) {
     98            foreach ( at_getGroupConf() as $arrayTipologie ) {
     99                $selected_sections = array_merge( $selected_sections, $arrayTipologie );
     100                $selected_sections_unique = array_unique( array_merge( $selected_sections, $arrayTipologie ) );
     101            }
     102        }
     103
     104        $diff = array_diff_assoc( $selected_sections, array_unique( $selected_sections ) );
     105        $alert_duplicates = esc_js( "Elenco duplicati:\n" );
     106        if ( is_array( $diff ) && !empty( $diff ) ) {
     107            foreach ( $diff as $x ) {
     108                $duplicate_term = get_term_by( 'id', $x, 'tipologie' );
     109                if ( $duplicate_term && $duplicate_term->name ) {
     110                    $alert_duplicates .= '- ' . esc_js( $duplicate_term->name ) . '\n';
     111                }
     112            }
     113        }
     114
     115        $green_svg = '<span style="color:green" aria-label="OK">&#x2714;</span>';
     116        $red_svg = '<span style="color:red;" aria-label="Errore">&#x26A0;</span>';
     117
     118        $warning_count = '';
     119        $alert_count = esc_js( "Elenco tipologie non associate:\n" );
     120        if ( wp_count_terms( 'tipologie' ) != count( array_count_values( $selected_sections ) ) ) {
     121            foreach ( $atTerms as $term ) {
     122                if ( !in_array( $term->term_id, $selected_sections_unique ) ) {
     123                    $alert_count .= '- ' . esc_js( $term->name ) . '\n';
     124                    if ( !empty( $selected_sections_unique ) ) {
     125                        $max = max( array_keys( $selected_sections_unique ) );
     126                        $selected_sections_unique[ ++$max ] = $term->term_id;
     127                    }
     128                }
     129            }
     130            $warning_count = ' ' . esc_html( wp_count_terms( 'tipologie' ) - count( array_count_values( $selected_sections ) ) ) . ' tipologie non sono associate a un gruppo - <a href="#" onclick="alert(\'' . $alert_count . '\');return false;">Clicca qui per i dettagli</a>';
     131        } else {
     132            $warning_count = $green_svg;
     133        }
     134
     135        $warning_duplicates = '';
     136        if ( ( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) != 0 ) {
     137            $warning_duplicates = $red_svg . ' Verificare se intenzionale - <a href="#" onclick="alert(\'' . $alert_duplicates . '\');return false;">Clicca qui per i dettagli</a>';
     138        } else {
     139            $warning_duplicates = $green_svg;
     140        }
     141        ?>
     142        <h3><?php esc_html_e( 'Tipologie', 'amministrazione-trasparente' ); ?></h3>
     143        <table class="widefat fixed striped" cellspacing="0">
     144            <thead>
     145                <tr>
     146                    <th class="manage-column"><?php esc_html_e( 'Controllo', 'amministrazione-trasparente' ); ?></th>
     147                    <th class="manage-column num"><?php esc_html_e( 'Esito', 'amministrazione-trasparente' ); ?></th>
     148                </tr>
     149            </thead>
     150            <tbody>
     151                <tr class="alternate">
     152                    <td><?php echo esc_html( wp_count_terms( 'tipologie' ) ); ?> tipologie gestite</td>
     153                    <td><?php echo ( wp_count_terms( 'tipologie' ) > 0 ? $green_svg : $red_svg ); ?></td>
     154                </tr>
     155                <tr>
     156                    <td><?php echo esc_html( count( array_count_values( $selected_sections ) ) ); ?> tipologie correttamente associate nei gruppi</td>
     157                    <td><?php echo $warning_count; ?></td>
     158                </tr>
     159                <tr class="alternate">
     160                    <td><?php echo esc_html( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ); ?> tipologie sono associate a più gruppi</td>
     161                    <td><?php echo $warning_duplicates; ?></td>
     162                </tr>
     163            </tbody>
     164        </table>
     165        <br><br>
     166        <p><?php esc_html_e( 'Puoi aggiungere o modificare le singole sezioni di Amministrazione trasparente:', 'amministrazione-trasparente' ); ?></p>
     167        <a href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=tipologie&post_type=amm-trasparente' ) ); ?>" class="button-secondary"><?php esc_html_e( 'Aggiungi o modifica tipologie', 'amministrazione-trasparente' ); ?></a>
     168        <hr>
     169        <h3><?php esc_html_e( 'Gruppi', 'amministrazione-trasparente' ); ?></h3>
     170        <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     171        <form method="post" action="options.php" id="at-groupconf-form">
     172            <?php
     173            settings_fields( 'wpgov_at_option_groups' );
     174            $options = get_option( 'atGroupConf' );
     175            $all_terms = [];
     176            foreach ( $atTerms as $term ) {
     177                $all_terms[ $term->term_id ] = $term->name;
     178            }
     179            ?>
     180            <div class="at-groups-stack">
     181            <?php foreach ( at_get_taxonomy_groups() as $group ) :
     182                $group_slug = sanitize_title( $group );
     183                $sezione = at_getGroupConf( $group_slug );
     184            ?>
     185                <div class="at-group-card" style="background:#fff;border:1px solid #e5e5e5;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.03);padding:20px;max-width:700px;margin:0 auto 24px auto;">
     186                    <h4 style="margin-top:0;margin-bottom:12px;font-size:1.1em;display:flex;align-items:center;justify-content:space-between;">
     187                        <span><?php echo esc_html( $group ); ?></span>
     188                        <span style="color:#888;font-size:0.9em;"><?php echo esc_html( count( $sezione ) ); ?> tipologie</span>
     189                    </h4>
     190                    <ul class="at-sortable-list" id="sortable-<?php echo esc_attr( $group_slug ); ?>" style="margin-bottom:10px;padding-left:0;list-style:none;min-height:36px;">
     191                        <?php
     192                        if ( !empty( $sezione ) ) :
     193                            foreach ( $sezione as $term_id ) :
     194                                if ( isset( $all_terms[ $term_id ] ) ) :
     195                        ?>
     196                            <li class="at-sortable-item" style="margin:2px 0;padding:8px 12px;background:#f7f7f7;border:1px solid #e5e5e5;border-radius:4px;cursor:move;display:flex;align-items:center;justify-content:space-between;">
     197                                <span><?php echo esc_html( $all_terms[ $term_id ] ); ?></span>
     198                                <button type="button" class="button-link at-remove-term" data-term="<?php echo esc_attr( $term_id ); ?>" title="<?php esc_attr_e( 'Rimuovi', 'amministrazione-trasparente' ); ?>">&times;</button>
     199                                <input type="hidden" name="atGroupConf[<?php echo esc_attr( $group_slug ); ?>][]" value="<?php echo esc_attr( $term_id ); ?>">
     200                            </li>
     201                        <?php
     202                                endif;
     203                            endforeach;
     204                        endif;
     205                        ?>
     206                    </ul>
     207                    <div style="display:flex;gap:8px;">
     208                        <select class="at-add-term-select" style="min-width:180px;">
     209                            <option value=""><?php esc_html_e( 'Aggiungi tipologia…', 'amministrazione-trasparente' ); ?></option>
     210                            <?php
     211                            foreach ( $all_terms as $term_id => $term_name ) {
     212                                if ( empty( $sezione ) || !in_array( $term_id, $sezione ) ) {
     213                                    echo '<option value="' . esc_attr( $term_id ) . '">' . esc_html( $term_name ) . '</option>';
     214                                }
     215                            }
     216                            ?>
     217                        </select>
     218                        <button type="button" class="button at-add-term-btn"><?php esc_html_e( 'Aggiungi', 'amministrazione-trasparente' ); ?></button>
     219                    </div>
     220                </div>
     221            <?php endforeach; ?>
     222            </div>
     223            <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     224        </form>
     225        <script>
     226        jQuery(function($){
     227            // Enable sortable for each group
     228            $('.at-sortable-list').sortable({
     229                placeholder: "ui-state-highlight",
     230                axis: "y"
     231            });
     232
     233            // Remove term from group
     234            $('.at-sortable-list').on('click', '.at-remove-term', function(){
     235                $(this).closest('li').remove();
     236            });
     237
     238            // Add term to group
     239            $('.at-add-term-btn').on('click', function(){
     240                var $container = $(this).closest('.at-group-card');
     241                var $select = $container.find('.at-add-term-select');
     242                var termId = $select.val();
     243                var termName = $select.find('option:selected').text();
     244                if(termId){
     245                    var $list = $container.find('.at-sortable-list');
     246                    // Prevent duplicates
     247                    if($list.find('input[value="'+termId+'"]').length === 0){
     248                        var groupSlug = $list.attr('id').replace('sortable-','');
     249                        var $li = $('<li class="at-sortable-item" style="margin:2px 0;padding:8px 12px;background:#f7f7f7;border:1px solid #e5e5e5;border-radius:4px;cursor:move;display:flex;align-items:center;justify-content:space-between;">'
     250                            + '<span>'+termName+'</span>'
     251                            + '<button type="button" class="button-link at-remove-term" data-term="'+termId+'" title="<?php esc_attr_e( 'Rimuovi', 'amministrazione-trasparente' ); ?>">&times;</button>'
     252                            + '<input type="hidden" name="atGroupConf['+groupSlug+'][]" value="'+termId+'">'
     253                            + '</li>');
     254                        $list.append($li);
     255                        $select.find('option[value="'+termId+'"]').remove();
     256                    }
     257                }
     258                $select.val('');
     259            });
     260        });
     261        </script>
     262        <style>
     263        .at-groups-stack {
     264            display: block;
     265        }
     266        .at-group-card {
     267            width: 100%;
     268            max-width: 700px;
     269            margin: 0 auto 24px auto;
     270        }
     271        .at-sortable-list .ui-state-highlight { background: #e0f7fa; border: 1px dashed #0073aa; min-height: 36px; }
     272        .at-sortable-item .at-remove-term { color: #b32d2e; font-size: 1.2em; margin-left: 8px; }
     273        .at-sortable-item .at-remove-term:hover { color: #dc3232; }
     274        </style>
     275        <?php
     276
     277    // General tab
    51278    } else {
    52       echo 'Nessuna impostazione presente';
     279        at_setting_tabs( 0 );
     280        ?>
     281        <form method="post" action="options.php">
     282            <?php
     283            settings_fields( 'wpgov_at_options' );
     284            wp_nonce_field( 'wpgov_at_save_settings', 'wpgov_at_nonce' );
     285            $options = get_option( 'wpgov_at' );
     286            ?>
     287            <table class="form-table">
     288                <tr valign="top">
     289                    <th scope="row">
     290                        <label for="at_option_id"><?php esc_html_e( 'ID Pagina', 'amministrazione-trasparente' ); ?></label>
     291                    </th>
     292                    <td>
     293                        <input id="at_option_id" type="number" min="0" name="wpgov_at[page_id]" value="<?php echo esc_attr( isset( $options['page_id'] ) ? $options['page_id'] : '' ); ?>" size="55" />
     294                        <br>
     295                        <small>
     296                            <?php esc_html_e( 'ID della pagina di WordPress in cui è stato inserito lo shortcode del plugin.', 'amministrazione-trasparente' ); ?><br>
     297                            <?php esc_html_e( 'Lista shortcode:', 'amministrazione-trasparente' ); ?>
     298                            <a href="https://github.com/WPGov/amministrazione-trasparente/wiki/Shortcode" target="_blank" rel="noopener noreferrer">link</a>
     299                        </small>
     300                    </td>
     301                </tr>
     302                <tr valign="top">
     303                    <th scope="row">
     304                        <label for="at_option_opacity"><?php esc_html_e( 'Sfuma sezioni vuote', 'amministrazione-trasparente' ); ?></label>
     305                    </th>
     306                    <td>
     307                        <input id="at_option_opacity" name="wpgov_at[opacity]" type="checkbox" value="1" <?php checked( '1', isset( $options['opacity'] ) && $options['opacity'] ); ?> />
     308                        <br>
     309                        <small><?php esc_html_e( 'Aumenta la trasparenza visiva delle sezioni senza alcun contenuto. Consigliato: ON', 'amministrazione-trasparente' ); ?></small>
     310                    </td>
     311                </tr>
     312                <tr valign="top">
     313                    <th scope="row">
     314                        <label for="at_enable_tag"><?php esc_html_e( 'Abilita tag', 'amministrazione-trasparente' ); ?></label>
     315                    </th>
     316                    <td>
     317                        <input id="at_enable_tag" name="wpgov_at[enable_tag]" type="checkbox" value="1" <?php checked( '1', isset( $options['enable_tag'] ) && $options['enable_tag'] ); ?> />
     318                        <br>
     319                        <small><?php esc_html_e( 'Consenti di associare dei tag ai post di Amministrazione Trasparente. Consigliato: OFF', 'amministrazione-trasparente' ); ?></small>
     320                    </td>
     321                </tr>
     322                <tr valign="top">
     323                    <th scope="row">
     324                        <label for="at_show_love"><?php esc_html_e( 'Mostra credits', 'amministrazione-trasparente' ); ?></label>
     325                    </th>
     326                    <td>
     327                        <input id="at_show_love" name="wpgov_at[show_love]" type="checkbox" value="1" <?php checked( '1', isset( $options['show_love'] ) && $options['show_love'] ); ?> />
     328                        <br>
     329                        <small><?php esc_html_e( 'Aiutaci a far conoscere il progetto e ottieni una via preferenziale per il supporto. Consigliato: ON', 'amministrazione-trasparente' ); ?></small>
     330                    </td>
     331                </tr>
     332                <tr valign="top">
     333                    <th scope="row" colspan="2">
     334                        <h2><?php esc_html_e( 'Avanzate', 'amministrazione-trasparente' ); ?></h2>
     335                    </th>
     336                </tr>
     337                <tr valign="top">
     338                    <th scope="row">
     339                        <label for="at_enable_ucc"><?php esc_html_e( 'Abilita uffici e Centri di costo', 'amministrazione-trasparente' ); ?></label>
     340                    </th>
     341                    <td>
     342                        <input id="at_enable_ucc" name="at_enable_ucc" type="checkbox" value="1" <?php checked( '1', isset( $options['enable_ucc'] ) && $options['enable_ucc'] ); ?> />
     343                        <br>
     344                        <small><?php esc_html_e( 'Consenti di associare i contenuti a una nuova tassonomia per uffici e centri di costo. Consigliato: OFF, attivare solo se necessario.', 'amministrazione-trasparente' ); ?></small>
     345                    </td>
     346                </tr>
     347                <tr valign="top">
     348                    <th scope="row">
     349                        <label for="at_map_cap"><?php esc_html_e( 'Mappa capacità', 'amministrazione-trasparente' ); ?></label>
     350                    </th>
     351                    <td>
     352                        <input id="at_map_cap" name="wpgov_at[map_cap]" type="checkbox" value="1" <?php checked( '1', isset( $options['map_cap'] ) && $options['map_cap'] ); ?> />
     353                        <br>
     354                        <small><?php esc_html_e( 'Mappa le meta capacità per personalizzare ruoli e permessi. [per utenti esperti] + [richiede componenti aggiuntivi]. Consigliato: OFF', 'amministrazione-trasparente' ); ?></small>
     355                    </td>
     356                </tr>
     357                <tr valign="top">
     358                    <th scope="row">
     359                        <label for="at_pasw_2013"><?php esc_html_e( 'Forza PASW2013', 'amministrazione-trasparente' ); ?></label>
     360                    </th>
     361                    <td>
     362                        <input id="at_pasw_2013" name="wpgov_at[pasw_2013]" type="checkbox" value="1" <?php checked( '1', isset( $options['pasw_2013'] ) && $options['pasw_2013'] ); ?> />
     363                        <br>
     364                        <small><?php esc_html_e( 'Spunta casella se vuoi attivare ottimizzazioni per il template PASW2013. [abilitare solo se il tema attivo è una versione precedente al 2013 o se è stato cambiato il nome della cartella di "pasw2013"]', 'amministrazione-trasparente' ); ?></small>
     365                    </td>
     366                </tr>
     367                <tr valign="top" <?php if ( !isset( $options['custom_terms'] ) || !$options['custom_terms'] ) { echo 'style="display:none;"'; } ?>>
     368                    <th scope="row">
     369                        <label for="custom_terms"><?php esc_html_e( 'Custom Terms', 'amministrazione-trasparente' ); ?></label>
     370                    </th>
     371                    <td>
     372                        <input id="custom_terms" name="wpgov_at[custom_terms]" type="checkbox" value="1" <?php checked( '1', isset( $options['custom_terms'] ) && $options['custom_terms'] ); ?> />
     373                        <br>
     374                        <small><?php esc_html_e( 'Utile in caso di test da parte del servizio di supporto. Mantienila disattivata!', 'amministrazione-trasparente' ); ?></small>
     375                    </td>
     376                </tr>
     377            </table>
     378            <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     379        </form>
     380        <?php
     381        // Optional: Debug info for advanced users
     382        if ( at_option('debug') ) {
     383            echo '<hr><h3>DEBUG</h3>';
     384            $terms = get_terms( [ 'taxonomy' => 'tipologie', 'hide_empty' => false ] );
     385            echo esc_html__( 'Numero sezioni installate:', 'amministrazione-trasparente' ) . ' ' . esc_html( count( $terms ) ) . '<br>';
     386            $count = 0;
     387            $merge = [];
     388            foreach ( amministrazionetrasparente_getarray() as $inner ) {
     389                $count += count( $inner[1] );
     390                $merge = array_merge( $merge, $inner[1] );
     391            }
     392            sort( $merge );
     393            echo esc_html__( 'Numero sezioni supportate dal plugin:', 'amministrazione-trasparente' ) . ' ' . esc_html( $count );
     394            echo '<hr>';
     395            echo '<div style="width:45%;float:left;"><h4>' . esc_html__( 'Installate:', 'amministrazione-trasparente' ) . '</h4><ul>';
     396            foreach ( $terms as $term ) {
     397                echo '<li>' . esc_html( $term->name ) . '</li>';
     398            }
     399            echo '</ul></div>';
     400            echo '<div style="width:45%;float:left;"><h4>' . esc_html__( 'Supportate:', 'amministrazione-trasparente' ) . '</h4><ul>';
     401            foreach ( $merge as $merge_item ) {
     402                echo '<li>' . esc_html( $merge_item ) . '</li>';
     403            }
     404            echo '</ul></div><hr>';
     405        }
    53406    }
    54     echo '</pre>';
    55 
    56     echo '<pre>';
    57     $a = get_option('atGroupConf');
    58     if ( is_array( $a ) ) {
    59       $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS);
    60       print_r( $e );
    61     } else {
    62       echo 'Nessuna configurazione presente';
    63     }
    64     echo '</pre>'; 
    65 
    66   } else if ( isset($_GET['at_action']) ) {
    67 
    68     at_setting_tabs( 1 );
    69 
    70     $selected_sections = array();
    71     $selected_sections_unique = array();
    72 
    73     $atTerms = get_terms(
    74       array(
    75         'taxonomy' => 'tipologie',
    76         'parent'   => 0,
    77         'hide_empty' => false,
    78       )
    79     );
    80 
    81     if( is_array( at_getGroupConf() ) ) {
    82       foreach ( at_getGroupConf() as $key => $arrayTipologie ) {
    83         $selected_sections = array_merge( $selected_sections, $arrayTipologie );
    84         $selected_sections_unique = array_unique( array_merge( $selected_sections, $arrayTipologie ) );
    85       }
    86     }
    87 
    88     $diff = array_diff_assoc($selected_sections, array_unique($selected_sections) );
    89     $alert_duplicates = 'Elenco duplicati:\n';
    90     if ( is_array( $diff ) && !empty( $diff ) ) {
    91       foreach ( $diff as $x ) {
    92         $duplicate_term = get_term_by('id', $x, 'tipologie');
    93         if ( $duplicate_term && $duplicate_term->name ) {
    94           $alert_duplicates .= '- '.esc_js($duplicate_term->name). '\n';
    95         }
    96       }
    97     }
    98 
    99     $green_svg = '<span style="color:green"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/></svg></span>';
    100     $red_svg = '<span style="color:red;"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle-fill" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg></span>';
    101 
    102     $warning_count = '';
    103     $alert_count = 'Elenco tipologie non associate:\n';
    104     if ( wp_count_terms( 'tipologie' ) != count( array_count_values( $selected_sections ) ) ) {
    105       foreach( $atTerms as $term ) {
    106         if ( !in_array( $term->term_id, $selected_sections_unique ) ) {
    107           $alert_count .= '- '.esc_js($term->name) . '\n';
    108           if ( !empty( $selected_sections_unique) ) {
    109             $max = max( array_keys( $selected_sections_unique ) );
    110             $selected_sections_unique[ ++$max ] = $term->term_id;
    111           }
    112          
    113         }
    114       }
    115       $warning_count = ' '.(wp_count_terms( 'tipologie' ) - count( array_count_values( $selected_sections ) ) ).' tipologie non sono associate a un gruppo - <a href="#" onclick="alert(\''.$alert_count.'\');">Clicca qui per i dettagli</a></b>';
    116     } else {
    117       $warning_count = $green_svg;
    118     }
    119 
    120     $warning_duplicates = '';
    121     if ( ( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) != 0 ) {
    122       $warning_duplicates = $red_svg.' Verificare se intenzionale - <a href="#" onclick="alert(\''.$alert_duplicates.'\');">Clicca qui per i dettagli</a>';
    123     } else {
    124       $warning_duplicates = $green_svg;
    125     }
    126     echo '<h3>Tipologie</h3>';
    127    
    128     echo '<table class="widefat fixed" cellspacing="0">
    129     <thead>
    130     <tr>
    131             <th id="columnname" class="manage-column column-columnname" scope="col">Controllo</th>
    132             <th id="columnname" class="manage-column column-columnname num" scope="col">Esito</th>
    133     </tr>
    134     </thead>
    135     <tbody>
    136         <tr class="alternate">
    137             <td class="column-columnname">'.wp_count_terms( 'tipologie' ).'</b> tipologie gestite</td>
    138             <td class="column-columnname">'.(wp_count_terms( 'tipologie' ) > 0 ? $green_svg : $red_svg ).'</td>
    139         </tr>
    140         <tr>
    141             <td class="column-columnname">'. count( array_count_values( $selected_sections ) ) . '</b> tipologie correttamente associate nei gruppi</td>
    142             <td class="column-columnname">'.$warning_count.'</td>
    143         </tr>
    144         <tr class="alternate">
    145             <td class="column-columnname">'.( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) . '</b> tipologie sono associate a più gruppi</td>
    146             <td class="column-columnname">'.$warning_duplicates.'</td>
    147         </tr>
    148     </tbody>
    149   </table>
    150   <br><br>
    151   <p>Puoi aggiungere o modificare le singole sezioni di Amministrazione trasparente:</p>
    152   <a href="edit-tags.php?taxonomy=tipologie&post_type=amm-trasparente" class="button-secondary">Aggiungi o modifica tipologie</a>
    153   <hr><h3>Gruppi</h3>';
    154     echo '<form method="post" action="options.php">';
    155     settings_fields( 'wpgov_at_option_groups' );
    156 
    157     $options = get_option( 'atGroupConf' );
    158    
    159  
    160     foreach ( at_get_taxonomy_groups() as $group ) {
    161       echo '<details style="margin:10px;"><summary style="margin: 10px;"><b>'.$group.'</b>';
    162       $sezione = at_getGroupConf( sanitize_title( $group ) );
    163       echo ' ('.count($sezione).')';
    164       echo '</summary>';
    165       echo '<div>';
    166       $dropdownOptions = array();
    167       foreach( $atTerms as $term ) {
    168         $atSelected = ( in_array( $term->term_id, $sezione) ? 'selected' : '' );
    169 
    170         $arrayIndex = array_search( $term->term_id, $selected_sections_unique );
    171         $dropdownOptions[ $arrayIndex ] = '<option value="'.$term->term_id.'" '.$atSelected.'>'.$term->name.'</option>';
    172       }
    173       ksort( $dropdownOptions ); // Order by key to keep default AT order
    174       $dropdownOptionsEcho = '';
    175       foreach( $dropdownOptions as $x ) {
    176         $dropdownOptionsEcho .= $x;
    177       }
    178       echo '<select id="'.sanitize_title( $group ).'" name="atGroupConf['.sanitize_title( $group ).'][]" multiple="multiple">';
    179       echo $dropdownOptionsEcho;
    180       echo '</select>';
    181 
    182       echo '<script>jQuery("#'.sanitize_title( $group ).'").multiSelect( { keepOrder: true, selectableHeader: "Disponibili:", selectionHeader: "Selezionate:" } );</script>';
    183       echo '</div>';
    184       echo '</details>';
    185     }
    186 
    187     submit_button( 'Salva configurazione' );
    188     echo '</form>';
    189 
    190   } else {
    191     at_setting_tabs( 0 );
    192 
    193     echo '<form method="post" action="options.php">';
    194 
    195     settings_fields( 'wpgov_at_options');
    196     $options = get_option( 'wpgov_at');
    197   ?>
    198   <table class="form-table">
    199     <tr valign="top">
    200             <th scope="row">
    201               <label for="at_option_id">ID Pagina</label>
    202             </th>
    203             <td>
    204               <input id="at_option_id" type="number" min="0" name="wpgov_at[page_id]" value="<?php echo esc_html( isset( $options['page_id'] ) ? $options['page_id'] : '' ); ?>" size="55" />
    205               <br>
    206               <small>ID della pagina di WordPress in cui è stato inserito lo shortcode del plugin).<br>
    207               Lista shortcode: <a href="https://github.com/WPGov/amministrazione-trasparente/wiki/Shortcode">link</a></small>
    208             </td>
    209           </tr>
    210 
    211           <tr valign="top">
    212     <th scope="row">
    213       <label for="at_option_opacity">Sfuma sezioni vuote</label>
    214     </th>
    215     <td>
    216       <input id="at_option_opacity" name="wpgov_at[opacity]" type="checkbox" value="1"
    217         <?php checked( '1', isset($options['opacity']) && $options['opacity'] ); ?> />
    218       <br>
    219       <small>Aumenta la trasparenza visiva delle sezioni senza alcun contenuto<br>Consigliato: <b>ON</b></small>
    220     </td>
    221   </tr>
    222   <tr valign="top">
    223     <th scope="row">
    224       <label for="at_enable_tag">Abilita tag</label>
    225     </th>
    226     <td>
    227       <input id="at_enable_tag" name="wpgov_at[enable_tag]" type="checkbox" value="1"
    228         <?php checked( '1', isset( $options['enable_tag'] ) && $options['enable_tag'] ); ?> />
    229       <br><small>Consenti di associare dei tag ai post di Amministrazione Trasparente<br>Consigliato: <b>OFF</b></small>
    230     </td>
    231   </tr>
    232   <tr valign="top">
    233     <th scope="row">
    234     <label for="at_show_love">Mostra credits</label>
    235     </th>
    236     <td>
    237       <input id="at_show_love" name="wpgov_at[show_love]" type="checkbox" value="1"
    238         <?php checked( '1', isset( $options['show_love'] ) && $options['show_love'] ); ?> />
    239       <br><small>Aiutaci a far conoscere il progetto e ottieni una via preferenziale per il supporto<br>Consigliato: <b>ON</b></small>
    240     </td>
    241   </tr>
    242   <tr valign="top">
    243   <th scope="row" colspan="2">
    244     <h2>Avanzate</h2>
    245     <?php if ( isset( $options['enable_ucc'] ) ) { ?>
    246       <tr valign="top">
    247         <th scope="row">
    248           <label for="at_enable_ucc">Abilita uffici e Centri di costo</label>
    249         </th>
    250         <td>
    251           <input id="at_enable_ucc" name="wpgov_at[enable_ucc]" type="checkbox" value="1"
    252             <?php checked( '1', isset( $options['enable_ucc'] ) && $options['enable_ucc'] ); ?> />
    253           <br><small>Consenti di associare i contenuti a una nuova tassonomia basata su divsione aggiuntiva per uffici e centri di costo</small>
    254         </td>
    255       </tr>
    256     <?php } ?>
    257     <tr valign="top">
    258     <th scope="row">
    259     <label for="at_map_cap">Mappa capacità</label>
    260     </th>
    261     <td>
    262     <input id="at_map_cap" name="wpgov_at[map_cap]" type="checkbox" value="1"
    263       <?php checked( '1', isset( $options['map_cap'] ) && $options['map_cap'] ); ?> />
    264     <br>
    265     <small>Mappa le meta capacità per personalizzare ruoli e permessi<br>[per utenti esperti] + [richiede componenti aggiuntivi]<br>Consigliato: <b>OFF</b></small>
    266     </td>
    267     </tr>
    268   </th>
    269   </tr>
    270   <tr valign="top">
    271   <th scope="row">
    272   <label for="at_pasw_2013">Forza PASW2013</label>
    273   </th>
    274   <td>
    275   <input id="at_pasw_2013" name="wpgov_at[pasw_2013]" type="checkbox" value="1"
    276     <?php checked( '1', isset( $options['pasw_2013'] ) && $options['pasw_2013'] ); ?> />
    277   <br>
    278   <small>Spunta casella se vuoi attivare ottimizzazioni per il template PASW2013<br>[abilitare solo se il tema attivo è una versione precedente al 2013 o se è stato cambiato il nome della cartella di "pasw2013"]</small>
    279   </td>
    280   </tr>
    281   </th>
    282   </tr>
    283     <tr valign="top" <?php if ( !isset( $options['custom_terms'] ) || !$options['custom_terms'] ) { echo 'style="display:none;"'; } ?>>
    284       <th scope="row">
    285         <label for="custom_terms">Custom Terms</label>
    286       </th>
    287       <td>
    288         <input id="custom_terms" name="wpgov_at[custom_terms]" type="checkbox" value="1"
    289           <?php checked( '1', isset( $options['custom_terms'] ) && $options['custom_terms'] ); ?> />
    290         <br>
    291         <small>Utile in caso di test da parte del servizio di supporto. <b>Mantienila disattivata!</b></small>
    292       </td>
    293     </tr>
    294   </tr>
    295     </table>
    296 
    297 <?php
    298    
    299   submit_button( 'Salva configurazione' );
    300   echo '</form>';
    301   if ( at_option('debug') ) {
    302     echo '<hr><h3>DEBUG</h3>';
    303     $terms = get_terms( array( 'taxonomy' => 'tipologie', 'hide_empty' => false ) );
    304     echo 'Numero sezioni installate: '.count($terms).'<br>';
    305     $count = 0;
    306     $merge = array();
    307     foreach ( amministrazionetrasparente_getarray() as $inner ) {
    308       $count+= count($inner[1]);
    309       $merge = array_merge( $merge, $inner[1] );
    310     }
    311     sort($merge);
    312     echo 'Numero sezioni supportate dal plugin: '.sanitize_text_field( $count );
    313     echo '<hr>';
    314     echo '<div style="width:45%;float:left;"><h4>Installate:</h4>';
    315     echo '<ul>';
    316     foreach ( $terms as $term ) {
    317       echo '<li>'.sanitize_text_field($term->name).'</li>';
    318     }
    319     echo '</ul>';
    320     echo '</div>';
    321     echo '<div style="width:45%;float:left;"><h4>Supportate:</h4>';
    322     echo '<ul>';
    323     foreach ( $merge as $merge_item ) {
    324       echo '<li>'.sanitize_text_field($merge_item).'</li>';
    325     }
    326     echo '</ul>';
    327     echo '</div>';
    328     echo '<hr>';
    329   }
    330 }
    331 ?>
     407    ?>
    332408</div>
  • amministrazione-trasparente/tags/9.0/sezioni.php

    r3301628 r3301857  
    207207      );
    208208}
     209
     210/**
     211 * Get the group name by term slug or term ID.
     212 * If given a term ID, it fetches the term and uses its slug.
     213 * Returns the group name (first element of each array in amministrazionetrasparente_getarray)
     214 * if the term slug matches any of the group's terms' slugs.
     215 */
     216function at_getGroupNameByTerm( $term ) {
     217    if ( is_numeric( $term ) ) {
     218        $term_obj = get_term( $term, 'tipologie' );
     219        if ( ! $term_obj || is_wp_error( $term_obj ) ) {
     220            return '';
     221        }
     222        $slug = $term_obj->slug;
     223    } else {
     224        $slug = $term;
     225    }
     226
     227    // Build a map of term slugs to group names
     228    foreach ( amministrazionetrasparente_getarray() as $group ) {
     229        $group_name = $group[0];
     230        $terms = $group[1];
     231        foreach ( $terms as $term_name ) {
     232            $term_obj = get_term_by( 'name', $term_name, 'tipologie' );
     233            if ( $term_obj && ! is_wp_error( $term_obj ) && $term_obj->slug === $slug ) {
     234                return $group_name;
     235            }
     236        }
     237    }
     238    return 'noo';
     239}
  • amministrazione-trasparente/trunk/README.md

    r3301628 r3301857  
    77## Credits
    88
    9 Copyright © 2012-2024 **Marco Milesi**
     9Copyright © 2012-2025 **Marco Milesi**
    1010www.marcomilesi.com - www.wpgov.it
  • amministrazione-trasparente/trunk/amministrazionetrasparente.php

    r3301628 r3301857  
    44Plugin URI: https://wordpress.org/plugins/amministrazione-trasparente/
    55Description: Soluzione completa per la pubblicazione online dei documenti ai sensi del D.lgs. n. 33 del 14/03/2013
    6 Version: 8.1.4
     6Version: 9.0
    77Author: Marco Milesi
    88Author Email: [email protected]
     
    1212
    1313add_action( 'init', function() {
    14    
     14  // Only register if the option is enabled
     15  if ( !at_option('enable_ucc') ) {
     16    return;
     17  }
    1518  if ( !( function_exists('wpgov_register_taxonomy_areesettori') ) ){
    1619    $labels = array(
     
    4447      'query_var' => true
    4548    );
    46     register_taxonomy( 'areesettori', array('incarico', 'spesa', 'avcp' ), $args );
    47   }
    48 });
    49 
    50 add_action('init', function(){
    51   if ( at_option( 'enable_ucc' ) ) {
    52     register_taxonomy_for_object_type( 'areesettori', 'amm-trasparente' );
    53   }
    54 }, 200);
     49    register_taxonomy( 'areesettori', array('incarico', 'spesa', 'avcp', 'amm-trasparente' ), $args );
     50  }
     51});
    5552
    5653add_action( 'init', function() {
     
    313310$AmministrazioneTrasparente_Backend = new AmministrazioneTrasparente_Backend();
    314311
     312add_action( 'admin_enqueue_scripts', function( $hook ) {
     313    // Only load on your plugin settings page
     314    if ( isset($_GET['page']) && $_GET['page'] === 'wpgov_at' ) {
     315        wp_enqueue_script( 'jquery-ui-sortable' );
     316    }
     317});
     318
    315319add_action( 'admin_menu', function() {
    316   add_submenu_page( 'edit.php?post_type=amm-trasparente', 'Impostazioni', 'Impostazioni', 'manage_options', 'wpgov_at', function() {
    317     include(plugin_dir_path(__FILE__) . 'settings.php');
    318   } );
     320
     321    // Dashboard submenu (edit_amm-trasparente)
     322    $post_type_object = get_post_type_object('amm-trasparente');
     323    $capability = $post_type_object && isset($post_type_object->cap->edit_posts)
     324        ? $post_type_object->cap->edit_posts
     325        : 'edit_posts';
     326
     327    add_submenu_page(
     328        'edit.php?post_type=amm-trasparente',
     329        'Dashboard Amministrazione Trasparente',
     330        'Revisione',
     331        $capability,
     332        'at_tipologie_dashboard',
     333        function() {
     334            include(plugin_dir_path(__FILE__) . 'dashboard.php');
     335        }
     336    );
     337
     338    // Impostazioni submenu (manage_options)
     339    add_submenu_page(
     340        'edit.php?post_type=amm-trasparente',
     341        'Impostazioni',
     342        'Impostazioni',
     343        'manage_options',
     344        'wpgov_at',
     345        function() {
     346            include(plugin_dir_path(__FILE__) . 'settings.php');
     347        }
     348    );   
    319349} );
    320350
     
    349379}
    350380
    351 ?>
     381add_action('pre_get_posts', function($query) {
     382    if (
     383        is_admin() &&
     384        $query->is_main_query() &&
     385        isset($_GET['post_type']) &&
     386        $_GET['post_type'] === 'amm-trasparente' &&
     387        isset($_GET['at_older_than']) &&
     388        is_numeric($_GET['at_older_than'])
     389    ) {
     390        $years = intval($_GET['at_older_than']);
     391        $date = date('Y-m-d', strtotime('-' . $years . ' years'));
     392        $query->set('date_query', [
     393            [
     394                'column' => 'post_date',
     395                'before' => $date,
     396            ]
     397        ]);
     398    }
     399});
     400
     401// Breadcrumb filter for Design Comuni WordPress theme
     402add_filter( 'dci_get_breadcrumb_items', function( $items ) {
     403   
     404    if ( is_tax( array( 'tipologie' ) ) ) {
     405        // Add home link as first item
     406        $items[] = "<a href='" . home_url() . "'>" . __('Home', 'design-comuni-italia') . "</a>";
     407
     408        $term = get_queried_object();
     409        if ( $term && isset( $term->term_id ) ) {
     410            $group = function_exists('at_getGroupNameByTerm') ? at_getGroupNameByTerm( $term->term_id ) : '';
     411
     412            if ( at_option( 'page_id' ) ) {
     413                $items[] = "<a href='" . get_permalink( at_option( 'page_id' ) ) . "'>" . get_the_title( at_option( 'page_id' ) ) . "</a>";
     414                $items[] = '<a href="' . get_permalink( at_option( 'page_id' ) ) . '#' . sanitize_title( $group ) . '">' . $group . '</a>';
     415            }
     416            $taxonomy = get_queried_object();
     417            $items[] = $taxonomy->name;
     418            return $items;
     419        }
     420    } else if ( get_post_type() == 'amm-trasparente' ) {
     421        // Add home link as first item
     422        $items[] = "<a href='" . home_url() . "'>" . __('Home', 'design-comuni-italia') . "</a>";
     423       
     424        $terms = get_the_terms( get_the_ID(), 'tipologie' );
     425        if ( $terms && !is_wp_error( $terms ) ) {
     426            $group = function_exists('at_getGroupNameByTerm') ? at_getGroupNameByTerm( $terms[0]->term_id ) : '';
     427
     428            if ( at_option( 'page_id' ) ) {
     429                $items[] = "<a href='" . get_permalink( at_option( 'page_id' ) ) . "'>" . get_the_title( at_option( 'page_id' ) ) . "</a>";
     430                $items[] = '<a href="' . get_permalink( at_option( 'page_id' ) ) . '#' . sanitize_title( $group ) . '">' . $group . '</a>';
     431            }
     432
     433            $items[] = sprintf( '<a href="%s">%s</a>', esc_url( get_term_link( $terms[0] ) ), $terms[0]->name );
     434        }
     435        $items[] = get_the_title();
     436        return $items;
     437    }
     438    return $items;
     439}, 10, 2 );
     440
     441// Filter to change the archive title for 'tipologie' taxonomy
     442add_filter( 'get_the_archive_title', function( $title ) {
     443    if ( is_tax( 'tipologie' ) ) {
     444        $term = get_queried_object();
     445        if ( $term && isset( $term->name ) ) {
     446            return $term->name;
     447        }
     448    }
     449    return $title;
     450});
     451
     452// Show admin notice when filtering by date
     453add_action('admin_notices', function() {
     454    if (
     455        isset($_GET['post_type']) && $_GET['post_type'] === 'amm-trasparente' &&
     456        isset($_GET['at_older_than']) && is_numeric($_GET['at_older_than'])
     457    ) {
     458        $years = intval($_GET['at_older_than']);
     459        ?>
     460        <div class="notice notice-warning is-dismissible">
     461            <p>
     462                <strong>Filtro attivo:</strong>
     463                Stai visualizzando solo i documenti più vecchi di <?php echo esc_html($years); ?> anni.
     464                <a href="<?php echo esc_url( admin_url('edit.php?post_type=amm-trasparente') ); ?>" class="button" style="margin-left:8px;">Rimuovi filtro</a>
     465            </p>
     466        </div>
     467        <?php
     468    }
     469});
     470
     471require_once(plugin_dir_path(__FILE__) . 'gutenberg.php');
  • amministrazione-trasparente/trunk/readme.txt

    r3301628 r3301857  
    55Requires at least: 4.2
    66Tested up to: 6.9
    7 Version: 8.1.4
    8 Stable tag: 8.1.4
     7Version: 9.0
     8Stable tag: 9.0
    99License: GPLv2 or later
    1010License URI: http://www.gnu.org/licenses/gpl-2.0.html
     
    1212Plugin completo per la gestione documentale di Amministrazione Trasparente nelle Pubbliche Amministrazioni (D.lgs. 33/2013)
    1313
    14 == Description ==
    15 
    16 Plugin completo per la gestione documentale di **Amministrazione Trasparente** (D.lgs. 33 del 14/03/2013 e successive integrazioni), riguardante il riordino della disciplina degli obblighi di pubblicità, trasparenza e diffusione di informazioni da parte delle pubbliche amministrazioni.
    17 
    18 > Con questo plugin potrai gestire le sezioni richieste dalla normativa direttamente nel tuo sito WordPress, senza il bisogno di servizi esterni
    19 
    20 = Caratteristiche =
    21 * Aggiornamento costante, tecnico e normativo
    22 * Inserimento rapido e intuitivo
    23 * Supporto per la catalogazione avanzata delle voci (tassonomie e tag) e filtri amministrativi per la ricerca dei contenuti
    24 * Soluzione ideale per ogni tipo di contenuto (documenti, testo, link,...)
    25 * Gestione avanzata dei ruoli ("map-cap ready")
    26 * Funzione di reindirizzamento delle voci a link esterni
    27 * Personalizzazioni grafiche e numerosi shortcode
    28 * Widget personalizzabili
    29 * Compatibile con tutti i temi WordPress
    30 
    31 = CONTATTI & SUPPORTO =
    32 Per qualsiasi informazione, segnalare problemi o fornire feedback, seguici su [wpgov.it](https://www.wpgov.it/)
    33 
    34 == Installation ==
    35 
    36 http://www.youtube.com/watch?v=qWj9hvzNSlg
    37 
    38 Puoi trovare la documentazione su [docs.wpgov.it](https://docs.wpgov.it/docs/category/amministrazione-trasparente)
     14== Descrizione ==
     15
     16**Amministrazione Trasparente** è il plugin WordPress più completo per la gestione dei documenti e delle sezioni richieste dalla normativa italiana sulla trasparenza amministrativa (D.lgs. 33/2013 e successive integrazioni). 
     17Permette di pubblicare, organizzare e mantenere aggiornate tutte le informazioni obbligatorie direttamente dal tuo sito WordPress, senza servizi esterni.
     18
     19> Gestisci facilmente sezioni, documenti, allegati e filtri, con un'interfaccia intuitiva e aggiornata alle ultime disposizioni di legge.
     20
     21### Caratteristiche principali
     22
     23- **Aggiornamento costante** tecnico e normativo
     24- **Inserimento rapido** e intuitivo dei documenti
     25- **Catalogazione avanzata** tramite tassonomie, tag e filtri amministrativi
     26- **Soluzione ideale** per ogni tipo di contenuto (documenti, testo, link, allegati…)
     27- **Gestione avanzata dei ruoli** ("map-cap ready")
     28- **Reindirizzamento** delle voci a link esterni
     29- **Personalizzazione grafica** e numerosi shortcode
     30- **Widget personalizzabili**
     31- **Compatibilità** con tutti i temi WordPress, incluso supporto specifico per temi PA (PASW2013, Design Comuni, ecc.)
     32- **Dashboard avanzata** per la panoramica e la gestione delle tipologie e dei documenti
     33- **Filtri rapidi** per gruppi, ricerca e documenti vecchi (>5 anni)
     34- **Notifiche e avvisi** per una gestione più sicura e trasparente
     35
     36### Contatti & Supporto
     37
     38Per qualsiasi informazione, segnalazione di problemi o feedback, visita [wpgov.it](https://www.wpgov.it/) 
     39Documentazione completa: [docs.wpgov.it](https://docs.wpgov.it/docs/category/amministrazione-trasparente)
     40
     41== Installazione ==
     42
     431. Scarica e installa il plugin tramite la directory di WordPress o carica manualmente la cartella.
     442. Attiva il plugin tramite il menu 'Plugin' di WordPress.
     453. Configura le sezioni e le opzioni tramite il menu "Trasparenza" nel back-end.
     464. Consulta la [documentazione online](https://docs.wpgov.it/docs/category/amministrazione-trasparente) per tutte le funzionalità avanzate.
     47
     48Video guida: 
     49https://www.youtube.com/watch?v=qWj9hvzNSlg
    3950
    4051== Screenshots ==
     
    5061
    5162== Changelog ==
     63
    5264> Di seguito la lista completa di aggiornamenti, test e correzioni. Aggiornare il prima possibile per usufruire delle ultime migliorie!
     65
     66= 9.0 2025-05-28 =
     67
     68* **Nuovo**: Aggiunga funzionalità di dashboard (Trasparenza > Revisione) per una panoramica delle sezioni e dei contenuti (la dashboard è visibile a chiunque abbia diritti di pubblicazione sul post type)
     69* **Nuovo**: Dashboard: nuova visualizzazione voci senza tipologia associata
     70* **Nuovo**: La dashboard sarà nel tempo arricchita con consigli e funzionalità
     71* **Nuovo**: Benvenuto Gutenberg, addio shortcode (facoltativo)! Aggiunto blocco Gutenberg per visualizzare le sezioni e un nuovo stile grafico selezionabile!
     72* **Nuovo**: Blocco Gutenberg con diverse opzioni di stile e possibilità di avere voci "espandibili"
     73* **Nuovo**: Migliorata pagina delle impostazioni con layout moderno per la personalizzazione delle sezioni e possibilità di riordinare le categorie
     74* **Nuovo**: Aggiungo supporto per le breadcrumb del template "Design Comuni WordPress Theme" (modello PNRR) - Modifica applicata automaticamente
     75* **Nuovo**: Rimosso prefisso "Sezione:" dal titolo degli archivi delle sezioni
     76* **Migliorato**: Accessibilità e prestazioni generali
     77* **Corretto**: Bug minori, test e ottimizzazioni varie
     78
     79= 8.1.3 20240722 =
     80* **Migliorato**: Esperienza utente nella dashboard con filtri e notifiche più chiare
     81* **Corretto**: Bug minori e ottimizzazioni varie
    5382
    5483= 8.1.3 20240722 =
  • amministrazione-trasparente/trunk/settings.php

    r3301628 r3301857  
    22
    33<?php
     4/**
     5 * Render settings tabs.
     6 */
    47function at_setting_tabs( $id ) {
    5 
    6   $id0 = $id1 = $id2 = '';
    7   switch ( $id ) {
    8     case 0:
    9       $id0 = ' nav-tab-active';
    10       break;
    11     case 1:
    12       $id1 = ' nav-tab-active';
    13       break;
    14     case 2:
    15       $id2 = ' nav-tab-active';
    16       break;
     8    $tabs = [
     9        0 => [ 'Generale', 'edit.php?post_type=amm-trasparente&page=wpgov_at' ],
     10        1 => [ 'Gestione sezioni', 'edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=config' ],
     11        2 => [ 'Debug', 'edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=debug' ],
     12    ];
     13    echo '<h2 class="nav-tab-wrapper wp-clearfix">';
     14    foreach ( $tabs as $i => $tab ) {
     15        $active = ( $i === $id ) ? ' nav-tab-active' : '';
     16        printf(
     17            '<a href="%s" class="nav-tab%s">%s</a>',
     18            esc_url( admin_url( $tab[1] ) ),
     19            esc_attr( $active ),
     20            esc_html( $tab[0] )
     21        );
    1722    }
    18   $r = '<h2 class="nav-tab-wrapper wp-clearfix">
    19     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at" class="nav-tab'.$id0.'">Generale</a>
    20     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=config" class="nav-tab'.$id1.'">Gestione sezioni</a>
    21     <a href="edit.php?post_type=amm-trasparente&page=wpgov_at&at_action=debug" class="nav-tab'.$id2.'">Debug</a>
    22   </h2>';
    23   echo $r;
     23    echo '</h2>';
    2424}
    2525?>
    2626
    2727<div class="wrap">
    28   <h1>Amministrazione Trasparente</h1>
    29   <div id="welcome-panel" class="welcome-panel">
    30     <div class="welcome-panel-column-container">
    31       <ul>
    32         <li><a href="https://github.com/WPGov/amministrazione-trasparente/wiki" class="welcome-icon welcome-write-blog">Documentazione del plugin</a></li>
    33         <li><a href="https://github.com/WPGov/amministrazione-trasparente" class="welcome-icon dashicons-editor-code">Migliora il codice su GitHub</a></li>
    34         <li><div class="welcome-icon dashicons-admin-users">Creato da <a href="https://www.marcomilesi.com/">Marco Milesi</a></div></li>
    35         <li><div class="welcome-icon dashicons-groups">Con il contributo di <a href="http://www.porteapertesulweb.it/">Porte Aperte sul Web</a></div></li>
    36       </ul>
     28    <?php
     29    $plugin_slug = 'amministrazione-trasparente';
     30    $wporg_logo_url = 'https://ps.w.org/' . $plugin_slug . '/assets/icon-256x256.jpg';
     31    ?>
     32    <div class="at-intro-banner" style="background:#fff;border:1px solid #e5e5e5;border-radius:8px;padding:24px 32px;margin-bottom:24px;box-shadow:0 2px 8px rgba(0,0,0,0.03);display:flex;align-items:center;gap:32px;">
     33        <div style="flex:0 0 auto;">
     34            <img src="<?php echo esc_url( $wporg_logo_url ); ?>"
     35                 alt="Amministrazione Trasparente"
     36                 style="width:64px;height:64px;padding:8px;">
     37        </div>
     38        <div style="flex:1 1 auto;">
     39            <h2 style="margin-top:0;margin-bottom:8px;font-size:1.5em;"><?php esc_html_e( 'Benvenuto in Amministrazione Trasparente', 'amministrazione-trasparente' ); ?></h2>
     40            <p style="margin:0 0 12px 0;color:#555;">
     41                <?php esc_html_e( 'Gestisci la trasparenza della tua amministrazione pubblica in modo semplice e conforme alle normative italiane. Consulta la documentazione, contribuisci allo sviluppo o scopri chi ha reso possibile questo progetto.', 'amministrazione-trasparente' ); ?>
     42            </p>
     43            <div style="display:flex;flex-wrap:wrap;gap:12px;">
     44                <a href="https://github.com/WPGov/amministrazione-trasparente/wiki" class="button button-primary" target="_blank" rel="noopener noreferrer">
     45                    <?php esc_html_e( 'Documentazione', 'amministrazione-trasparente' ); ?>
     46                </a>
     47                <a href="https://github.com/WPGov/amministrazione-trasparente" class="button" target="_blank" rel="noopener noreferrer">
     48                    <?php esc_html_e( 'Contribuisci su GitHub', 'amministrazione-trasparente' ); ?>
     49                </a>
     50                <a href="https://www.marcomilesi.com/" class="button" target="_blank" rel="noopener noreferrer">
     51                    <?php esc_html_e( 'Autore', 'amministrazione-trasparente' ); ?>
     52                </a>
     53                <a href="http://www.porteapertesulweb.it/" class="button" target="_blank" rel="noopener noreferrer">
     54                    <?php esc_html_e( 'Community Porte Aperte sul Web', 'amministrazione-trasparente' ); ?>
     55                </a>
     56            </div>
     57        </div>
    3758    </div>
    38   </div>
    39 
    40   <?php
    41 
    42   if ( isset($_GET['at_action']) && $_GET['at_action'] == 'debug'  ) {
    43 
    44     at_setting_tabs( 2 );
    45 
    46     echo '<pre>';
    47     $a = get_option('wpgov_at');
    48     if ( is_array( $a ) ) {
    49       $e = filter_var_array( get_option('wpgov_at'), FILTER_SANITIZE_SPECIAL_CHARS);
    50       print_r( $e );
     59
     60    <?php
     61    // Debug tab
     62    if ( isset($_GET['at_action']) && $_GET['at_action'] === 'debug' ) {
     63        at_setting_tabs( 2 );
     64        echo '<pre>';
     65        $a = get_option('wpgov_at');
     66        if ( is_array( $a ) ) {
     67            $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS );
     68            print_r( $e );
     69        } else {
     70            esc_html_e( 'Nessuna impostazione presente', 'amministrazione-trasparente' );
     71        }
     72        echo '</pre>';
     73
     74        echo '<pre>';
     75        $a = get_option('atGroupConf');
     76        if ( is_array( $a ) ) {
     77            $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS );
     78            print_r( $e );
     79        } else {
     80            esc_html_e( 'Nessuna configurazione presente', 'amministrazione-trasparente' );
     81        }
     82        echo '</pre>';
     83
     84    // Config tab
     85    } elseif ( isset($_GET['at_action']) ) {
     86        at_setting_tabs( 1 );
     87
     88        $selected_sections = [];
     89        $selected_sections_unique = [];
     90
     91        $atTerms = get_terms([
     92            'taxonomy'   => 'tipologie',
     93            'parent'     => 0,
     94            'hide_empty' => false,
     95        ]);
     96
     97        if ( is_array( at_getGroupConf() ) ) {
     98            foreach ( at_getGroupConf() as $arrayTipologie ) {
     99                $selected_sections = array_merge( $selected_sections, $arrayTipologie );
     100                $selected_sections_unique = array_unique( array_merge( $selected_sections, $arrayTipologie ) );
     101            }
     102        }
     103
     104        $diff = array_diff_assoc( $selected_sections, array_unique( $selected_sections ) );
     105        $alert_duplicates = esc_js( "Elenco duplicati:\n" );
     106        if ( is_array( $diff ) && !empty( $diff ) ) {
     107            foreach ( $diff as $x ) {
     108                $duplicate_term = get_term_by( 'id', $x, 'tipologie' );
     109                if ( $duplicate_term && $duplicate_term->name ) {
     110                    $alert_duplicates .= '- ' . esc_js( $duplicate_term->name ) . '\n';
     111                }
     112            }
     113        }
     114
     115        $green_svg = '<span style="color:green" aria-label="OK">&#x2714;</span>';
     116        $red_svg = '<span style="color:red;" aria-label="Errore">&#x26A0;</span>';
     117
     118        $warning_count = '';
     119        $alert_count = esc_js( "Elenco tipologie non associate:\n" );
     120        if ( wp_count_terms( 'tipologie' ) != count( array_count_values( $selected_sections ) ) ) {
     121            foreach ( $atTerms as $term ) {
     122                if ( !in_array( $term->term_id, $selected_sections_unique ) ) {
     123                    $alert_count .= '- ' . esc_js( $term->name ) . '\n';
     124                    if ( !empty( $selected_sections_unique ) ) {
     125                        $max = max( array_keys( $selected_sections_unique ) );
     126                        $selected_sections_unique[ ++$max ] = $term->term_id;
     127                    }
     128                }
     129            }
     130            $warning_count = ' ' . esc_html( wp_count_terms( 'tipologie' ) - count( array_count_values( $selected_sections ) ) ) . ' tipologie non sono associate a un gruppo - <a href="#" onclick="alert(\'' . $alert_count . '\');return false;">Clicca qui per i dettagli</a>';
     131        } else {
     132            $warning_count = $green_svg;
     133        }
     134
     135        $warning_duplicates = '';
     136        if ( ( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) != 0 ) {
     137            $warning_duplicates = $red_svg . ' Verificare se intenzionale - <a href="#" onclick="alert(\'' . $alert_duplicates . '\');return false;">Clicca qui per i dettagli</a>';
     138        } else {
     139            $warning_duplicates = $green_svg;
     140        }
     141        ?>
     142        <h3><?php esc_html_e( 'Tipologie', 'amministrazione-trasparente' ); ?></h3>
     143        <table class="widefat fixed striped" cellspacing="0">
     144            <thead>
     145                <tr>
     146                    <th class="manage-column"><?php esc_html_e( 'Controllo', 'amministrazione-trasparente' ); ?></th>
     147                    <th class="manage-column num"><?php esc_html_e( 'Esito', 'amministrazione-trasparente' ); ?></th>
     148                </tr>
     149            </thead>
     150            <tbody>
     151                <tr class="alternate">
     152                    <td><?php echo esc_html( wp_count_terms( 'tipologie' ) ); ?> tipologie gestite</td>
     153                    <td><?php echo ( wp_count_terms( 'tipologie' ) > 0 ? $green_svg : $red_svg ); ?></td>
     154                </tr>
     155                <tr>
     156                    <td><?php echo esc_html( count( array_count_values( $selected_sections ) ) ); ?> tipologie correttamente associate nei gruppi</td>
     157                    <td><?php echo $warning_count; ?></td>
     158                </tr>
     159                <tr class="alternate">
     160                    <td><?php echo esc_html( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ); ?> tipologie sono associate a più gruppi</td>
     161                    <td><?php echo $warning_duplicates; ?></td>
     162                </tr>
     163            </tbody>
     164        </table>
     165        <br><br>
     166        <p><?php esc_html_e( 'Puoi aggiungere o modificare le singole sezioni di Amministrazione trasparente:', 'amministrazione-trasparente' ); ?></p>
     167        <a href="<?php echo esc_url( admin_url( 'edit-tags.php?taxonomy=tipologie&post_type=amm-trasparente' ) ); ?>" class="button-secondary"><?php esc_html_e( 'Aggiungi o modifica tipologie', 'amministrazione-trasparente' ); ?></a>
     168        <hr>
     169        <h3><?php esc_html_e( 'Gruppi', 'amministrazione-trasparente' ); ?></h3>
     170        <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     171        <form method="post" action="options.php" id="at-groupconf-form">
     172            <?php
     173            settings_fields( 'wpgov_at_option_groups' );
     174            $options = get_option( 'atGroupConf' );
     175            $all_terms = [];
     176            foreach ( $atTerms as $term ) {
     177                $all_terms[ $term->term_id ] = $term->name;
     178            }
     179            ?>
     180            <div class="at-groups-stack">
     181            <?php foreach ( at_get_taxonomy_groups() as $group ) :
     182                $group_slug = sanitize_title( $group );
     183                $sezione = at_getGroupConf( $group_slug );
     184            ?>
     185                <div class="at-group-card" style="background:#fff;border:1px solid #e5e5e5;border-radius:8px;box-shadow:0 2px 8px rgba(0,0,0,0.03);padding:20px;max-width:700px;margin:0 auto 24px auto;">
     186                    <h4 style="margin-top:0;margin-bottom:12px;font-size:1.1em;display:flex;align-items:center;justify-content:space-between;">
     187                        <span><?php echo esc_html( $group ); ?></span>
     188                        <span style="color:#888;font-size:0.9em;"><?php echo esc_html( count( $sezione ) ); ?> tipologie</span>
     189                    </h4>
     190                    <ul class="at-sortable-list" id="sortable-<?php echo esc_attr( $group_slug ); ?>" style="margin-bottom:10px;padding-left:0;list-style:none;min-height:36px;">
     191                        <?php
     192                        if ( !empty( $sezione ) ) :
     193                            foreach ( $sezione as $term_id ) :
     194                                if ( isset( $all_terms[ $term_id ] ) ) :
     195                        ?>
     196                            <li class="at-sortable-item" style="margin:2px 0;padding:8px 12px;background:#f7f7f7;border:1px solid #e5e5e5;border-radius:4px;cursor:move;display:flex;align-items:center;justify-content:space-between;">
     197                                <span><?php echo esc_html( $all_terms[ $term_id ] ); ?></span>
     198                                <button type="button" class="button-link at-remove-term" data-term="<?php echo esc_attr( $term_id ); ?>" title="<?php esc_attr_e( 'Rimuovi', 'amministrazione-trasparente' ); ?>">&times;</button>
     199                                <input type="hidden" name="atGroupConf[<?php echo esc_attr( $group_slug ); ?>][]" value="<?php echo esc_attr( $term_id ); ?>">
     200                            </li>
     201                        <?php
     202                                endif;
     203                            endforeach;
     204                        endif;
     205                        ?>
     206                    </ul>
     207                    <div style="display:flex;gap:8px;">
     208                        <select class="at-add-term-select" style="min-width:180px;">
     209                            <option value=""><?php esc_html_e( 'Aggiungi tipologia…', 'amministrazione-trasparente' ); ?></option>
     210                            <?php
     211                            foreach ( $all_terms as $term_id => $term_name ) {
     212                                if ( empty( $sezione ) || !in_array( $term_id, $sezione ) ) {
     213                                    echo '<option value="' . esc_attr( $term_id ) . '">' . esc_html( $term_name ) . '</option>';
     214                                }
     215                            }
     216                            ?>
     217                        </select>
     218                        <button type="button" class="button at-add-term-btn"><?php esc_html_e( 'Aggiungi', 'amministrazione-trasparente' ); ?></button>
     219                    </div>
     220                </div>
     221            <?php endforeach; ?>
     222            </div>
     223            <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     224        </form>
     225        <script>
     226        jQuery(function($){
     227            // Enable sortable for each group
     228            $('.at-sortable-list').sortable({
     229                placeholder: "ui-state-highlight",
     230                axis: "y"
     231            });
     232
     233            // Remove term from group
     234            $('.at-sortable-list').on('click', '.at-remove-term', function(){
     235                $(this).closest('li').remove();
     236            });
     237
     238            // Add term to group
     239            $('.at-add-term-btn').on('click', function(){
     240                var $container = $(this).closest('.at-group-card');
     241                var $select = $container.find('.at-add-term-select');
     242                var termId = $select.val();
     243                var termName = $select.find('option:selected').text();
     244                if(termId){
     245                    var $list = $container.find('.at-sortable-list');
     246                    // Prevent duplicates
     247                    if($list.find('input[value="'+termId+'"]').length === 0){
     248                        var groupSlug = $list.attr('id').replace('sortable-','');
     249                        var $li = $('<li class="at-sortable-item" style="margin:2px 0;padding:8px 12px;background:#f7f7f7;border:1px solid #e5e5e5;border-radius:4px;cursor:move;display:flex;align-items:center;justify-content:space-between;">'
     250                            + '<span>'+termName+'</span>'
     251                            + '<button type="button" class="button-link at-remove-term" data-term="'+termId+'" title="<?php esc_attr_e( 'Rimuovi', 'amministrazione-trasparente' ); ?>">&times;</button>'
     252                            + '<input type="hidden" name="atGroupConf['+groupSlug+'][]" value="'+termId+'">'
     253                            + '</li>');
     254                        $list.append($li);
     255                        $select.find('option[value="'+termId+'"]').remove();
     256                    }
     257                }
     258                $select.val('');
     259            });
     260        });
     261        </script>
     262        <style>
     263        .at-groups-stack {
     264            display: block;
     265        }
     266        .at-group-card {
     267            width: 100%;
     268            max-width: 700px;
     269            margin: 0 auto 24px auto;
     270        }
     271        .at-sortable-list .ui-state-highlight { background: #e0f7fa; border: 1px dashed #0073aa; min-height: 36px; }
     272        .at-sortable-item .at-remove-term { color: #b32d2e; font-size: 1.2em; margin-left: 8px; }
     273        .at-sortable-item .at-remove-term:hover { color: #dc3232; }
     274        </style>
     275        <?php
     276
     277    // General tab
    51278    } else {
    52       echo 'Nessuna impostazione presente';
     279        at_setting_tabs( 0 );
     280        ?>
     281        <form method="post" action="options.php">
     282            <?php
     283            settings_fields( 'wpgov_at_options' );
     284            wp_nonce_field( 'wpgov_at_save_settings', 'wpgov_at_nonce' );
     285            $options = get_option( 'wpgov_at' );
     286            ?>
     287            <table class="form-table">
     288                <tr valign="top">
     289                    <th scope="row">
     290                        <label for="at_option_id"><?php esc_html_e( 'ID Pagina', 'amministrazione-trasparente' ); ?></label>
     291                    </th>
     292                    <td>
     293                        <input id="at_option_id" type="number" min="0" name="wpgov_at[page_id]" value="<?php echo esc_attr( isset( $options['page_id'] ) ? $options['page_id'] : '' ); ?>" size="55" />
     294                        <br>
     295                        <small>
     296                            <?php esc_html_e( 'ID della pagina di WordPress in cui è stato inserito lo shortcode del plugin.', 'amministrazione-trasparente' ); ?><br>
     297                            <?php esc_html_e( 'Lista shortcode:', 'amministrazione-trasparente' ); ?>
     298                            <a href="https://github.com/WPGov/amministrazione-trasparente/wiki/Shortcode" target="_blank" rel="noopener noreferrer">link</a>
     299                        </small>
     300                    </td>
     301                </tr>
     302                <tr valign="top">
     303                    <th scope="row">
     304                        <label for="at_option_opacity"><?php esc_html_e( 'Sfuma sezioni vuote', 'amministrazione-trasparente' ); ?></label>
     305                    </th>
     306                    <td>
     307                        <input id="at_option_opacity" name="wpgov_at[opacity]" type="checkbox" value="1" <?php checked( '1', isset( $options['opacity'] ) && $options['opacity'] ); ?> />
     308                        <br>
     309                        <small><?php esc_html_e( 'Aumenta la trasparenza visiva delle sezioni senza alcun contenuto. Consigliato: ON', 'amministrazione-trasparente' ); ?></small>
     310                    </td>
     311                </tr>
     312                <tr valign="top">
     313                    <th scope="row">
     314                        <label for="at_enable_tag"><?php esc_html_e( 'Abilita tag', 'amministrazione-trasparente' ); ?></label>
     315                    </th>
     316                    <td>
     317                        <input id="at_enable_tag" name="wpgov_at[enable_tag]" type="checkbox" value="1" <?php checked( '1', isset( $options['enable_tag'] ) && $options['enable_tag'] ); ?> />
     318                        <br>
     319                        <small><?php esc_html_e( 'Consenti di associare dei tag ai post di Amministrazione Trasparente. Consigliato: OFF', 'amministrazione-trasparente' ); ?></small>
     320                    </td>
     321                </tr>
     322                <tr valign="top">
     323                    <th scope="row">
     324                        <label for="at_show_love"><?php esc_html_e( 'Mostra credits', 'amministrazione-trasparente' ); ?></label>
     325                    </th>
     326                    <td>
     327                        <input id="at_show_love" name="wpgov_at[show_love]" type="checkbox" value="1" <?php checked( '1', isset( $options['show_love'] ) && $options['show_love'] ); ?> />
     328                        <br>
     329                        <small><?php esc_html_e( 'Aiutaci a far conoscere il progetto e ottieni una via preferenziale per il supporto. Consigliato: ON', 'amministrazione-trasparente' ); ?></small>
     330                    </td>
     331                </tr>
     332                <tr valign="top">
     333                    <th scope="row" colspan="2">
     334                        <h2><?php esc_html_e( 'Avanzate', 'amministrazione-trasparente' ); ?></h2>
     335                    </th>
     336                </tr>
     337                <tr valign="top">
     338                    <th scope="row">
     339                        <label for="at_enable_ucc"><?php esc_html_e( 'Abilita uffici e Centri di costo', 'amministrazione-trasparente' ); ?></label>
     340                    </th>
     341                    <td>
     342                        <input id="at_enable_ucc" name="at_enable_ucc" type="checkbox" value="1" <?php checked( '1', isset( $options['enable_ucc'] ) && $options['enable_ucc'] ); ?> />
     343                        <br>
     344                        <small><?php esc_html_e( 'Consenti di associare i contenuti a una nuova tassonomia per uffici e centri di costo. Consigliato: OFF, attivare solo se necessario.', 'amministrazione-trasparente' ); ?></small>
     345                    </td>
     346                </tr>
     347                <tr valign="top">
     348                    <th scope="row">
     349                        <label for="at_map_cap"><?php esc_html_e( 'Mappa capacità', 'amministrazione-trasparente' ); ?></label>
     350                    </th>
     351                    <td>
     352                        <input id="at_map_cap" name="wpgov_at[map_cap]" type="checkbox" value="1" <?php checked( '1', isset( $options['map_cap'] ) && $options['map_cap'] ); ?> />
     353                        <br>
     354                        <small><?php esc_html_e( 'Mappa le meta capacità per personalizzare ruoli e permessi. [per utenti esperti] + [richiede componenti aggiuntivi]. Consigliato: OFF', 'amministrazione-trasparente' ); ?></small>
     355                    </td>
     356                </tr>
     357                <tr valign="top">
     358                    <th scope="row">
     359                        <label for="at_pasw_2013"><?php esc_html_e( 'Forza PASW2013', 'amministrazione-trasparente' ); ?></label>
     360                    </th>
     361                    <td>
     362                        <input id="at_pasw_2013" name="wpgov_at[pasw_2013]" type="checkbox" value="1" <?php checked( '1', isset( $options['pasw_2013'] ) && $options['pasw_2013'] ); ?> />
     363                        <br>
     364                        <small><?php esc_html_e( 'Spunta casella se vuoi attivare ottimizzazioni per il template PASW2013. [abilitare solo se il tema attivo è una versione precedente al 2013 o se è stato cambiato il nome della cartella di "pasw2013"]', 'amministrazione-trasparente' ); ?></small>
     365                    </td>
     366                </tr>
     367                <tr valign="top" <?php if ( !isset( $options['custom_terms'] ) || !$options['custom_terms'] ) { echo 'style="display:none;"'; } ?>>
     368                    <th scope="row">
     369                        <label for="custom_terms"><?php esc_html_e( 'Custom Terms', 'amministrazione-trasparente' ); ?></label>
     370                    </th>
     371                    <td>
     372                        <input id="custom_terms" name="wpgov_at[custom_terms]" type="checkbox" value="1" <?php checked( '1', isset( $options['custom_terms'] ) && $options['custom_terms'] ); ?> />
     373                        <br>
     374                        <small><?php esc_html_e( 'Utile in caso di test da parte del servizio di supporto. Mantienila disattivata!', 'amministrazione-trasparente' ); ?></small>
     375                    </td>
     376                </tr>
     377            </table>
     378            <?php submit_button( __( 'Salva configurazione', 'amministrazione-trasparente' ) ); ?>
     379        </form>
     380        <?php
     381        // Optional: Debug info for advanced users
     382        if ( at_option('debug') ) {
     383            echo '<hr><h3>DEBUG</h3>';
     384            $terms = get_terms( [ 'taxonomy' => 'tipologie', 'hide_empty' => false ] );
     385            echo esc_html__( 'Numero sezioni installate:', 'amministrazione-trasparente' ) . ' ' . esc_html( count( $terms ) ) . '<br>';
     386            $count = 0;
     387            $merge = [];
     388            foreach ( amministrazionetrasparente_getarray() as $inner ) {
     389                $count += count( $inner[1] );
     390                $merge = array_merge( $merge, $inner[1] );
     391            }
     392            sort( $merge );
     393            echo esc_html__( 'Numero sezioni supportate dal plugin:', 'amministrazione-trasparente' ) . ' ' . esc_html( $count );
     394            echo '<hr>';
     395            echo '<div style="width:45%;float:left;"><h4>' . esc_html__( 'Installate:', 'amministrazione-trasparente' ) . '</h4><ul>';
     396            foreach ( $terms as $term ) {
     397                echo '<li>' . esc_html( $term->name ) . '</li>';
     398            }
     399            echo '</ul></div>';
     400            echo '<div style="width:45%;float:left;"><h4>' . esc_html__( 'Supportate:', 'amministrazione-trasparente' ) . '</h4><ul>';
     401            foreach ( $merge as $merge_item ) {
     402                echo '<li>' . esc_html( $merge_item ) . '</li>';
     403            }
     404            echo '</ul></div><hr>';
     405        }
    53406    }
    54     echo '</pre>';
    55 
    56     echo '<pre>';
    57     $a = get_option('atGroupConf');
    58     if ( is_array( $a ) ) {
    59       $e = filter_var_array( $a, FILTER_SANITIZE_SPECIAL_CHARS);
    60       print_r( $e );
    61     } else {
    62       echo 'Nessuna configurazione presente';
    63     }
    64     echo '</pre>'; 
    65 
    66   } else if ( isset($_GET['at_action']) ) {
    67 
    68     at_setting_tabs( 1 );
    69 
    70     $selected_sections = array();
    71     $selected_sections_unique = array();
    72 
    73     $atTerms = get_terms(
    74       array(
    75         'taxonomy' => 'tipologie',
    76         'parent'   => 0,
    77         'hide_empty' => false,
    78       )
    79     );
    80 
    81     if( is_array( at_getGroupConf() ) ) {
    82       foreach ( at_getGroupConf() as $key => $arrayTipologie ) {
    83         $selected_sections = array_merge( $selected_sections, $arrayTipologie );
    84         $selected_sections_unique = array_unique( array_merge( $selected_sections, $arrayTipologie ) );
    85       }
    86     }
    87 
    88     $diff = array_diff_assoc($selected_sections, array_unique($selected_sections) );
    89     $alert_duplicates = 'Elenco duplicati:\n';
    90     if ( is_array( $diff ) && !empty( $diff ) ) {
    91       foreach ( $diff as $x ) {
    92         $duplicate_term = get_term_by('id', $x, 'tipologie');
    93         if ( $duplicate_term && $duplicate_term->name ) {
    94           $alert_duplicates .= '- '.esc_js($duplicate_term->name). '\n';
    95         }
    96       }
    97     }
    98 
    99     $green_svg = '<span style="color:green"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-circle-fill" viewBox="0 0 16 16"><path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/></svg></span>';
    100     $red_svg = '<span style="color:red;"><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle-fill" viewBox="0 0 16 16"><path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/></svg></span>';
    101 
    102     $warning_count = '';
    103     $alert_count = 'Elenco tipologie non associate:\n';
    104     if ( wp_count_terms( 'tipologie' ) != count( array_count_values( $selected_sections ) ) ) {
    105       foreach( $atTerms as $term ) {
    106         if ( !in_array( $term->term_id, $selected_sections_unique ) ) {
    107           $alert_count .= '- '.esc_js($term->name) . '\n';
    108           if ( !empty( $selected_sections_unique) ) {
    109             $max = max( array_keys( $selected_sections_unique ) );
    110             $selected_sections_unique[ ++$max ] = $term->term_id;
    111           }
    112          
    113         }
    114       }
    115       $warning_count = ' '.(wp_count_terms( 'tipologie' ) - count( array_count_values( $selected_sections ) ) ).' tipologie non sono associate a un gruppo - <a href="#" onclick="alert(\''.$alert_count.'\');">Clicca qui per i dettagli</a></b>';
    116     } else {
    117       $warning_count = $green_svg;
    118     }
    119 
    120     $warning_duplicates = '';
    121     if ( ( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) != 0 ) {
    122       $warning_duplicates = $red_svg.' Verificare se intenzionale - <a href="#" onclick="alert(\''.$alert_duplicates.'\');">Clicca qui per i dettagli</a>';
    123     } else {
    124       $warning_duplicates = $green_svg;
    125     }
    126     echo '<h3>Tipologie</h3>';
    127    
    128     echo '<table class="widefat fixed" cellspacing="0">
    129     <thead>
    130     <tr>
    131             <th id="columnname" class="manage-column column-columnname" scope="col">Controllo</th>
    132             <th id="columnname" class="manage-column column-columnname num" scope="col">Esito</th>
    133     </tr>
    134     </thead>
    135     <tbody>
    136         <tr class="alternate">
    137             <td class="column-columnname">'.wp_count_terms( 'tipologie' ).'</b> tipologie gestite</td>
    138             <td class="column-columnname">'.(wp_count_terms( 'tipologie' ) > 0 ? $green_svg : $red_svg ).'</td>
    139         </tr>
    140         <tr>
    141             <td class="column-columnname">'. count( array_count_values( $selected_sections ) ) . '</b> tipologie correttamente associate nei gruppi</td>
    142             <td class="column-columnname">'.$warning_count.'</td>
    143         </tr>
    144         <tr class="alternate">
    145             <td class="column-columnname">'.( count( $selected_sections ) - count( array_count_values( $selected_sections ) ) ) . '</b> tipologie sono associate a più gruppi</td>
    146             <td class="column-columnname">'.$warning_duplicates.'</td>
    147         </tr>
    148     </tbody>
    149   </table>
    150   <br><br>
    151   <p>Puoi aggiungere o modificare le singole sezioni di Amministrazione trasparente:</p>
    152   <a href="edit-tags.php?taxonomy=tipologie&post_type=amm-trasparente" class="button-secondary">Aggiungi o modifica tipologie</a>
    153   <hr><h3>Gruppi</h3>';
    154     echo '<form method="post" action="options.php">';
    155     settings_fields( 'wpgov_at_option_groups' );
    156 
    157     $options = get_option( 'atGroupConf' );
    158    
    159  
    160     foreach ( at_get_taxonomy_groups() as $group ) {
    161       echo '<details style="margin:10px;"><summary style="margin: 10px;"><b>'.$group.'</b>';
    162       $sezione = at_getGroupConf( sanitize_title( $group ) );
    163       echo ' ('.count($sezione).')';
    164       echo '</summary>';
    165       echo '<div>';
    166       $dropdownOptions = array();
    167       foreach( $atTerms as $term ) {
    168         $atSelected = ( in_array( $term->term_id, $sezione) ? 'selected' : '' );
    169 
    170         $arrayIndex = array_search( $term->term_id, $selected_sections_unique );
    171         $dropdownOptions[ $arrayIndex ] = '<option value="'.$term->term_id.'" '.$atSelected.'>'.$term->name.'</option>';
    172       }
    173       ksort( $dropdownOptions ); // Order by key to keep default AT order
    174       $dropdownOptionsEcho = '';
    175       foreach( $dropdownOptions as $x ) {
    176         $dropdownOptionsEcho .= $x;
    177       }
    178       echo '<select id="'.sanitize_title( $group ).'" name="atGroupConf['.sanitize_title( $group ).'][]" multiple="multiple">';
    179       echo $dropdownOptionsEcho;
    180       echo '</select>';
    181 
    182       echo '<script>jQuery("#'.sanitize_title( $group ).'").multiSelect( { keepOrder: true, selectableHeader: "Disponibili:", selectionHeader: "Selezionate:" } );</script>';
    183       echo '</div>';
    184       echo '</details>';
    185     }
    186 
    187     submit_button( 'Salva configurazione' );
    188     echo '</form>';
    189 
    190   } else {
    191     at_setting_tabs( 0 );
    192 
    193     echo '<form method="post" action="options.php">';
    194 
    195     settings_fields( 'wpgov_at_options');
    196     $options = get_option( 'wpgov_at');
    197   ?>
    198   <table class="form-table">
    199     <tr valign="top">
    200             <th scope="row">
    201               <label for="at_option_id">ID Pagina</label>
    202             </th>
    203             <td>
    204               <input id="at_option_id" type="number" min="0" name="wpgov_at[page_id]" value="<?php echo esc_html( isset( $options['page_id'] ) ? $options['page_id'] : '' ); ?>" size="55" />
    205               <br>
    206               <small>ID della pagina di WordPress in cui è stato inserito lo shortcode del plugin).<br>
    207               Lista shortcode: <a href="https://github.com/WPGov/amministrazione-trasparente/wiki/Shortcode">link</a></small>
    208             </td>
    209           </tr>
    210 
    211           <tr valign="top">
    212     <th scope="row">
    213       <label for="at_option_opacity">Sfuma sezioni vuote</label>
    214     </th>
    215     <td>
    216       <input id="at_option_opacity" name="wpgov_at[opacity]" type="checkbox" value="1"
    217         <?php checked( '1', isset($options['opacity']) && $options['opacity'] ); ?> />
    218       <br>
    219       <small>Aumenta la trasparenza visiva delle sezioni senza alcun contenuto<br>Consigliato: <b>ON</b></small>
    220     </td>
    221   </tr>
    222   <tr valign="top">
    223     <th scope="row">
    224       <label for="at_enable_tag">Abilita tag</label>
    225     </th>
    226     <td>
    227       <input id="at_enable_tag" name="wpgov_at[enable_tag]" type="checkbox" value="1"
    228         <?php checked( '1', isset( $options['enable_tag'] ) && $options['enable_tag'] ); ?> />
    229       <br><small>Consenti di associare dei tag ai post di Amministrazione Trasparente<br>Consigliato: <b>OFF</b></small>
    230     </td>
    231   </tr>
    232   <tr valign="top">
    233     <th scope="row">
    234     <label for="at_show_love">Mostra credits</label>
    235     </th>
    236     <td>
    237       <input id="at_show_love" name="wpgov_at[show_love]" type="checkbox" value="1"
    238         <?php checked( '1', isset( $options['show_love'] ) && $options['show_love'] ); ?> />
    239       <br><small>Aiutaci a far conoscere il progetto e ottieni una via preferenziale per il supporto<br>Consigliato: <b>ON</b></small>
    240     </td>
    241   </tr>
    242   <tr valign="top">
    243   <th scope="row" colspan="2">
    244     <h2>Avanzate</h2>
    245     <?php if ( isset( $options['enable_ucc'] ) ) { ?>
    246       <tr valign="top">
    247         <th scope="row">
    248           <label for="at_enable_ucc">Abilita uffici e Centri di costo</label>
    249         </th>
    250         <td>
    251           <input id="at_enable_ucc" name="wpgov_at[enable_ucc]" type="checkbox" value="1"
    252             <?php checked( '1', isset( $options['enable_ucc'] ) && $options['enable_ucc'] ); ?> />
    253           <br><small>Consenti di associare i contenuti a una nuova tassonomia basata su divsione aggiuntiva per uffici e centri di costo</small>
    254         </td>
    255       </tr>
    256     <?php } ?>
    257     <tr valign="top">
    258     <th scope="row">
    259     <label for="at_map_cap">Mappa capacità</label>
    260     </th>
    261     <td>
    262     <input id="at_map_cap" name="wpgov_at[map_cap]" type="checkbox" value="1"
    263       <?php checked( '1', isset( $options['map_cap'] ) && $options['map_cap'] ); ?> />
    264     <br>
    265     <small>Mappa le meta capacità per personalizzare ruoli e permessi<br>[per utenti esperti] + [richiede componenti aggiuntivi]<br>Consigliato: <b>OFF</b></small>
    266     </td>
    267     </tr>
    268   </th>
    269   </tr>
    270   <tr valign="top">
    271   <th scope="row">
    272   <label for="at_pasw_2013">Forza PASW2013</label>
    273   </th>
    274   <td>
    275   <input id="at_pasw_2013" name="wpgov_at[pasw_2013]" type="checkbox" value="1"
    276     <?php checked( '1', isset( $options['pasw_2013'] ) && $options['pasw_2013'] ); ?> />
    277   <br>
    278   <small>Spunta casella se vuoi attivare ottimizzazioni per il template PASW2013<br>[abilitare solo se il tema attivo è una versione precedente al 2013 o se è stato cambiato il nome della cartella di "pasw2013"]</small>
    279   </td>
    280   </tr>
    281   </th>
    282   </tr>
    283     <tr valign="top" <?php if ( !isset( $options['custom_terms'] ) || !$options['custom_terms'] ) { echo 'style="display:none;"'; } ?>>
    284       <th scope="row">
    285         <label for="custom_terms">Custom Terms</label>
    286       </th>
    287       <td>
    288         <input id="custom_terms" name="wpgov_at[custom_terms]" type="checkbox" value="1"
    289           <?php checked( '1', isset( $options['custom_terms'] ) && $options['custom_terms'] ); ?> />
    290         <br>
    291         <small>Utile in caso di test da parte del servizio di supporto. <b>Mantienila disattivata!</b></small>
    292       </td>
    293     </tr>
    294   </tr>
    295     </table>
    296 
    297 <?php
    298    
    299   submit_button( 'Salva configurazione' );
    300   echo '</form>';
    301   if ( at_option('debug') ) {
    302     echo '<hr><h3>DEBUG</h3>';
    303     $terms = get_terms( array( 'taxonomy' => 'tipologie', 'hide_empty' => false ) );
    304     echo 'Numero sezioni installate: '.count($terms).'<br>';
    305     $count = 0;
    306     $merge = array();
    307     foreach ( amministrazionetrasparente_getarray() as $inner ) {
    308       $count+= count($inner[1]);
    309       $merge = array_merge( $merge, $inner[1] );
    310     }
    311     sort($merge);
    312     echo 'Numero sezioni supportate dal plugin: '.sanitize_text_field( $count );
    313     echo '<hr>';
    314     echo '<div style="width:45%;float:left;"><h4>Installate:</h4>';
    315     echo '<ul>';
    316     foreach ( $terms as $term ) {
    317       echo '<li>'.sanitize_text_field($term->name).'</li>';
    318     }
    319     echo '</ul>';
    320     echo '</div>';
    321     echo '<div style="width:45%;float:left;"><h4>Supportate:</h4>';
    322     echo '<ul>';
    323     foreach ( $merge as $merge_item ) {
    324       echo '<li>'.sanitize_text_field($merge_item).'</li>';
    325     }
    326     echo '</ul>';
    327     echo '</div>';
    328     echo '<hr>';
    329   }
    330 }
    331 ?>
     407    ?>
    332408</div>
  • amministrazione-trasparente/trunk/sezioni.php

    r3301628 r3301857  
    207207      );
    208208}
     209
     210/**
     211 * Get the group name by term slug or term ID.
     212 * If given a term ID, it fetches the term and uses its slug.
     213 * Returns the group name (first element of each array in amministrazionetrasparente_getarray)
     214 * if the term slug matches any of the group's terms' slugs.
     215 */
     216function at_getGroupNameByTerm( $term ) {
     217    if ( is_numeric( $term ) ) {
     218        $term_obj = get_term( $term, 'tipologie' );
     219        if ( ! $term_obj || is_wp_error( $term_obj ) ) {
     220            return '';
     221        }
     222        $slug = $term_obj->slug;
     223    } else {
     224        $slug = $term;
     225    }
     226
     227    // Build a map of term slugs to group names
     228    foreach ( amministrazionetrasparente_getarray() as $group ) {
     229        $group_name = $group[0];
     230        $terms = $group[1];
     231        foreach ( $terms as $term_name ) {
     232            $term_obj = get_term_by( 'name', $term_name, 'tipologie' );
     233            if ( $term_obj && ! is_wp_error( $term_obj ) && $term_obj->slug === $slug ) {
     234                return $group_name;
     235            }
     236        }
     237    }
     238    return 'noo';
     239}
Note: See TracChangeset for help on using the changeset viewer.