[plugin] kzSkinSelect ou choisir parmi un des thèmes installés

bazooka07bazooka07 Member
10 nov. modifié dans Plugins
Allez, un petit dernier pour finir l'année en beauté.

Suite au passage de bâon dans le staff de PluXml, il y a une grande campagne de test sur différents thèmes.
J'ai également quelques thèmes qui trainent au fond de mon disque.

Mais parmi tous les plugins qui trainent dans la nature, je n'ai pas trouvé chaussure à mon pied comme la Belle au Bois Dormant.
J'ai donc plongé les mains dans le cambouis pour avoir un outil qui va bien : le plugin kzSkinSelect.

Vous pouvez passer en revue tous les thèmes installés sur votre serveur de test sans avoir à utiliser de hook personnalisé. Cool !

Et cela marche chez Free
Télécharger la dernière version de ce magnifique plugin kzSkinSelect.
2021-11-10 : version 1.2.0 - intégration du sélecteur de thèmes dans la sidebar + download à a volée
2021-06-02 : diverses optimisations
2018-12-30 : Fix erreur dans .htaccess qui empêche l'affichage de l'icône du plugin
2018-12-29 : 1ère publication

Nouveauté : mon dépôt de plugins est également sur Github.

Réponses

  • Voilà encore de la belle ouvrage et je vais bien sûr tester cela.
    bazooka07 a écrit:
    Nouveauté : mon dépôt de plugins est également sur Github.

    Tu ne pourrait pas en profiter pour faire sur Github, comme Stéphane, un repository compatible qui me permettrait d'afficher automatiquement tous tes plugins (plus mises à jour) sur les pages de mon centre de ressources ?

    Des exemples ici.

    https://ressources.pluxopolis.net/

    En outre, cela me permettrait, comme quelques autres, d'intégrer tes œuvres dans l'administration de mon nouveau plugin jpbMultidepots qui, greffé sur les dépôts compatibles, propose téléchargement, installation, mises à jour et nouveautés des dépôts sélectionnés.
  • Cela est différent de ce que faisait Stéphane.

    Là c'est un site entièrement statique généré automatiquement sur mon PC avec mon gestionnaire de dépôt de plugins, thèmes, scripts et plus.

    Une fois généré sur mon PC, je fais un git push origin master pour faire la mise à jour du site en ligne.

    Tu as une doc sur les fichiers que tu as besoin pour ton plugin ou il faut que j'analyse ton code ( pas trop le temps pour l'instant ) ?

    As-tu remarqué que mon dépôt gère les thèmes ?
  • bazooka07 a écrit:
    As-tu remarqué que mon dépôt gère les thèmes ?

    Oui, bien sûr et je vais évaluer ça juste après avoir testé kzSkinSelect.

    En fait, je l'ai déjà récupéré en local et commencé à regarder la source mais il me vient une question qui me titille depuis longtemps. Il y a-il moyen de supprimer du dépôt les plugins/thèmes ?

    Sur ton précédent dépôt, cela était facile mais là, plusieurs fichiers sont impactés par la présence d'un plugin et je n'ai pas encore trouvé (quoi que pas encore cherché) comment retirer les items facilement.

    As-tu prévu quelque chose ?
    Suite au passage de bâon dans le staff de PluXml

    Heu...

    Qui c'est ce bâon ?
  • @ Bakooka07

    kzSkinSelect fonctionne parfaitement et un seul mot. Félicitation ! :)
    Tu as une doc sur les fichiers que tu as besoin pour ton plugin ou il faut que j'analyse ton code ( pas trop le temps pour l'instant ) ?

    J'ai envoyé ça en privé.

    J'attaque l'étude de ton nouveau dépôt.
  • Salut,

    Très bon plugin bazooka07, merci ! :)
  • bazooka07bazooka07 Member
    décembre 2018 modifié
    @jack31,

    3 principes sont appliqués pour gérer mon dépôt de plugins :
    - un seul fichier index.php à installer. Les dossiers et les fichiers images, CSS, .. sont créés automatiquement à la 1ère visite du site
    - on privilégie le protocole FTP pour administrer le dépôt. On évite ainsi les limites imposés par PHP (taille, vitesse). Et puis, c'est le protocole qui est fait pour.
    - les catalogues de plugins, thèmes sont générés automatiquement : nouveaux plugins, catalogue trop vieux ou absent

    les catalogues des plugins, thèmes, ... sont au format JSON et stockés dans le dossier workdir
    les plugins sont à déposer dans le dossier plugins qui est créé automatiquement à la 1ère visite du site ( on sait gérer un dépôt vide )
    pour les thèmes, c'est le dossier thèmes
    idem pour les scripts

    Si on supprime un plugin dans le dossier plugins, il suffit de supprimer le fichier workdir/plugins.json et le dossier workdir/assets/plugins. Ils seront recréés à la prochaine visite du dépôt.

    les images ( icon.*, preview.* ) sont extraites des archives zip et stockées dans les dossiers workdir/assets/plugins, workdir/assets/thèmes, ... Elles sont renommés avec le nom du plugin ou du thème

    index.php sait générer un site statique pour le stocker dans les pages Github. Certainement aussi chez Gitlab.

    Index.php gére la sécurité CORS pour Javascript. Donc les contraintes imposées par certains hébergeurs sur curl() ou file_get_contents peuvent être contournées en Javascript. Y compris avec api.github.com (V3)
  • Tu devance mes questions Bazooka. :)

    Toujours est-il que ça a l'air de fonctionner au poil et que jusqu’ici, il a l'air bien plus pratique que Repositorix.

    Reste à trouver le moyen d'afficher les plugins/thèmes/scripts dans les pages d'un site comme j'ai si bien réussi sur ressources.pluxopolis.net

    Une petite idée en passant.

    N'y aurait-il pas moyen d'afficher une alerte donnant des derniers plugins/thèmes/scripts intégrés dans le repo ?
  • bazooka07bazooka07 Member

    Bonjour,

    Petite mise à jour de ce plugin :

    • Optimisation du code
    • Bouton plus discret pour changer le style
    • Optimisation CSS

    Télécharger version 1.1.0

  • bazooka07bazooka07 Member
    3 juin modifié

    Petite mise à jour rapide :

    • certains thèmes n'utilisent pas le fichier site.css généré par PluXml. Donc obligé de styler le CSS en dur dans la page HTML
    • PluCss modifie l'aspect de la balise < summary>. Pas cool !

    Même lien de téléchargement que précédemment.

  • cpalocpalo Member

    Bonsoir,
    J'aurai souhaité afficher le select de thème en haut de la sidebar, et non pas fixé en bas.
    Est-ce qu'il faut que je modifie le plugin pour ajouter un hook, ou bien la possibilité existe-t-elle déjà?
    Cordialement

  • bazooka07bazooka07 Member

    Bonjour,
    Le plugin ajoute quelques règles CSS avec le hook "ThemeEndHead()".
    L'affichage se fait en position absolue (display: fixed). Pour déplacer le <select>, il suffit de modifier les valeurs de bottom et right. Eventuellement remplacer bottom ou right par top ou left. 1vh correspond à 1% de la hauteur de la fenêtre du navigateur. A remplacer éventuellement par une valeur en rem.

    L'affichage est indépendant de la sidebar. On a aucune garantie que chaque thème présente la même structure HTML
    Pour intégrer le <select> dans la sidebar, il faut modifier le hook "ThemeEndHead()" et utiliser les expressions régulières pour localiser la sidebar dans le flux html.

  • 9 nov. modifié

    @cpalo Bonjour,

    Tu peut éventuellement aussi modifier le plugin en faisant usage du hook indexEnd pour rechercher une balise et y inserer le formulaire

    exemple de modification désolé @bazooka07 si j'abime ton code
    raccourcie des modifs: ajout du hook themetag() à la volée et utilisation du hook indexEnd à la place de ThemeEndHead pour cibler toute balise aside (inspirer de hookMyTheme ).

    edit ajout d'une constante pour facilement modifier le tag ou string à accrocher pour y inserer le selecteur de théme

        <?php
    
        if (!defined('PLX_ROOT')) { exit; }
    
        /**
         * Permet à un visiteur de tester les différents styles avec un fichier infos.xml
         * présents dans le dossier de thèmes.
         *
         * La boîte de seélection de thèmes s'affiche en base et à droite du site.
         * Il n'y a aucun hook à ajouter aux thèmes. Activez simplement ce plugin pour vos essais.
         *
         * @author  J.P. Pourrez aka Bazooka07
         * hacked  09/11/2021 G.Cyrille  aka gc-nomade aka gcyrillus 
         * ajout du hook themetag() à la volée et utilisation du hook indexEnd à la place de ThemeEndHead
         * @update  2021-06-02
         * @update  2019-11-27
         * @date    2018-12-29
         * */
        class kzSkinSelect extends plxPlugin {
    
            const PREPEND_TO_TAG ='<aside>';// tag à accrocher - si tous les thèmes dispose d'un conteneur avec la chaine exact :  class="sidebar"> cela fonctionne aussi, 
                    // l'occurance(s) à trouver doit matcher exactement case et espaces.
            const TOKEN = __CLASS__ .'-Token';
            const FIELD_NAME = 'kz-token';
            const HOOKS = array(
                'plxMotorDemarrageBegin',
                'plxMotorDemarrageEnd',
                'ThemeTag',
                'IndexEnd',
                'ThemeEndBody',
            );
            const BEGIN_CODE = '<?php # ' . __CLASS__ . PHP_EOL;
            const END_CODE = PHP_EOL . '?>';
    
            private $__currentTheme = false;
    
            public function __construct($default_lang) {
                parent::__construct($default_lang);
                if(!defined('PLX_ADMIN')) {
                    foreach(self::HOOKS as $hook) {
                        $this->addHook($hook, $hook);
                    }
                }
            }
    
            private function _title_theme($filename) {
                if(function_exists('simplexml_load_file')) {
                    $infos = simplexml_load_file($filename);
                    return trim($infos->title->__toString());
                } else {
                    $parser = xml_parser_create(PLX_CHARSET);
                    xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
                    xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 0);
                    if(xml_parse_into_struct($parser, file_get_contents($filename), $values, $tags) == 1) {
                        xml_parser_free($parser);
                        if(!empty($tags['title'])) {
                            $k = $tags['title'][0];
                            return $values[$k]['value'];
                        }
                    }
                }
                return 'No-title';
            }
    
            /**
             * Traitement du hook plxMotorDemarrageBegin.
             * */
            public function getThemes($themesRoot, $currentTheme) {
                $themes = array();
                // On collecte les thèmes disponibles sur le site
                $pattern = PLX_ROOT . $themesRoot . '*/infos.xml';
                foreach(glob($pattern) as $filename) {
    
                    $root = preg_replace('@/infos.xml$@', '', $filename);
                    $folder = basename($root);
                    $caption = self::_title_theme($filename);
                    if(strtolower($caption) != strtolower($folder)) {
                        $caption .= " ($folder)";
                    }
                    // Tague les thèmes sans aperçu
                    $mark = ' *';
                    foreach(array('jpg', 'jpeg', 'png', 'gif') as $ext) {
                        if(file_exists($root."/preview.$ext")) {
                            $mark = '';
                            break;
                        }
                    }
                    $themes[$folder] = $caption.$mark;
                }
    
                if(count($themes) > 1) {
                    // Plusieurs thèmes sont disponibles
                    asort($themes);
                    $this->__themes = $themes;
                    $this->__currentTheme = $currentTheme;
    
                    $options = array(
                        'options' => array('regexp' => '@^[\da-z]{40}@i')
                    );
                    if(filter_has_var(INPUT_POST, __CLASS__)) {
                        if(isset($_SESSION[self::TOKEN])) {
                            if(
                                empty($_POST[self::FIELD_NAME]) or
                                filter_input(INPUT_POST, self::FIELD_NAME, FILTER_VALIDATE_REGEXP, $options) === false
                            ) {
                                return false;
                            }
    
                            $key = $_POST[self::FIELD_NAME];
                            if(isset($_SESSION[self::TOKEN][$key]) and intval($_SESSION[self::TOKEN][$key]) < time()) {
                                unset($_SESSION[self::TOKEN]);
                                die('Security error : invalid or expired token');
                            }
                            unset($_SESSION[self::TOKEN][$key]);
                            // On change de thème
                            $value = filter_input(INPUT_POST, __CLASS__, FILTER_SANITIZE_STRING);
                            if(!empty($value) and array_key_exists($value, $themes)) {
                                $this->__currentTheme = $value;
                                $_SESSION[__CLASS__] = $value;
                                return $value;
                            }
                        }
                    } elseif(!empty($_SESSION[__CLASS__])) {
                        // On récupère le précèdent choix du visiteur et on l'active s'il existe.
                        $value = $_SESSION[__CLASS__];
                        if(array_key_exists($value, $themes)) {
                            $this->__currentTheme = $value;
                            return $value;
                        }
                    }
                }
    
                return false;
            }
    
            /* ============== Hooks ========================= */
    
            /**
             * Analyse de la situation.
             * valide le choix d'un thème par le visiteur.
             * En mode article, interdit les commentaires dans ce cas précis.
             *
             * Dans le cas contraire, reprend le choix précèdent du visiteur stocké dans une variable de session.
             * */
            public function plxMotorDemarrageBegin() {
                echo self::BEGIN_CODE;
        ?>
        $value = $this->plxPlugins->aPlugins['<?= __CLASS__ ?>']->getThemes(
            $this->aConf['racine_themes'],
            $this->style
        );
    
        if(!empty($value)) {
            $this->style = $value;
        }
    
        if($this->mode == 'article' and filter_has_var(INPUT_POST, '<?= __CLASS__ ?>')) {
            $<?= __CLASS__ ?>Coms = $this->aConf['allow_com'];
            $this->aConf['allow_com'] = false;
        }
    
        # PluXml doit poursuivre son traitement
        return false;
        <?php
                echo self::END_CODE;
            }
    
            /**
             * En mode article, restitue l'autorisation des commentaires.
             * */
            public function plxMotorDemarrageEnd() {
                if(empty($this->__currentTheme)) {
                    # Un seul thème disponible. Retour au fonctionnment standard
                    return;
                }
    
                echo self::BEGIN_CODE;
        ?>
        if(isset($<?= __CLASS__ ?>Coms)) {
            # On restaure l'autorisation des commentaires
            $this->aConf['allow_com'] = $<?= __CLASS__ ?>Coms;
        }
        <?php
                echo self::END_CODE;
            }
    
            /**
             * Quelques rèegle de style CSS
             * */
            public function ThemeEndHead() {
                if($this->__currentTheme === false) { return; }
        ?>
                <style type="text/css">
                    #kzSkinSelect-wrapper {
                        display: block;
                        position: fixed;
                        bottom: 1vh;
                        right: 2rem;
                        padding: 0.25rem;
                        background-color: #bfb658;
                        color: #000;
                        font-family: 'Noto Sans', Arial, Sans-Serif;
                        font-size: 12pt;
                        border-radius: 0.3rem;
                        -webkit-appearance: initial;
                        z-index: 9999;
                    }
    
                    #kzSkinSelect-wrapper summary {
                        display: list-item;
                    }
    
                    #kzSkinSelect-wrapper select {
                        margin: 0;
                        background-color: #fff;
                    }
                </style>
        <?php       
            }
    
    
    
            public function IndexEnd() {
                    $prependToTag = self::PREPEND_TO_TAG;   
                    echo '<?php ';?>
                        ob_start();
                        eval($plxMotor->plxPlugins->callHook('ThemeTag')); # Hook Plugins  
                        $output = str_replace('<?php echo $prependToTag; ?>', ob_get_clean(), $output);
                 ?>
                  <?php 
                }
            public function ThemeTag() {
    
                echo self::PREPEND_TO_TAG ;
                if($this->__currentTheme === false) { return; }
    
                $token = sha1(mt_rand(0, 1000000));
                $_SESSION[self::TOKEN][$token] = time() + 3600; // Date limite pour le token
            ?>
                    <details id="<?= __CLASS__ ?>-wrapper">
                        <summary>Style</summary>
                        <form method="post">
                            <input name="<?= self::FIELD_NAME; ?>" value="<?= $token; ?>" type="hidden" />
        <?php plxUtils::printSelect(__CLASS__, $this->__themes, $this->__currentTheme); ?>
                        </form>
                    </details>
                    <script type="text/javascript">
                        (function() {
                            'use strict';
                            const details = document.getElementById('<?= __CLASS__ ?>-wrapper');
                            const select = document.getElementById('id_<?= __CLASS__ ?>');
    
                            if(details == null || select == null) { return; }
    
                            select.autofocus = true;
                            select.onchange = function(event) {
                                event.preventDefault();
                                if(select.value.trim() != '') {
                                    select.form.submit();
                                }
                            }
                        })();
                    </script>
    
                <?php
            }
        }
    
    

    HS La mise en forme générale sur le forum est vraiment galère ... on en arrive a ne plus savoir s'il faut utiliser du html , du markdown ou un mixe des deux , ni lesquels fonctionnent ensemble selon le moment ou l'on post , j'ai même des post qui ne prennent que le json au moment de la réedition , ça rend un peu schizo, non ?

    Remise en ligne et test de mon vieux site re7net.com . le design et moi on ne sait ... s'est jamais reconnu en fait! mais je fait des efforts.

  • cpalocpalo Member

    Je voyais plutôt quelque chose comme :-1:

    <?php eval($plxShow->callHook('plxShowSkinSelect')) ?>
    

    ou dans une page statique

    <?php echo plxUtils::strCheck('<?php
    global $plxShow;
    eval($plxShow->callHook("plxShowSkinSelect"));
    ?>
    ');
    ?>
    
  • 10 nov. modifié

    Ce que tu décris est la façon dont est codé pour être utiliser le plugin https://github.com/Pluxopolis/plxMySkinSelect ou le plugin https://github.com/Pluxopolis/plxMySearch , ce n'est pas le cas du plugin de bazooka qui intègre le formulaire à partir du hook ThemeEndBody() , donc invariablement juste avant la fermeture de body , sauf a utiliser le hook IndexEnd et modifier et redévelopper le plugin en conséquences. Le plugin de bazooka est développer pour ceux qui ne veulent ou ne savent pas mettre les mains et la souris dans le code ;)

    La modification que j'ai faites dans le post précédent , n'a changer que le hook utilisé et mis une constante aisément modifiable en debut de script pour t'aider à trouver la chaine la plus pertinente (une balise, une chaine de mots,..) dans tes thèmes pour injecter le sélecteur de thèmes de bazooka07. Je n'ai rien redévelopper, juste tordu un peu avec 2 coups de marteau. peut-etre devrait tu simplement utilise le plugin plxMySkinSelect .. en le reinjectant manuellement dans chacun des thème :(

    cdt

    Remise en ligne et test de mon vieux site re7net.com . le design et moi on ne sait ... s'est jamais reconnu en fait! mais je fait des efforts.

  • cpalocpalo Member
    10 nov. modifié

    Si j'ai cela en début dans ma sidebar, comment dois-je modifier ton code pour que cela fonctionne.

    <div class="sidebar">
        <div class="block-skin-select">
        Affichage du selecteur de thème
    

    Dans ton code, petite erreur car tu as laissé le css initial ce qui fait apparaitre le selecteur fixé en bas comme dans le plugin original

  • cpalocpalo Member
    10 nov. modifié

    L'interêt de kzSkinSelect par rapport à plxMySkinSelect c'est justement le fait qu'on n'ait pas besoin de modifier les thèmes qu'on veut tester.
    Mais effectivement si on veut qu'il soit toujours visible quelque soit le thème, il faut que son affichage ne soit pas lié à un thème.

  • 10 nov. modifié

    pour placer le selecteur dans <div class="block-skin-select"> il te suffit juste de recopier ce morceau dans la constante ou il y a pour le moment <aside>.

    Pour le CSS, il se trouve injecter dans la fonction public function ThemeEndHead() {} .Tu peut le réecrire ou mettre un lien direct vers une feuille de style à la palce du html/css injecté.

    Tu peut aussi , le vider, voir retirer ce hook du plugin et injecter tes styles dans la config CSS du plugin coté site si tu utilises une version récente de PluXml.
    Cdt

    Remise en ligne et test de mon vieux site re7net.com . le design et moi on ne sait ... s'est jamais reconnu en fait! mais je fait des efforts.

  • Effectivement il faut utiliser le hook ThemeEndBody pour ne pas avoir à modifier tous les thèmes.
    La difficulté est de reconnaitre la sidebar principale dans le contenu généré par PluXml ($output dans index.php)
    Comme il n'y a jamais de recommendation officielle, c'est un peu la foire aux aveugles. Donc on recherche une <aside> ou <div> qui répond à une des conditions suivantes:

    • un id égal à aside ou sidebar, éventuellement avec le préfixe "site-" ou "main-"
    • une class qui contient aside ou sidebar, éventuellement avec le préfixe "site-" ou "main-"

    En cas d'échec, on affiche le sélecteur comme avant, en bas et à droite de la fenêtre. Pour rappel un article peut être affiché sans sidebar.

    En bonus, on peut créer à la volée l'archive zip du thème affiché et la télécharger.
    Télécharger la version 1.2.0 du plugin
    Voir la démo

  • cpalocpalo Member

    Bonsoir,
    @bazooka07
    Merci pour cette version 1.2 du plugin.
    Je viens de l'installer et la tester rapidement.
    A-priori pas de bug et ça me plait bien.
    @gcyrillus-nomade
    Merci à toi aussi pour ton aide et de cet échange.
    Cela m'a permis de mettre un peu plus les mains dans le "cambouis" et d'apprendre.
    Cordialement

Connectez-vous ou Inscrivez-vous pour répondre.