- la traduction de l'arbre XML applatissait parfois certains éléments tableaux (notamment dans la clé 'associations'). Il faut pour analyser du coup se reporter à la présence de l'attribut 'nodeType'.
- parfois l'API retourne une erreur 500 sur certaines requêtes. Plutôt que de planter la page, on loge l'erreur et la requête qui l'a générée.
d'une ressource (tel que 'products'). Des champs «simples» uniquement là.
On utilise cette information dans l'iterateur pour que si un critère `{unchamp = 3}` est utilisé,
et que ce champ existe pour la ressource indiquée, alors l'appel du webservice filtrera automatiquement
le critère (`filter[unchamp]=3`), ce qui peut réduire le volume de données envoyées par le WS.
Le filtrage du coup se fait lors de la requête, et non après dans la boucle DATA pour ces champs là donc.
Du coup on utilise plus cache_me() mais cache_get(), et on évite
sur un recalcul que ça appelle 10 fois la même chose sur le WS (mais 1 seule fois quand même)
en mettant le résultat dans une statique locale.
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.