Sass-convert memo

12 September 2016

Petit mémo pour la commande sass-convert qui permet de convertir un fichier CSS existant en fichier .scss (ou .sass, il suffit d’adapter le paramètre –to)

Convertir tout un répertoire de fichier css

sass-convert --from css --to scss --trace -R .

Convertir un fichier

sass-convert --from css --to scss --trace perso.css > perso.scss

Des rédacteurs restreints dans #SPIP

5 September 2016

Chacun sa rubrique !

Il est possible d’améliorer un peu la gestion des utilisateurs de SPIP. Dans cet exemple, on va :

  • Pouvoir restreindre un rédacteur à une ou plusieurs rubriques. C’est similaire au administrateur restreint.
  • Limiter la création d’article par les administrateurs/rédacteurs restreints à leur rubrique uniquement.

C’est assez pratique si vous n’avez pas envie que des articles soit poster n’importe ou sur le site.

On commence par permettre de lier aussi les rédacteurs à une rubrique, il faut placer ce code dans le fichier config/mes_options.php :

<?php
define('_STATUT_AUTEUR_RUBRIQUE', '0minirezo,1comite');

Ensuite on ajoute la vérification des accès restreints dans l’autorisation a créé des articles dans une rubrique.
Attention, c’est une surcharge de fonction, cela veut dire qu’elle va remplacer celle du core de SPIP.

Il faut mettre ce code dans un fichier de fonction (mes_fonctions.php par exemple).

<?php
/**
 * Autorisation de créer un article dans une rubrique $id
 *
 * Il faut pouvoir voir la rubrique et pouvoir créer un article…
 *
 * @param  string $faire Action demandée
 * @param  string $type Type d'objet sur lequel appliquer l'action
 * @param  int $id Identifiant de l'objet
 * @param  array $qui Description de l'auteur demandant l'autorisation
 * @param  array $opt Options de cette autorisation
 * @return bool          true s'il a le droit, false sinon
 **/
function autoriser_rubrique_creerarticledans($faire, $type, $id, $qui, $opt) {
    return
        $id
        and autoriser('voir', 'rubrique', $id)
        and autoriser('creer', 'article')

        // Vérifier l'accès restreint avant d'autoriser la publication
        and (
             !$qui['restreint'] or !$id
             or in_array($id, $qui['restreint'])
         );
}

Executer du code lorsqu’un utilisateur ce connecte sous SPIP

12 August 2016

J’avais besoin d’exécuter un peu de code lorsqu’un utilisateur ce connecte à SPIP. Il y a un moyen assez simple de le faire : dans le traiter du formulaire login.

La connexion de l’utilisateur ce fait dans la partie vérifier du formulaire CVT. Cela veut dire que la session a été créé.

<?php
function prefix_formulaire_traiter($flux) {

    if ($flux['args']['form'] == 'login') {
        // Coder ici
    }

    return $flux;
}

Bien entendu je préfèrerai avoir un pipeline post_login, ce serai plus simple et plus lisible dans le code.
Cela viendra peut-être avec SPIP 3.2 !


Executer du code lorsqu'un inscription est validée sous SPIP

6 August 2016

Dans SPIP, il n’y a pas de pipeline post_inscription. Difficile donc d’exécuter facilement du code lorsque l’inscription est validé par l’utilisateur. Cela va peut être changé avec SPIP 3.2.

En attendant, voici un bricolage avec le pipeline post_edition :

<?php
function prefix_post_edition($flux) {

    // Confirmation d'une inscription
    if ($flux['args']['table'] == 'spip_auteurs'
        and $flux['args']['statut_ancien'] == 'nouveau'
        and $flux['args']['action'] == 'instituer'
        and $flux['data']['statut'] == '6forum' ) { // Limité aux visiteurs
        $id_auteur = $flux['args']['id_objet'];
        // Faire des trucs ici.
    }

    return $flux;
}

Si vous n'avez plus de réseau sous linux après l'installation de Windows 10

30 July 2016

Si après la mise à niveau vers Windows 10, votre partition Linux n’arrive plus à se connecter au réseau et donc à Internet, ne tapez pas tout de suite sur votre BiduleBox !

Il est possible que cela soit la faute de Windows 10 !

J’ai une carte Intel I270-v et après avoir installé Windows 10, ma partition Linux Mint n’arrivait plus à se connecter au réseau.

Après des heures de recherche la solution est assez WTF : il faut désactiver le Wake on Lane (WoL) de Windows.

Rendez-vous dans les propriétés de votre carte, onglet Power management et décocher les cases relatives au WoL.


Windows 7 et mise à jour qui tournent folles

29 July 2016

Aujourd’hui c’est le dernier jour pour profiter de la mise à jour gratuite vers Windows 10.

Du coup, vous avez peut-être sortit votre vieux CD de Windows 7 pour réinstaller tout ça, après tout, quand c’est gratuit… C’est vous le produit.

Bref, vous pourriez être confronté, comme moi a l’impossibilité d’installer les mise à jour. Elles tournent en boucle et voilà, rien ne se passe. C’est génial non ? Bien entendu impossible de passez à Windows 10 sans faire quelques mises à jour de Windows 7.

Bref, voici une solution pour sortir de la mélasse :

  1. Téléchargez ce patch pour le 32bits ou ce patch pour le 64bits.
  2. Redémarrez Windows.
  3. Installez le patch.
  4. Redémarrez (encore…).
  5. Lancez les mises à jours.
  6. Prenez la direction de la cafetière la plus proche.

Voilà !


Préparer Ubuntu 16.04 ou Linux Mint 18 pour le développement web local

16 July 2016

On commence par installer les éléments du serveur web :

sudo apt install lamp-server^ php-gd php-sqlite3 php-curl php-xml php-xdebug php-mbstring

N’oubliez pas que le “^” à la fin de lamp-server n’est pas une faute de frappe !

Donner un nom au serveur web

Même si on a plus vraiment de message d’erreur, il est toujours bon de donner un nom au serveur. On fait comme pour Ubuntu 14.04 :

echo "ServerName localhost" | sudo tee /etc/apache2/conf-available/fqdn.conf
sudo a2enconf fqdn

Configurer xdebug

La configuration par défaut de xdebug est un peu légère. On modifie le fichier de configuration /etc/php/7.0/mods-available/xdebug.ini pour y ajouter ces lignes:

xdebug.max_nesting_level = 1000

; Pas de limite pour l'affichage xdebug
xdebug.var_display_max_depth = -1
xdebug.var_display_max_children = -1
xdebug.var_display_max_data = -1

Augmenter la valeur maximale d’upload

Par défaut, la valeur maximale d’upload est de 2Mo. C’est un poil handicapant de nos jours ou le moindre fichier dépasse facilement cette limite.

Il suffit d’éditer /etc/php/7.0/apache2/php.ini et de modifier les valeurs:

upload_max_filesize = 1024M
post_max_size = 1024M

Dans le même fichier, j’en profite pour afficher les erreurs, et vraiment toutes les erreurs PHP:

error_reporting = E_ALL
display_errors = On

Utiliser un autre répertoire que /var/www

Ensuite, je n’aime pas trop utiliser le dossier /var/www sur lequel pointe localhost par défaut. J’aime bien mettre les fichiers à l’abri dans mon répertoire /home:

Il faut éditer le fichier /etc/apache2/sites-available/000-default.conf A la fin de la déclaration du VirtualHost il faut ajouter ceci:

<Directory /home/phenix/Sites>
      Options Indexes FollowSymLinks
      AllowOverride all
      Require all granted
</Directory>

Il faut aussi remplacer la déclaration du DocumentRoot qui se trouve plus haut !

Maintenant, normalement, localhost pointe sur le dossier Sites de mon /home.

Changer les droits d’Apache

J’aime également bien que Apache tourne avec mes droits utilisateurs, cela évite de pas mal de problème d’écriture. Sur un serveur web c’est plutôt déconseillé, mais pour uniquement du local, je ne vois pas trop le mal.

Il faut éditer le fichier /etc/apache2/envvars et changer les ligne USER et GROUP. Cher moi cela donne ceci:

export APACHE_RUN_USER=phenix
export APACHE_RUN_GROUP=phenix

Activer l’URL_REWRITING

Par défaut, mod_rewrite n’est pas activé. On a déjà préparé le terrain avec AllowOverride all mais il faut encore activer le module:

sudo a2enmod rewrite

Ensuite on redémarre apache:

sudo service apache2 restart

Activer le module Expires

Un autre module bien utile: expires, pour les sites qui configure le cache du navigateur via Apache2

sudo a2enmod expires

On oublie pas de relancer apache pour prendre en compte le nouveau mod:

sudo service apache2 restart

Activer le module Headers

Pour les sites qui manipule les headers via apache2:

sudo a2enmod headers

On oublie pas de relancer apache pour prendre en compte le nouveau mod:

sudo service apache2 restart

[#wwwlocalhost<-]

Activer www.localhost

Parfois, on place des redirections via les fichiers .htaccess pour forcer l’utiliser les www devant le nom de domaine. Du coup, c’est pratique d’avoir un www.localhost fonctionnel. Il faut pour cela éditer le fichier /etc/hosts pour y ajouter :

127.0.0.1       www.localhost

MySQL

Je ne suis pas un grand fan des tables en InnoDB, depuis le jour ou elles ont toutes crashés lamentablement. Dans mon domaine, l’utilisation d’InnoDB n’est pas du tout indispensable. MyISAM pourrait même être meilleur, car il est plus rapide sur les opérations simples comme SELECT et INSERT.

Du coup, on change le moteur par défaut, en éditant le fichier /etc/mysql/mysql.conf.d/mysqld.cnf.

Dans la section [mysqld] on ajoute la ligne:

default-storage-engine=myisam

Truc en plus

Font Web

Toutes les fonts “web” ne sont pas installées, il faut les demander :

sudo apt-get install ttf-mscorefonts-installer

Charger PHP Mcrypt

Certaine application comme composer on besoin de Mcrypt, on va donc charger l’extension :

sudo apt install php-mcrypt
sudo phpenmod mcrypt

Bon travail !


Utiliser les forums de #SPIP sur d'autres types d'objets

10 March 2016

Parce que dans SPIP, il n’y a pas que des articles !

J’en ai marre de ne jamais me souvenir de cette procédure donc je vais la noter une bonne fois pour toutes :’-) .

Procédure :

Il faut déclarer quelques petites choses pour réussir à implémenter les forums de SPIP sur d’autres objets que les articles :

On commence par définir la fonction qui permet au formulaire de forum de trouver le titre de l’objet. Mettons que vous ayez un plugin qui définit un objet “annexe” sur lequel vous voulez utiliser les forums :

Dans le fichier de fonctions.php du plugin :

<?php
/**
 * Récupérer le titre des annexes pour les forums
 *
 * @param int $id_objet
 * @access public
 * @return string le titre de l'annexe
 */
function annexe_forum_extraire_titre($id_objet) {
    include_spip('inc/filtres');
    return generer_info_entite($id_objet, 'annexe', 'titre');
}

Ensuite, il faut définir le pipeline qui va permettre à la balise #FORMULAIRE_FORUM de trouver automatiquement l’objet du forum :

Dans le fichier pipelines.php :

<?php
function prefix_forum_objets_depuis_env($objets) {
    $objets['annexe'] = id_table_objet('annexe');
    return $objets;
}

On n’oublie pas d’ajouter le pipeline dans le paquet.xml :

<pipeline nom="forum_objets_depuis_env" inclure="prefix_pipelines.php" />

Dans le cas où les forums sont désactivés partout, on peut forcer le passage avec une fonction à déclarer dans le fichier inc/annexe_accepter_forums_publics.php :

<?php
function inc_annexe_accepter_forums_publics_dist($arg = null) {
    return 'abo'; // chaine de 3 caractere parmi 'non','pos','pri','abo'
}

Normalement à ce stade, la balise #FORMULAIRE_FORUM affiche le formulaire sur votre objet :).

Il ne faut pas oublier d’ajouter le critère * *id_annexe ?* * dans la boucle principale des forums et dans celle qui compte les messages. Sans quoi, SPIP va afficher tous les messages sans distinction.

Limitation :

Il y a cependant une configuration qui ne fonctionne pas correctement :

Si les forums sont désactivés sur les articles, il est impossible d’utiliser le mécanisme de réponse car #PARAMETRES_FORUM ne renvoie rien. Le problème vient de cette partie du code, qui est spécifique à la configuration des articles. Il est toujours possible de faire une surcharge brutale de la balise pour faire sauter cette limitation. Mais, du coup, le formulaire de configuration de l’admin n’a plus aucun sens.

Conclusion :

Les forums de SPIP ne sont pas encore complètement portables sur d’autres objets. Il y a visiblement eu du travail dans ce sens, mais ce n’est pas encore complet. Cependant, il suffit souvent d’activer les forums d’articles pour que tout se passe pour le mieux.


Contrôler les index des tableaux #SPIP

23 January 2016

SPIP possède un mécanisme de tableau dans le compilateur. C’est plutôt rudimentaire et mériterait certainement plus d’attention de la part des développeurs.

Dans beaucoup de cas, ils sont de précieux alliés mais rapidement limités. On les abandonne généralement rapidement au profit d’une fonction php. Soit parce que le code devient illisible, soit parce qu’ils ne sont pas assez souples.

Cependant, il y a quand même moyen de faire des choses assez puissantes sans prise de tête particulière. L’installation de spip_bonux est indispensable, cela permet d’accéder aux balises #SET_PUSH et #SET_MERGE qui rendent le code plus lisible.

Un système de news par secteur ET par mots-clés

J’ai besoin d’afficher tous les articles d’un secteur mélangés avec les articles qui possèdent un mot-clé défini. L’idée est de créer un module de “news” qui peut être enrichi par des articles qui ne seraient pas dans la rubrique “news”. L’idée est simple: remplir un tableau a l’aide de deux boucles SPIP et puis l’afficher avec une boucle DATA.

[(#REM) Initialiser le tableau ]
[(#SET{news, #ARRAY})]
<BOUCLE_article(ARTICLES){id_secteur=1}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ID_ARTICLE})]
</BOUCLE_article>

[(#REM) Recherche sur le mot-clé "news" ]
<BOUCLE_mot(ARTICLES){id_mot=42}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ID_ARTICLE})]
</BOUCLE_mot>

#GET{news} contient maintenant 4 id_articles: les deux derniers articles du secteur 1 et les deux derniers articles possédant le mot-clé 42.

Mais comme c’est un système de news, il faut tirer l'affichage par date. Or, les données du tableau sont tirées par ordre de boucles: d’abord, les informations de la boucle article, ensuite les informations de la boucle d’article_mot.

En réalité, ce dont j’ai besoin, c’est de la possibilité de trier mon tableau par date une fois qu’il a été généré par les boucles. Il faut donc que je sauvegarde la date de l’article dans mon tableau.

[(#REM) Initialiser le tableau ]
[(#SET{news, #ARRAY})]
<BOUCLE_article(ARTICLES){id_secteur=1}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ARRAY{id_article, #ID_ARTICLE, date, #DATE}})]
</BOUCLE_article>

[(#REM) Recherche sur le mot-clé "news" ]
<BOUCLE_mot(ARTICLES){id_mot=42}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ARRAY{id_article, #ID_ARTICLE, date, #DATE}})]
</BOUCLE_mot>

Voilà, donc maintenant, #GET{news} est un tableau qui contient 4 tableaux à deux clés: id_article et date.

Ensuite, via une petite astuce php, on va utiliser une des deux valeurs comme clé pour recomposer un tableau. Rien de complexe, tout est dans PHP:

[(#REM) Simplifier le tableau pour avoir id_article => date ]
[(#SET{news, #GET{news}|array_column{date, id_article}})]

Array_column est une fonction PHP 5.5. Mais spip_bonux l’apporte au version inférieur.

Ensuite, il ne reste plus qu’à faire une boucle data triée par valeur.

Voici le code complet:

[(#REM)
On va calculer les news:
- Soit cela se trouve dans le secteur des news
- Soit il y a le mot-clé news
]

[(#REM) Initialiser le tableau ]
[(#SET{news, #ARRAY})]
<BOUCLE_article(ARTICLES){id_secteur=1}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ARRAY{id_article, #ID_ARTICLE, date, #DATE}})]
</BOUCLE_article>

[(#REM) Recherche sur le mot-clé "news" ]
<BOUCLE_mot(ARTICLES){id_mot=42}{par date}{inverse}{lang}{0,2}>
  [(#SET_PUSH{news, #ARRAY{id_article, #ID_ARTICLE, date, #DATE}})]
</BOUCLE_mot>

[(#REM) Simplifier le tableau pour avoir id_article => date ]
[(#SET{news, #GET{news}|array_column{date, id_article}})]

<section class="section-news">
  <span class="label article-section"><:titre_news:></span>
  [(#REM) Affichage de articles du tableau ]
  <B_data_news>
    <ul class="news-list">
      <BOUCLE_data_news(DATA){source tableau, #GET{news}}{par valeur}{inverse}{0,2}>
        <li><INCLURE{fond=inclure/article_resume, id_article=#CLE} /></li>
      </BOUCLE_data_news>
    </ul>
  </B_data_news>
</section>

Générer automatiquement des touch-icons avec #SPIP

2 November 2015

Comme beaucoup de choses en développement web, les touch-icons1 c’est le bordel. Des formats différents en fonction des écrans, en fonction des résolutions d’écrans, des versions d’Android en vrac, et des développeurs perdus au milieu.

Bref, voici un petit squelette SPIP basé sur le travail Mathias Bynens.

L’idée est de placer un fichier apple-touch-icon.png dans le dossier squelettes/ de SPIP pour le décliner automatiquement dans toutes les autres versions. Le fichier ne sera pas agrandi donc il vaut mieux utiliser un fichier de minimum 192px.

Dans certains cas, la gestion automatique n’est pas idéale. On peut alors placer un fichier apple-touch-icon-VALEURxVALEUR.png pour remplacer celui générer automatiquement. Par exemple, si je veux remplacer le fichier 72px: apple-touch-icon-72x72.png

[(#REM)
  Favicon touch icon.
  Voir https://mathiasbynens.be/notes/touch-icons

  Ce fichier va générer les favicons pour un maximum de device.
  Il n'est pas inutile de passer ce squelette dans le filtre supprimer_ligne_vide (https://gist.github.com/phenix-factory/1dc0195bd655a654b9ef)
]

[(#REM)
  Tableau des tailles, en px
  Pour le moment, ils n'ont pas encore pondu autre chose que des icônes carrées. On espère que cela ne change pas.
]

[(#SET{taille_device,
[(#ARRAY{
192,192,
180,180,
152,152,
144,144,
120,120,
114,114,
76,76,
72,72,
60,60,
57,57})]})]

<BOUCLE_generateur_touch_icone(DATA){source tableau, #GET{taille_device}}>
  [(#REM)
    L'utilisateur fourni un fichier spécifique, on affiche directement
  ]

  [(#CHEMIN{apple-touch-icon-#VALEURx#VALEUR.png}|oui)
    [<link rel="[(#VALEUR|=={192}?{icon, apple-touch-icon-precomposed})]" sizes="#VALEURx#VALEUR" href="(#CHEMIN{apple-touch-icon-#VALEURx#VALEUR.png})">]
  ]

  [(#REM)
    Pas de fichier spécifique, on va créer l’icône si le fichier générique le permet.
  ]
  [(#CHEMIN{apple-touch-icon-#VALEURx#VALEUR.png}|non
    |et{#CHEMIN{apple-touch-icon.png}|hauteur|>={#VALEUR}|oui}
    |et{#CHEMIN{apple-touch-icon.png}|largeur|>={#VALEUR}|oui})
    [<link rel="[(#VALEUR|=={192}?{icon, apple-touch-icon-precomposed})]" sizes="#VALEURx#VALEUR" href="(#CHEMIN{apple-touch-icon.png}|image_reduire{#VALEUR,#VALEUR}|extraire_attribut{src})">]
    ]
</BOUCLE_generateur_touch_icone>

Un Gist est disponible pour ce code.


  1. Les icônes qui s’affichent quand un site web est ajouté dans la liste des app d’un smartphone par exemple ↩︎