Plugin Directory

Changeset 3135883


Ignore:
Timestamp:
08/15/2024 04:10:08 AM (20 months ago)
Author:
mi13
Message:

test to 6.6.1

Location:
mi13-glossary/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • mi13-glossary/trunk/js/mi13_glossary_admin.js

    r2840058 r3135883  
    11/*
    2 mi13_glossary_admin script 0.2
     2mi13_glossary_admin script 0.3
    33*/
    44
     
    1313            dataType: "json",
    1414            type: "post",
    15             data: {"url": $(this).attr('href'),"id": $(this).attr('id'), "val": $('#mi13_glossary_filter option:selected').text()},
     15            data: {"nonce": mi13_glossary_admin.nonce,"url": $(this).attr('href'),"id": $(this).attr('id'), "val": $('#mi13_glossary_filter option:selected').text()},
    1616            timeout: 5000,
    1717            success: function(resp) {
  • mi13-glossary/trunk/mi13-glossary.php

    r3084998 r3135883  
    11<?php
    22/*
    3 Plugin Name:    mi13-glossary
    4 Plugin URI:     https://wordpress.org/plugins/mi13-glossary/
    5 Description:    Glossary plugin for your site (ru).
    6 Version:        3
    7 Author:         mi13
    8  
    9 Copyright 2021-2022  Mihail Nebov  (email: mihail_teo@mail.ru)
    10 
    11 This program is free software; you can redistribute it and/or modify
    12 it under the terms of the GNU General Public License as published by
    13 the Free Software Foundation; either version 2 of the License, or
    14 (at your option) any later version.
    15 
    16 This program is distributed in the hope that it will be useful,
    17 but WITHOUT ANY WARRANTY; without even the implied warranty of
    18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    19 GNU General Public License for more details.
    20 
    21 You should have received a copy of the GNU General Public License
    22 along with this program; if not, write to the Free Software
    23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
     3Plugin Name: mi13-glossary
     4Plugin URI:  https://wordpress.org/plugins/mi13-glossary/
     5Description: Glossary plugin for your site.
     6Version:     4
     7Author:      mi13
     8License:     GPL v2 or later
     9License URI: https://www.gnu.org/licenses/gpl-2.0.html
     10
    2411*/
    2512
    26 if( !defined( 'ABSPATH')) exit();
    27 
    28 function mi13_glossary_install() {
     13if( !defined( 'ABSPATH') ) exit();
     14
     15function mi13_glossary_install(){
    2916    $default_settings = array(
    3017        'ignore' => 'script,style,h1,h2,h3,h4,h5,h6,a,pre,code,span,mark',
     
    3724register_activation_hook(__FILE__,'mi13_glossary_install');
    3825
    39 function mi13_glossary_deactivate() {
     26function mi13_glossary_deactivate(){
    4027    unregister_setting('mi13_glossary', 'mi13_glossary');
    4128    unregister_post_type('mi13_glossary');
     
    4532function mi13_glossary_uninstall()
    4633{
    47     if ( __FILE__ != WP_UNINSTALL_PLUGIN ) return;
     34    if( __FILE__ !== WP_UNINSTALL_PLUGIN ) return;
    4835    $args = array('posts_per_page' => -1,'post_type' => 'mi13_glossary');
    4936    $glos = get_posts($args);
    50     foreach( $glos as $post ) {
     37    foreach( $glos as $post ){
    5138        wp_delete_post($post->ID);
    5239    }
     
    5441    delete_option('mi13_glossary');
    5542}
    56 register_uninstall_hook(    __FILE__, 'mi13_glossary_uninstall' );
     43register_uninstall_hook( __FILE__, 'mi13_glossary_uninstall' );
    5744
    5845add_action('init', 'mi13_glossary_init');
    5946function mi13_glossary_init(){
    60     function mi13_glossary_valid($settings) {
    61         $settings['ignore'] = strip_tags(wp_specialchars_decode($settings['ignore'],ENT_QUOTES));
    62         $settings['link_style'] = strip_tags($settings['link_style']);
     47    function mi13_glossary_valid($settings){
     48        $settings['ignore'] = wp_strip_all_tags( wp_specialchars_decode($settings['ignore'],ENT_QUOTES) );
     49        $settings['link_style'] = wp_strip_all_tags( $settings['link_style'] );
    6350        $settings['publish_stop'] = isset($settings['publish_stop']) ? boolval($settings['publish_stop']) : 0;
    64         $settings['pattern'] = isset($settings['pattern']) ? strip_tags($settings['pattern']) : '[а-я\x{0301}]{0,4}';
    65     return $settings;
     51        $settings['pattern'] = isset($settings['pattern']) ? wp_strip_all_tags( $settings['pattern'] ) : '[а-я\x{0301}]{0,4}';
     52        return $settings;
    6653    }
    6754    register_setting( 'mi13_glossary', 'mi13_glossary', 'mi13_glossary_valid' );
     
    7865}
    7966
    80 function mi13_glossary_menu() {
    81     function mi13_glossary_admin_scripts() {
    82         wp_enqueue_script('mi13_glossary_admin', plugins_url('/js/mi13_glossary_admin.js',__FILE__), array('jquery'),'0.2',true);
     67function mi13_glossary_menu(){
     68    function mi13_glossary_admin_scripts(){
     69        wp_enqueue_script('mi13_glossary_admin', plugins_url('/js/mi13_glossary_admin.js',__FILE__), array('jquery'),'0.3',true);
     70        wp_localize_script( 'mi13_glossary_admin', 'mi13_glossary_admin',
     71            array(
     72                'nonce' => wp_create_nonce('mi13_glossary_admin'),
     73            )
     74        ); 
    8375    }
    8476    $page = add_options_page(
     
    9486
    9587add_action( "load-post.php", 'mi13_glossary_help_tabs' );
    96 function mi13_glossary_help_tabs() {
     88function mi13_glossary_help_tabs(){
    9789    $screen = get_current_screen();
    98     if ( ($screen->id == 'mi13_glossary') ) {
     90    if( $screen->id == 'mi13_glossary' ){
    9991        $screen->add_help_tab(
    10092            array(
     
    111103}
    112104
    113 function mi13_glossary_scripts() {
    114     if ( is_singular( 'post' ) ) {
     105function mi13_glossary_scripts(){
     106    if( is_singular( 'post' ) ){
    115107        $settings = get_option('mi13_glossary');
    116108        wp_enqueue_script('mi13_glossary', plugins_url('/js/mi13_glossary.js',__FILE__), array(),'0.2',true);
    117109        wp_enqueue_style('mi13_glossary', plugins_url('/css/mi13_glossary.css',__FILE__), array(),'0.1');
    118        
    119110        $style = $settings['link_style'];
    120         if( empty( $style ) ) {
     111        if( empty( $style ) ){
    121112            $style .= '.mi13_glossary_link{color:green;cursor:pointer;}.mi13_glossary_link:hover{color:orange;}';
    122113        }
     
    124115        wp_localize_script( 'mi13_glossary', 'mi13_glossary_ajax',
    125116            array(
    126                 'url' => admin_url('admin-ajax.php?action=mi13_glossary')
     117                'url' => admin_url('admin-ajax.php?action=mi13_glossary'),
    127118            )
    128119        );     
     
    131122add_action('wp_enqueue_scripts', 'mi13_glossary_scripts');
    132123
    133 if( wp_doing_ajax() ) {
     124if( wp_doing_ajax() ){
    134125    add_action('wp_ajax_mi13_glossary', 'mi13_glossary_modal_ajax');
    135126    add_action('wp_ajax_nopriv_mi13_glossary', 'mi13_glossary_modal_ajax');
    136127}
    137128
    138 function mi13_glossary_modal_ajax() { // функция вызова модального окна
    139     if (isset($_GET['id']) && isset($_GET['pos'])) {
     129function mi13_glossary_modal_ajax(){ // функция вызова модального окна
     130    if(isset($_GET['id']) && isset($_GET['pos'])){
    140131        $idstr = sanitize_text_field($_GET['id']);
    141132        $pos = sanitize_text_field($_GET['pos']);
    142133        $id = substr($idstr,3,4);
    143         if( is_numeric($id) && is_numeric($pos) && ($id>0) ) {
     134        if( is_numeric($id) && is_numeric($pos) && $id>0 ){
    144135            echo '<div class="mi13_glossary_content">';
    145136            global $post;
    146137            $post = get_post($id);
    147             if ($post && ($post->post_type==='mi13_glossary'))  {
     138            if( $post && $post->post_type==='mi13_glossary' )  {
    148139                setup_postdata( $post );
    149140                the_content();
     
    160151
    161152function mi13_glossary($text){ //Пойск ключевых слов в теле поста
    162     if ( is_singular( 'post' ) & !get_post_format() ) {
     153    if( is_singular( 'post' ) & !get_post_format() ){
    163154        $array = get_transient('mi13_glossary');
    164         if ($array===false) {
     155        if( $array === false ){
    165156            $args = array('posts_per_page' => -1,'post_type' => 'mi13_glossary','post_status' => 'publish');
    166157            $glos = get_posts($args);
    167158            $n = 0;
    168159            $array = [];
    169             foreach( $glos as $post ) {
     160            foreach( $glos as $post ){
    170161                $array[$n]['title'] = $post->post_title;
    171162                $array[$n]['id'] = $post->ID;
     
    173164            }
    174165            unset($glos);
    175             set_transient('mi13_glossary',$array,DAY_IN_SECONDS);
     166            set_transient( 'mi13_glossary', $array,DAY_IN_SECONDS );
    176167        }
    177168       
    178         if(!empty($array)) {
     169        if( $array ){
    179170            $settings = get_option('mi13_glossary');
    180        
    181171            $ignore = $settings['ignore'];
    182172            $ignore = preg_quote($ignore, '/');
    183173            $ignore = str_replace(',','|',$ignore);
    184            
    185174            preg_match_all( '@<(' . $ignore . ')[^>]*?\>.*?</\\1>@si', $text, $tags, PREG_SET_ORDER );
    186175            $text = preg_replace( '@<(' . $ignore . ')[^>]*?\>.*?</\\1>@si','<mi13_glossary_tag>', $text); // Вырезаем теги с содержимым
    187            
    188176            preg_match_all( '/\<\/?[^>]+>/U', $text, $only_tags,PREG_SET_ORDER ); // Вырезаем все остальные теги
    189177            $text = preg_replace( '/\<\/?[^>]+>/U','<mi13_glossary_only_tag>',$text);
    190            
    191             usort($array, function($a, $b) {
     178            usort($array, function($a, $b){
    192179                return strlen($a["title"]) < strlen($b["title"]) ? 1 : -1;
    193180            }); // Сортируем лестницей чтобы исключить повторного пойска
    194            
    195             foreach( $array as $key ) {
     181            foreach( $array as $key ){
    196182                $str = $key['title'];
    197183                $tok = strtok( $str, " ");
     
    199185                $return = '<span class="mi13_glossary_link" onclick="mi13_glossary()" data="map' . $key['id'] . '">'; // map для того чтобы число из id не участвовало в пойске
    200186                $n = 0;
    201                 while ( $tok !== false ) {
    202                     if($n>=1) {
     187                while ( $tok !== false ){
     188                    if($n>=1){
    203189                        $search .= '\s';
    204190                        $return .= 'mi13_glossary_spase'; // Тоже, чтобы исключить повторный пойск, но не обязательно
     
    216202            unset($array);
    217203            $text = str_replace('mi13_glossary_spase',' ',$text);
    218             foreach( $only_tags as $tag ) {
     204            foreach( $only_tags as $tag ){
    219205                $text = preg_replace( '/\<mi13_glossary_only_tag>/',$tag[0],$text,1);
    220206            }
    221             foreach( $tags as $tag ) {
     207            foreach( $tags as $tag ){
    222208                $text = preg_replace( '/\<mi13_glossary_tag>/',$tag[0],$text,1);
    223209            }
     
    230216add_filter( 'the_content', 'mi13_glossary',99);
    231217
    232 function mi13_glossary_page_table($action=null,$page=null,$val=null) { // Тест на странице настроек плагина
     218function mi13_glossary_page_table($action=null,$page=null,$val=null){ // Тест на странице настроек плагина
    233219    $return = '';
    234220    $posts_per_page = -1;
     
    236222    $button_test = '';
    237223    $h3title = '';
    238     if( $action ) {
     224    if( $action ){
    239225        $args = array(
    240226            'posts_per_page' => -1,
     
    243229        );
    244230        $glos = get_posts($args);
    245         if($glos) {
     231        if($glos){
    246232            function mi13_glossary_num_decline( $intnum, $titles ){ // https://wp-kama.ru/note/funktsiya-skloneniya-slov-posle-chisel-php
    247233                $titles = preg_split( '/, */', $titles );
     
    262248            $ignore = str_replace(',','|',$ignore);
    263249            $post__in = [];
    264             if( $val && $val<>'All' ) {
    265                 foreach( $glos as $post ) {
    266                     if( $val == $post->post_title ) {
     250            if( $val && $val<>'All' ){
     251                foreach( $glos as $post ){
     252                    if( $val == $post->post_title ){
    267253                        $tok = strtok( $val, " ");
    268254                        $search = '/\b';
    269255                        $n = 0;
    270                         while ( $tok !== false ) {
    271                             if($n>=1) {
     256                        while ( $tok !== false ){
     257                            if($n>=1){
    272258                                $search .= '\s';
    273259                            }
     
    288274            }
    289275            else {
    290                 foreach( $glos as $post ) {
     276                foreach( $glos as $post ){
    291277                    $title = $post->post_title;
    292278                    $tok = strtok( $title, " ");
    293279                    $search = '/\b';
    294280                    $n = 0;
    295                     while ( $tok !== false ) {
    296                         if($n>=1) {
     281                    while ( $tok !== false ){
     282                        if($n>=1){
    297283                            $search .= '\s';
    298284                        }
     
    312298            }
    313299            unset($glos);
    314             usort($keys, function($a, $b) {
     300            usort($keys, function($a, $b){
    315301                return strlen($a["title"]) < strlen($b["title"]) ? 1 : -1;
    316302            });
     
    337323                )
    338324            );
    339             if( $action == 'mi13_glossary_test_posts' ) {
     325            if( $action == 'mi13_glossary_test_posts' ){
    340326                $posts_per_page = 10;
    341                 if (isset($page)) $paged = intval($page);
    342                 else $paged = (isset($_GET['n_page']) && intval($_GET['n_page'])>1) ? intval($_GET['n_page']) : 1;
    343                 if( $val && $val<>'All' && isset($keys[0]) ) {
     327                if(isset($page)) $paged = intval($page);
     328                if( $val && $val<>'All' && isset($keys[0]) ){
    344329                    $h3title .= '<h3>Тест ключа <i>&lt;' . $val . '&gt;</i> в постах';
    345330                    $posts = get_posts($args);
    346                     foreach( $posts as $post ) {
     331                    foreach( $posts as $post ){
    347332                        $id = $post->ID;
    348333                        $title = $post->post_title;
     
    351336                        $text = preg_replace( '/\<\/?[^>]+>/U','',$text);
    352337                        preg_match($keys[0]['search'],$text,$matches);
    353                         if( isset($matches[0]) ) {
     338                        if( isset($matches[0]) ){
    354339                            $post__in[] = $id;
    355340                        }
     
    362347                }
    363348                $args['posts_per_page'] = $posts_per_page;
    364                 $args['paged'] = $paged;
    365                 if( count($post__in)>0 ) {
     349                if( $paged ) $args['paged'] = $paged;
     350                if( count( $post__in ) > 0 ){
    366351                    $args['post__in'] = $post__in;
    367352                }
     
    386371                    $text = preg_replace( '/\<\/?[^>]+>/U','',$text);
    387372                    $n=0;
    388                     foreach($keys as $key) {
     373                    foreach($keys as $key){
    389374                        preg_match($key['search'],$text,$matches);
    390375                        $text = preg_replace($key['search'],'',$text,1);
    391                         if(isset($matches[0])) {
     376                        if(isset($matches[0])){
    392377                            $return .=
    393378                            '<tr ' . $alternate . '>
     
    403388                    }
    404389                    unset($text);
    405                     if($n === 0) {
     390                    if($n === 0){
    406391                        $return .=
    407392                        '<tr ' . $alternate . '>
     
    429414                $h3title .= ' (' . $paged . '/' . $posts->max_num_pages . ')';
    430415            }
    431             elseif( $action == 'mi13_glossary_test_keys' ) {
     416            elseif( $action == 'mi13_glossary_test_keys' ){
    432417                $h3title .= '<h3>Тест количества постов с ключом';
    433418                if( $val && $val<>'All' ) $h3title .= ' <i>&lt;' . $val . '&gt;</i>';
     
    442427                </thead>
    443428                <tbody>';
    444                 foreach($keys as $key) {
     429                foreach($keys as $key){
    445430                    $keys_for_table[$key['id']] = array(
    446431                        'title' => $key['title'],
     
    458443                    $text = preg_replace( '@<(' . $ignore . ')[^>]*?\>.*?</\\1>@si','',$text);
    459444                    $text = preg_replace( '/\<\/?[^>]+>/U','',$text);
    460                     foreach($keys as $key) {
     445                    foreach($keys as $key){
    461446                        preg_match($key['search'],$text,$matches);
    462447                        $text = preg_replace($key['search'],'',$text,1);
    463                         if(isset($matches[0])) {
     448                        if(isset($matches[0])){
    464449                            $keys_for_table[$key['id']]['count']++;
    465450                        }
     
    467452                    unset($text);   
    468453                }
    469                 foreach( $keys_for_table as $key ) {
     454                foreach( $keys_for_table as $key ){
    470455                    $prim = '';
    471456                    $keylength = mb_strlen( $key['title'] );
    472                     foreach( $oldkeys as $oldkey ) {
    473                         if( mb_strtolower($key['title']) === mb_substr( $oldkey['title'], 0, $keylength ) ) {
     457                    foreach( $oldkeys as $oldkey ){
     458                        if( mb_strtolower($key['title']) === mb_substr( $oldkey['title'], 0, $keylength ) ){
    474459                            $prim .= 'Возможно дубликат (' . $oldkey['id'] . ')! ';
    475460                            break;
     
    507492}
    508493
    509 function mi13_glossary_page() { // Страница настроек плагина
     494function mi13_glossary_page(){ // Страница настроек плагина
    510495    $settings = get_option('mi13_glossary');
    511496    if( !isset($settings['pattern']) )  $settings['pattern'] = '[а-я\x{0301}]{0,4}';
     
    550535        <h2>Тесты</h2>
    551536        <div id="mi13_glossary_menu" style="background:#ffedc0;padding:8px">
    552 <?php
    553         $select = '';
    554         $keys = array();
    555         $args = array(
    556             'posts_per_page' => -1,
    557             'post_type' => 'mi13_glossary',
    558             'post_status' => 'publish'
    559         );
    560         $glos = get_posts($args);
    561         if($glos) {
    562             $select .= '<strong><label for="filter">Фильтр: </label></strong>';
    563             $select .= '<select id="mi13_glossary_filter">';
    564             $select .= '<option value="0">All</option>';
    565             foreach( $glos as $post ) {
    566                 $keys[] = $post->post_title;
    567             }
    568             usort($keys, function($a, $b) {
    569                 return strlen($a) < strlen($b) ? 1 : -1;
    570             });
    571             $i = 1;
    572             foreach( $keys as $key ) {
    573                 $select .= '<option value="'.$i.'">'.$key.'</option>';
    574                 $i++;
    575             }
    576             $select .= '</select>';
    577         }
    578         echo $select;
    579 ?>
    580          <p><button class="button" id="mi13_glossary_test_keys">Тест количества постов с ключом</button></p>
    581          <p><button class="button" id="mi13_glossary_test_posts">Тест ключей в постах</button></p>
     537        <?php
     538            $select = '';
     539            $keys = array();
     540            $args = array(
     541                'posts_per_page' => -1,
     542                'post_type' => 'mi13_glossary',
     543                'post_status' => 'publish'
     544            );
     545            $glos = get_posts($args);
     546            if($glos){
     547                $select .= '<strong><label for="filter">Фильтр: </label></strong>';
     548                $select .= '<select id="mi13_glossary_filter">';
     549                $select .= '<option value="0">All</option>';
     550                foreach( $glos as $post ){
     551                    $keys[] = $post->post_title;
     552                }
     553                usort($keys, function($a, $b){
     554                    return strlen($a) < strlen($b) ? 1 : -1;
     555                });
     556                $i = 1;
     557                foreach( $keys as $key ){
     558                    $select .= '<option value="'.$i.'">'.$key.'</option>';
     559                    $i++;
     560                }
     561                $select .= '</select>';
     562            }
     563            echo $select;
     564            ?>
     565            <p><button class="button" id="mi13_glossary_test_keys">Тест количества постов с ключом</button></p>
     566            <p><button class="button" id="mi13_glossary_test_posts">Тест ключей в постах</button></p>
    582567        </div>
    583568        <div id="mi13_glossary_table">
     
    592577    $id = null;
    593578    $val = null;
    594     if (isset($_POST['val'])) {
    595         $val = sanitize_textarea_field($_POST['val']);
    596     }
    597     if (isset($_POST['id'])) {
    598         $id = sanitize_textarea_field($_POST['id']);
    599     }
    600     if (isset($_POST['url'])) {
     579    $nonce = null;
     580    if(isset($_POST['nonce'])) $nonce = sanitize_textarea_field($_POST['nonce']);
     581    wp_verify_nonce( $nonce, 'mi13_glossary_admin' );
     582    if(isset($_POST['val'])) $val = sanitize_textarea_field($_POST['val']);
     583    if(isset($_POST['id'])) $id = sanitize_textarea_field($_POST['id']);
     584    if(isset($_POST['url'])){
    601585        $str = wp_parse_url($_POST['url'], PHP_URL_QUERY);
    602         if ($str) {
     586        if($str){
    603587            wp_parse_str($str, $array);
    604588            $page = (isset($array['n_page']) && intval($array['n_page'])>1) ? intval($array['n_page']) : 1; //fix bug for 1 page
     
    611595add_action( 'wp_ajax_mi13_glossary_pagination', 'mi13_glossary_pagination_ajax' );
    612596
    613 function mi13_glossary_list_for_page() {  // Код для вашей кастомной страницы глоссария
     597function mi13_glossary_list_for_page(){  // Код для вашей кастомной страницы глоссария
    614598    $args = array(
    615599        'posts_per_page' => -1,
     
    623607        $posts->the_post();
    624608        $string = get_the_content();
    625         if(substr($string,0,3) === '<h3') {
     609        if(substr($string,0,3) === '<h3'){
    626610            echo '<div class="mi13-glossary-article">';
    627611            the_content();
     
    633617}
    634618
    635 function mi13_glossary_delete_cash($id) { // Удаляем кэш глоссария при добавлении нового ключа или обновлении
     619function mi13_glossary_delete_cash($id){ // Удаляем кэш глоссария при добавлении нового ключа или обновлении
    636620    if(get_post_type($id)==='mi13_glossary') delete_transient('mi13_glossary');
    637621}
     
    639623add_action( 'save_post_mi13_glossary','mi13_glossary_delete_cash' );
    640624
    641 function mi13_glossary_publish_stop($id) { // Проверяем наличие заголовка в тексте; Публиковать может только админ
     625function mi13_glossary_publish_stop($id){ // Проверяем наличие заголовка в тексте; Публиковать может только админ
    642626    $stop = false;
    643627    $post = get_post( $id );
    644628    $publish_stop = get_option('mi13_glossary')['publish_stop'];
    645629    $string = $post->post_content;
    646     if(substr($string,0,3) !== '<h3') {
     630    if(substr($string,0,3) !== '<h3'){
    647631        $message = '<p>The &lt;h3&gt; heading is required at the beginning of the text!</p>';
    648632        $stop = true;
    649     } elseif($publish_stop && current_user_can('author')) {
     633    } elseif($publish_stop && current_user_can('author')){
    650634        $message = '<p>The administrator can publish posts (mi13_glossary) only!</p>';
    651635        $stop = true;
    652636    }
    653     if($stop) {
     637    if($stop){
    654638        $array = ['responce' => 200,'back_link' => true];
    655639        $post->post_status = 'pending';
  • mi13-glossary/trunk/readme.txt

    r3084998 r3135883  
    22Contributors: mi13
    33Tags: glossary, modal keys
    4 Tested up to: 6.5.3
    5 Stable tag: 3
     4Requires at least: 4.7
     5Tested up to: 6.6.1
     6Stable tag: 4
    67License: GPLv2 or later
    78License URI: https://www.gnu.org/licenses/gpl-2.0.html
    89
    9 Glossary plugin for your site (ru).
     10Glossary plugin for your site.
    1011
    1112== Description ==
     
    6364= 3 =
    6465* update plugin.
     66= 4 =
     67* update plugin.
Note: See TracChangeset for help on using the changeset viewer.