Skip to content
  • marcimat@rezo.net's avatar
    Grandes modifications du plugin d'API Prestashop notamment pour avoir des... · f7c75a35
    marcimat@rezo.net a rédigé
    Grandes modifications du plugin d'API Prestashop notamment pour avoir des boucles beaucoup plus simples à écrire.
    
    Un itérateur spécifique est créé qui étend l'itérateur DATA et va interroger le Webservice.
    On peut ainsi écrire `<BOUCLE_produits(PRESTASHOP:PRODUCTS){id IN 3,4,5}>#NAME</BOUCLE_produuits>`
    N'importe quel élément de l'API de webservice peut être utilisée de la sorte. Par exemple `(PRESTASHOP:CATEGORIES)`
    
    Quelques détails techniques
    ==========================
    
    Langues des boutiques
    --------------------
    
    Notre utilisation est basée sur un Prestashop en multi-boutique (chaque boutique a une URL sur un domaine dans une certaine langue (domaine.fr/boutique/ et domaine.en/shop/ par exemple).
    Dans la configuration, on renseigne une des URLs avec la clé d'API (avec des droits de lectures suffisants). À partir de là, le plugin saura retrouver / calculer les liens
    corrects pour chaque produit pour une langue voulue (la langue en cours du squelette ou du PHP par défaut) et intérrogera l'API en utilisant le bon domaine en fonction de la langue.
    
    L'ennuyant c'est que les produits qui sont traduits en différentes langues et partagés donc entre les boutiques renvoient via l'API de Webservice une sorte de XML équivalent à nos 
    balises multis, MAIS au lieu d'avoir un code de langue, on a un identifiant numérique de langue. Il faut appeler le webservice sur api/languages pour avoir la description de cet identifiant.
    Mais api/languages ne renvoie que l'identifiant de la langue active de la boutique, ce qui fait que si ce «multi» retourne un texte dans la langue 3, possiblement je ne sais pas à quoi correspond ce 3.
    Pour parer à ce problème (en multi-boutique / langue donc), on calcule pour chaque boutique les langues qu'il contient et on crée et sauvegarde un tableau de relation (identifiant de langue, 
    url de la boutique, code de langue). C'est ce que font les fonctions prestashop_ws_list_shops_by_lang() prestashop_ws_list_shops() et prestashop_ws_list_languages().
    
    Afin d'éviter de requêter abusivement le Webservice, on met en cache ces infos, en utilisant Memoization.
    
    
    Interroger le webservice en PHP
    -------------------------------
    
    L'itérateur qui sert au boucles utilise en interne un appel à la classe \SPIP\Prestashop\Webservice, qui surcharge la librairie PSWebServiceLibrary que propose 
    Prestashop par défaut.
    
    Il y a plusieurs moyens pour utiliser la classe, le plus simple étant :
    ```
    $wsps = \SPIP\Prestashop\Webservice::getInstanceByLang(); // langue automatique
    // ou $wsps = \SPIP\Prestashop\Webservice::getInstanceByLang('fr'); // langue fr (si trouvée)
    
    $xml = $wsps->get(['resource' => 'products']);
    // éventuellement avoir un arbre nettoyé / simplifié (c'est ce que fait l'itérateur)
    $arbre = prestashop_ws_nettoyer_reception($xml, 'products', prestashop_ws_list_languages());
    ```
    
    
    Balises Spécifiques
    -------------------
    
    Dans les Squelettes, chaque nom de balise du XML devient une balise utilisable dans la boucle.
    Par exemple l'appel à l'API 'api/products/1?display=full' (display=full est utilisé par défaut sur les boucles)
    retourne entre autres une balise XML `<date_add> ... </date_add>`. 
    Du coup, une boucle `(PRESTASHOP:PRODUCTS)` pourra utiliser `#DATE_ADD` qui retourne le texte de cette balise.
    Les balises XML qui contiennent d'autres balises, elles retourneront un tableau des ces balises.
    À l'exception de la balise `<languages>` qui est l'équivalent de notre balise `<multi>` qui est applatie automatiquement
    et transformée en balise `<multi>` comme SPIP en a l'habitude. Ainsi `[(#NAME|typo)]` affiche le nom du produit
    dans la langue en cours (pour peu que le produit soit traduit :)).
    
    Enfin les balises ayant un attribut `xlink:href` ajoutent automatiquement un champ `{nom de la balise}_url` qui permet
    d'obtenir le lien. Si la balise est `<truc xlink:href="toto">...</truc>` alors on aura accès à `#TRUC` et `#TRUC_URL` 
    
    Deux autres balises spécifiques existent :
    - `#URL_PRESTASHOP` retourne l'URL du prestashop dans la langue en cours
    - `#URL_PRESTASHOP{product,3}` retourne l'URL du produit, dans la langue en cours
    - `#URL_PRESTASHOP{product,4,en}` pareil en langue en.
    
    - `#URL_IMAGE_PRESTASHOP{product,3}` retourne l'url de l'image principale du produit dans la langue en cours
    - `#URL_IMAGE_PRESTASHOP{product,3,en}` pareil en anglais
    
    Pour ces 2 balises, c'est un peu compliqué car le webservice ne retourne pas directement ces URLs.
    Pour les produits, on "ping" l'URL du controlleur de prestashop, qui va rediriger sur l'URL propre. On capture l'URL de redirection (et on cache dans memoization).
    Pour les images, on ne sait (actuellement) que prédire où l'image est rangée dans Prestashop (img/c/{id}.jpg pour les catégories, img/p/{i}/{d}/{id}.jpg pour les produits).
    
    Autant pour les urls c'est passable, autant pour les images, c'est un peu imprevisible (le produit pourrait ne pas avoir d'image par exemple). Mais le webservice
    retourne une URL d'image qui nécessite une clé d'API pour fonctionner, ce qui n'est pas du tout pratique, car on ne peut par exemple pas l'utiliser pour appliquer `|image_reduire` 
    
    Il y a également les fonctions PHP correspondantes à ces balises :
    - prestashop_image($objet, $id)
    - calculer_url_prestashop()
    
    
    Mini démonstration
    ------------------
    
    Après avoir configuré l'URL et la clé sur exec=configurer_prestashop_api,
    une liste de 5 produits est affichée sur exec=demo_prestashop_api.
    Note : Le tout premier affichage peut être long.
    
    
    
    f7c75a35