Magento 2 : Ajouter des link alternate sur les pages cms

Sur magento 2 ( comme sur magento 1 ) , les contenus et notamment les pages cms sont accessibles via plusieurs url avec ou sans slash à la fin.

Vous pouvez le constater sur la page de la politique de confidentialité qui est à la fois disponible sous les urls :
http://magento2-demo.nexcess.net/privacy-policy-cookie-restriction-mode et http://magento2-demo.nexcess.net/privacy-policy-cookie-restriction-mode/

Au niveau Seo c’est assez moyen c’est pourquoi il est utile de préciser à Google quelle est la version à indexer.
Ceci peut être réalisé via l’ajout d’une balise link rel= »canonical ».

Nous allons voir ensemble comment réaliser cela pour magento 2 via un module qui s’appellera Hhennes/Cms
Ce module ajoutera automatiquement une balise canonical sur les pages cms, il est possible de configurer en back office quelle sera l’url à utiliser ( avec ou sans le slash )

Ce module sera dépendant du module Magento_Cms.

Je vais juste détailler le fonctionnement global, vous trouverez le lien vers github en fin d’article pour le télécharger. (sans la partie création initiale )

La logique est relativement simple , nous allons rajouter un block spécifique sur les pages cms dans le container « head.additional …

Magento 2 : Ajouter des link alternate sur les pages cms Lire la suite »

Magento : Liste des ressources utilisables dans system.xml

Un petit article rapide d’aide mémoire pour la gestion des fichiers system.xml dans magento 1 .
Ces fichiers peuvent utiliser souvent les éléments suivants :

 Source Model

Il doivent être utilisés pour des champs de types « select » ou « multiselect »

Ex :

<demo_field_source translate="label">
    <label>Demo Field source model</label>
    <frontend_type>select</frontend_type>
    <!-- Définition de la source -->
    <source_model>adminhtml/system_config_source_yesno</source_model>
    <!-- Fin Définition de la source -->
    <sort_order>1</sort_order>
    <show_in_default>1</show_in_default>
    <show_in_website>1</show_in_website>
    <show_in_store>1</show_in_store>
</demo_field_source>

Les plus utiles à retenir sont les suivants :

  • adminhtml/system_config_source_yesno ( Oui / Non )
  • adminhtml/system_config_source_country (Liste des pays )
  • adminhtml/system_config_source_cms_page ( Liste des pages cms )
  • adminhtml/system_config_source_email_template ( Listes des emails transactionnels )

Liste complète :

adminhtml/system_config_source_yesno
adminhtml/system_config_source_admin_page
adminhtml/system_config_source_catalog_gridPerPage
adminhtml/system_config_source_catalog_listMode
adminhtml/system_config_source_catalog_listPerPage
adminhtml/system_config_source_catalog_listSort
adminhtml/system_config_source_catalog_search_type
adminhtml/system_config_source_catalog_timeFormat
adminhtml/system_config_source_checktype
adminhtml/system_config_source_cms_page
adminhtml/system_config_source_cms_wysiwyg_enabled
adminhtml/system_config_source_country
adminhtml/system_config_source_cron_frequency
adminhtml/system_config_source_currency
adminhtml/system_config_source_currency_service
adminhtml/system_config_source_customer_address_type
adminhtml/system_config_source_customer_forgotpassword
adminhtml/system_config_source_customer_group
adminhtml/system_config_source_design_robots
adminhtml/system_config_source_email_identity
adminhtml/system_config_source_email_method
adminhtml/system_config_source_email_smtpauth
adminhtml/system_config_source_email_template
adminhtml/system_config_source_enabledisable
adminhtml/system_config_source_frequency
adminhtml/system_config_source_locale
adminhtml/system_config_source_locale_currency_all
adminhtml/system_config_source_locale_timezone
adminhtml/system_config_source_locale_weekdaycodes
adminhtml/system_config_source_locale_weekdaycodes
adminhtml/system_config_source_locale_weekdays
adminhtml/system_config_source_nooptreq
adminhtml/system_config_source_notification_frequency
adminhtml/system_config_source_order_status_new
adminhtml/system_config_source_order_status_newprocessing
adminhtml/system_config_source_order_status_processing
adminhtml/system_config_source_payment_allspecificcountries
adminhtml/system_config_source_payment_cctype
adminhtml/system_config_source_price_scope
adminhtml/system_config_source_price_step
adminhtml/system_config_source_product_thumbnail
adminhtml/system_config_source_reports_scope
adminhtml/system_config_source_security_domainpolicy
adminhtml/system_config_source_shipping_allspecificcountries
adminhtml/system_config_source_shipping_flatrate
adminhtml/system_config_source_shipping_tablerate
adminhtml/system_config_source_shipping_taxclass
adminhtml/system_config_source_storage_media_database
adminhtml/system_config_source_storage_media_storage
adminhtml/system_config_source_store
adminhtml/system_config_source_tax_apply_on
adminhtml/system_config_source_tax_basedon
adminhtml/system_config_source_watermark_position
adminhtml/system_config_source_web_redirect
adminhtml/system_config_source_yesno
adminhtml/system_config_source_yesnocustom
backup/config_source_type
captcha/config_font
captcha/config_form_backend
captcha/config_form_frontend
captcha/config_mode
catalog/product_attribute_source_msrp_type
cataloginventory/source_backorders
checkout/config_source_cart_summary
configurableswatches/system_config_source_catalog_product_configattribute
configurableswatches/system_config_source_catalog_product_configattribute_select
customer/config_share
downloadable/system_config_source_contentdisposition
downloadable/system_config_source_orderitemstatus
googleanalytics/system_config_source_type
googlebase/source_accounttype
googlebase/source_country
log/adminhtml_system_config_source_loglevel
pagecache/system_config_source_controls
paygate/authorizenet_source_cctype
paygate/authorizenet_source_cctype
paygate/authorizenet_source_paymentAction
payment/source_invoice
paypal/config::getApiAuthenticationMethods
paypal/config::getExpressCheckoutBASignupOptions
paypal/config::getExpressCheckoutButtonFlavors
paypal/config::getExpressCheckoutSolutionTypes
paypal/config::getPayflowproCcTypesAsOptionArray
paypal/config::getWppCcTypesAsOptionArray
paypal/config::getWppPeCcTypesAsOptionArray
paypal/system_config_source_bmlPosition::getBmlPositionsCCP
paypal/system_config_source_bmlPosition::getBmlPositionsCheckout
paypal/system_config_source_bmlPosition::getBmlPositionsCPP
paypal/system_config_source_bmlPosition::getBmlPositionsHP
paypal/system_config_source_bmlSize::getBmlSizeCCPC
paypal/system_config_source_bmlSize::getBmlSizeCCPS
paypal/system_config_source_bmlSize::getBmlSizeCheckoutC
paypal/system_config_source_bmlSize::getBmlSizeCheckoutN
paypal/system_config_source_bmlSize::getBmlSizeCPPC
paypal/system_config_source_bmlSize::getBmlSizeCPPN
paypal/system_config_source_bmlSize::getBmlSizeHPH
paypal/system_config_source_bmlSize::getBmlSizeHPS
paypal/system_config_source_buyerCountry
paypal/system_config_source_fetchingSchedule
paypal/system_config_source_logo
paypal/system_config_source_merchantCountry
paypal/system_config_source_paymentActions
paypal/system_config_source_paymentActions_express
paypal/system_config_source_requireBillingAddress
paypal/system_config_source_urlMethod
paypal/system_config_source_yesnoShortcut
salesrule/system_config_source_coupon_format
shipping/source_handlingAction
shipping/source_handlingType
tax/system_config_source_algorithm
tax/system_config_source_apply
tax/system_config_source_priceType
tax/system_config_source_tax_country
tax/system_config_source_tax_display_type
tax/system_config_source_tax_region
usa/shipping_carrier_abstract_source_mode
usa/shipping_carrier_abstract_source_requesttype
usa/shipping_carrier_dhl_international_source_contenttype
usa/shipping_carrier_dhl_international_source_method_doc
usa/shipping_carrier_dhl_international_source_method_freedoc
usa/shipping_carrier_dhl_international_source_method_freenondoc
usa/shipping_carrier_dhl_international_source_method_nondoc
usa/shipping_carrier_dhl_international_source_method_size
usa/shipping_carrier_dhl_international_source_method_unitofmeasure
usa/shipping_carrier_dhl_source_dutypaymenttype
usa/shipping_carrier_dhl_source_freemethod
usa/shipping_carrier_dhl_source_method
usa/shipping_carrier_dhl_source_protection_rounding
usa/shipping_carrier_dhl_source_protection_value
usa/shipping_carrier_dhl_source_shipmenttype
usa/shipping_carrier_fedex_source_dropoff
usa/shipping_carrier_fedex_source_freemethod
usa/shipping_carrier_fedex_source_method
usa/shipping_carrier_fedex_source_packaging
usa/shipping_carrier_fedex_source_unitofmeasure
usa/shipping_carrier_ups_source_container
usa/shipping_carrier_ups_source_destType
usa/shipping_carrier_ups_source_freemethod
usa/shipping_carrier_ups_source_method
usa/shipping_carrier_ups_source_originShipment
usa/shipping_carrier_ups_source_pickup
usa/shipping_carrier_ups_source_type
usa/shipping_carrier_ups_source_unitofmeasure
usa/shipping_carrier_usps_source_container
usa/shipping_carrier_usps_source_freemethod
usa/shipping_carrier_usps_source_machinable
usa/shipping_carrier_usps_source_method
usa/shipping_carrier_usps_source_size
weee/config_source_display
weee/config_source_fpt_tax
wishlist/config_source_summary

 

 Frontend Model :

Le frontend model est un block de template magento  et  qui permets de gérer un affichage particulier pour l’élément de configuration.…

Magento : Liste des ressources utilisables dans system.xml Lire la suite »

Prestashop 1.7 : Ajouter une navigation à facettes dans les listings

La gestion des listings à complétement été réécrite sur Prestashop 1.7 , et la bonne nouvelle et qu’ils gèrent maintenant nativement la navigation à facettes ( Tout du moins la partie front 😉 )
Nous allons voir ensemble comment mettre en place une navigation à facette basique sur la page des nouveaux produits.

Sommaire :

  1. Fonctionnement général
  2. Affichage de facettes
  3. Tri et gestion des facettes

Cet article est plus dans une démarche d’explication du fonctionnement, que dans la réalisation d’un module purement fonctionnel, et la réalisation est assez chronophage, dans la majorité des cas il sera préférable de passer par un module qui fera cela.
( Le module de navigation à facette de Prestashop le permets uniquement sur les catégories )

Fonctionnement général

Le premier point essentiel à noter et qu’il n’est pas nécessaire de faire de surcharge, tout peut être géré via un module 🙂

Avant de voir ce qu’il faut coder, il est important de comprendre comment fonctionnent les pages de listing sur prestashop 1.7
Dans mon exemple on va utiliser le controller NewProductsController ( controllers/front/listing/NewProductsController.php

Prestashop 1.7 : Ajouter une navigation à facettes dans les listings Lire la suite »

Magento : Créer une commande via l’api

J’ai récemment eut à créer des commandes Magento via l’api et j’ai rencontré pas mal de difficultés, j’en profite pour condenser l’ensemble du processus dans cet article 🙂

Voici un script qui permettra de créer une commande Magento à partir de l’api Soap de Magento ( à la fois avec la version api V1 et api V2 )
Cet exemple a été réalisé sur un Magento 1.9.3.x de démonstration utilisant les samples data Magento.

N’hésitez pas à consulter la documentation officielle des api, si des points ne sont pas assez clairs  : https://devdocs.magento.com/guides/m1x/api/soap/introduction.html

Le script part des postulats suivants :

  • Passage de commande pour un client existant
  • Avec une adresse de facturation par défaut de renseignée
  • Les adresses de livraison et de facturation seront similaires.
  • Un accès à l’api avec tous les accès nécessaires existe sur le site magento de destination.

Les actions effectuées par le script sont les suivantes :

  1. Login à l’api
  2. Récupération de l’identifiant du  client à partir de son email
  3. Récupération de l’identifiant de l’adresse de facturation/livraison du client
  4. Création d’un panier
  5. Assignation du client au panier
  6. Assignation des adresses du client au panier
  7. Ajout de produits au panier
    1. Produit simple
    2. Produit configurable
    3. Produit groupé
    4. Produit Bundle
  8. Récupération des modes de livraison disponibles pour le panier
  9. Assignation du mode de livraison du panier
  10. Récupération des modes de paiement disponibles pour le panier
  11. Assignation du mode de paiement du panier
  12. Transformation panier en commande

 

Voir le script complet pour l’api V1
Voir le script complet pour l’api V2

Avant de vous montrer le script complet voici un focus sur les éléments à comprendre

Ajout des produits au panier

En fonction du type de produit à ajouter au panier , les informations à envoyer ne seront pas les mêmes.…

Magento : Créer une commande via l’api Lire la suite »

Prestashop : Ajouter un objet dans l’api

Nous allons voir comment ajouter un nouvel objet personnalisé dans l’api Prestashop via un module.
Cette méthodologie fonctionne sous Prestashop 1.7

L’objectif est d’ajouter de rendre un nouvel objet « Sample » qui pourra être manipulé via l’api.
Pour cela nous allons créer un module hhapisample

Ce module va ajouter une entité « sample » qui sera gérable via l’API.

Cette entité aura uniquement les paramètres suivants :

  • référence
  • nom ( multilingue )
  • description ( multilingue )

Voici le code de cette entité à placer dans le fichier classes/Sample.php du module.

/**
 * Classe d'exemple pour le webservice
 */
class Sample extends ObjectModel {
 
    /** @var string Référence du document */
    public $reference;
 
    /** @var string nom */
    public $name;
 
    /** @var string description */
    public $description;
 
    /**
     * Définition des paramètres de la classe
     */
    public static $definition = array(
        'table' => 'sample',
        'primary' => 'id_sample',
        'multilang' => true,
        'multilang_shop' => false,
        'fields' => array(
            'reference' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 255),
            'name' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'size' => 255 , 'lang' => true),
            'description' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml' , 'lang' => true),
        ),
    );
 
    /**
     * Mapping de la classe avec le webservice
     * 
     * @var type 
     */
    protected $webserviceParameters = [
        'objectsNodeName' => 'samples', //objectsNodeName doit être la valeur déclarée dans le hookAddWebserviceResources ( liste des entités )
        'objectNodeName' => 'sample', // Détail d'une entité
        'fields' => []
    ];
}

La définition du webservice est géré dans l’objet est configuré dans la variable $webserviceParameters
Pour rendre disponible cette entité, il faut greffer votre module sur le hook addWebserviceResources

/**
     * Ajout de la nouvelle entité au webservice
     * @param $params
     * @return array
     */
    public function hookAddWebserviceResources($params) {
        return [
            'samples' => [ //Nom du paramètre $webserviceParameters['objectsNodeName'] de la classe Objet
                'description' => 'Sample new entity for API',
                'class' => 'Sample'
            ],
        ];
    }

Une fois le module installé, vous pouvez-voir dans la liste des objets de l’api que l’entité sample est bien visible.…

Prestashop : Ajouter un objet dans l’api Lire la suite »

Prestashop 1.7 : Utilisation des formfields

La version 1.7 rajoute une nouvelle notion pour gérer les champs sur certains formulaires front ( Client et Adresse entre autre )
Ceux-ci sont géré via la classe FormField et leur affichage est géré dans le template themes/themeName/templates/_partials/form-fields.tpl

Les méthodes utiles pour gérer ces champs sont les suivantes :

  • setName: Défini le nom du champ
  • setType: Défini le type du champ ( text/checkbox .. ) voir liste ci-dessous
  • setRequired : Défini si le champ est obligatoire ou non
  • setLabel : Défini le label du champ
  • setValue : Défini la valeur du champ
  • setAvailableValues : Défini les valeurs disponibles pour le champ, pour les select entre autre
  • addAvailableValue : Ajout une valeur disponible pour le champ
  • setMaxLength: Longueur maximum du champ
  • setConstraint : Ajoute une contrainte de validation au champ , les méthodes appelables sont celles de la classe Validation ( ex isEmail )

Pour l’exemple j’ai ajouté des nouveaux champs au formulaire de création de compte client via le hook hookAdditionalCustomerFormFields

Voici l’ensemble des  types de champs possibles :

return [
    //Champ texte standard
    (new FormField)
        ->setName('professionnal_id')
        ->setType('text')
        ->setRequired(true) //Décommenter pour rendre obligatoire
        ->setValue("TEST")
        ->setMaxLength("10")
        ->setLabel($this->l('Professionnal id')),
    //Champ File
    (new FormField)
        ->setName('justificatif_upload')
        ->setType('file')
        ->setLabel($this->l('document ID')),
    //Select
    (new FormField)
        ->setName('select_field')
        ->setType('select')
        ->setAvailableValues(array('key' => 'value 1', 'key2' => 'value2'))
        ->setLabel($this->l('Select type')),
    //countrySelect ( idem select mais rajoute une classe js js-country
    (new FormField)
        ->setName('country_field')
        ->setType('countrySelect')
        ->setAvailableValues(['key' => 'value 1', 'key2' => 'value2'])
        ->setLabel($this->l('Country Select')),
    //Checkbox
    (new FormField)
        ->setName('checkbox_field')
        ->setType('checkbox')
        ->setValue(1)
        ->setLabel($this->l('Checkbox type')),
    //radio-buttons
    (new FormField)
        ->setName('radio_field')
        ->setType('radio-buttons')
        ->setAvailableValues(array('key' => 'value 1', 'key2' => 'value2'))
        ->setLabel($this->l('Radio buttons type')),
    //date
    (new FormField)
        ->setName('date_field')
        ->setType('date')
        ->setLabel($this->l('Date')),
    //birthday
    (new FormField)
        ->setName('birthday_field')
        ->setType('birthday')
        ->setLabel($this->l('birthday')),
    //password
    (new FormField)
        ->setName('password_field')
        ->setType('password')
        ->setLabel($this->l('password')),
    //Champ email
    (new FormField)
        ->setName('email_field')
        ->setType('email')
        ->setLabel($this->l('email type')),
    //Champ tel
    (new FormField)
        ->setName('phone_field')
        ->setType('phone')
        ->setLabel($this->l('Phone type')),
    //Champ caché
    (new FormField)
        ->setName('hidden_field')
        ->setType('hidden')
        ->setValue('My hidden value')
];

Et leur visualisation :

Form fields prestashop

Prestashop 1.7 : Utilisation des formfields Lire la suite »

Prestashop 1.7 : Récupérer des informations personnalisées dans le panier

J’ai récemment fait face à un problème, car je souhaitais remontée un champ produit spécifique dans les informations du panier sur prestashop 1.7
( La modification décrite fonctionne également sur prestashop 1.6.1.x )

Après analyse, il s’avère que les informations disponibles sont remontées depuis la fonction getProducts de la classe Cart.

L’ensemble des champs remontés sont listé dans la requête sql de remontée des produits, et il n’est pas possible de récupérer nos nouveaux champs.

// Build query
$sql = new DbQuery();
 
// Build SELECT
$sql->select('cp.`id_product_attribute`, cp.`id_product`, cp.`quantity` AS cart_quantity, cp.id_shop, cp.`id_customization`, pl.`name`, p.`is_virtual`,
pl.`description_short`, pl.`available_now`, pl.`available_later`, product_shop.`id_category_default`, p.`id_supplier`,
p.`id_manufacturer`, m.`name` AS manufacturer_name, product_shop.`on_sale`, product_shop.`ecotax`, product_shop.`additional_shipping_cost`,
product_shop.`available_for_order`, product_shop.`show_price`, product_shop.`price`, product_shop.`active`, product_shop.`unity`, product_shop.`unit_price_ratio`,
stock.`quantity` AS quantity_available, p.`width`, p.`height`, p.`depth`, stock.`out_of_stock`, p.`weight`,
p.`available_date`, p.`date_add`, p.`date_upd`, IFNULL(stock.quantity, 0) as quantity, pl.`link_rewrite`, cl.`link_rewrite` AS category,
CONCAT(LPAD(cp.`id_product`, 10, 0), LPAD(IFNULL(cp.`id_product_attribute`, 0), 10, 0), IFNULL(cp.`id_address_delivery`, 0), IFNULL(cp.`id_customization`, 0)) AS unique_id, cp.id_address_delivery,
product_shop.advanced_stock_management, ps.product_supplier_reference supplier_reference');
 
// Build FROM
$sql->from('cart_product', 'cp');
 
...

Prestashop 1.7 : Récupérer des informations personnalisées dans le panier Lire la suite »

Prestashop : Modifier les listings dans l’administration

En complément d’un de mes précédents articles sur comment ajouter des nouveaux champs dans le listing des produits ( pour prestashop 1.7 ), nous allons voir comment effectuer cette action sur les autres controllers de l’administration.

Les listing des controllers concernés sont ceux qui utilisent encore l’ancienne infrastructure et les anciennes méthodes ( Clients, adresses, commandes , employés … )

Ce tutoriel fonctionne à partir de la version 1.6.0.2 de Prestashop et utilise le hook dynamique action.$this->controller_name.ListingFieldsModifier

Pour les versions inférieures il sera nécessaire de faire un override du controller concerné et d’ajouter les informations directement à la suite des paramètres de classe
$this->_select,
$this->_join,
$this->_where

Exécuté par via le code suivant dans la fonction getList de la classe AdminController

Hook::exec('action'.$this->controller_name.'ListingFieldsModifier', array(
'select' => &$this->_select,
'join' => &$this->_join,
'where' => &$this->_where,
'group_by' => &$this->_group,
'order_by' => &$this->_orderBy,
'order_way' => &$this->_orderWay,
'fields' => &$this->fields_list,
));

Prestashop : Modifier les listings dans l’administration Lire la suite »

Prestashop 1.7 : Dynamisez vos contenus wysiwyg

La problématique n’est pas nouvelle sur Prestashop, et c’est un point qui me frustre assez souvent et pour lequel j’avais déjà fait un module en 2014 ( cf. https://www.h-hennes.fr/blog/2014/01/18/prestashop-liens-dynamiques-vers-les-pages-cms-dans-lediteur-tinymce/ )
Ce module n’est malheureusement plus fonctionnel sur Prestashop 1.7.

Dans les éditeurs de contenus, il n’est pas possible  des mettre des liens ou des contenus dynamiques.
La bonne nouvelle cependant c’est que la version 1.7 de Prestashop apporte de nouveaux hooks qui vont permettre de modifier ces contenus avant l’affichage des éléments, et donc sans surcharge  🙂

Les éléments dont les contenus sont modifiables sont les suivants :

  • Pages cms
  • Catégories cms
  • Contenu produit
  • Contenu catégorie
  • Contenu Fabriquants
  • Contenu fournisseurs

Pour l’exemple on va partir sur le besoin suivant :

Je souhaite afficher un élément de configuration  dans l’ensemble des contenus noté ci-dessous.
Ce sera la configuration PS_SHOP_EMAIL , qui correspond à l’émail par défaut de la boutique.

Pour afficher cette variable il faudra intégrer dans les zones de contenus le code suivant :

{{configuration name=PS_SHOP_EMAIL}}

Le but du module sera donc de remplacer cet élément par sa valeur de configuration.…

Prestashop 1.7 : Dynamisez vos contenus wysiwyg Lire la suite »

Monitorez vos serveurs avec netdata

J’ai réinstallé mon serveur dédié sous ubuntu 16.04 récement, j’en ai profité donc pour chercher des nouveaux outils de monitoring, et je suis tombé sur « netdata » que j’avais déjà croisé il y’a pas mal de temps mais que je n’avais pas encore installé.

La solution est disponible sur github avec une documentation très complète à l’adresse suivante :
https://github.com/firehol/netdata/wiki/Installation

Il faut reconnaitre que cette solution est réussie graphiquement et très complète ( ça ressemble à un htop très très amélioré )
Nous allons voir comment installer et configurer basiquement cette solution.

Installer via la ligne de commande suivante :

bash <(curl -Ss https://my-netdata.io/kickstart.sh)

( Si curl n’est pas intallé apt-get install curl )

La durée du script d’installation dure environ 5 minutes :

Dans un premier temps il vérifie les prérequis et identifie les librairies manquantes sur votre serveur.
Et vous propose ensuite de les installer.

net data install 1

Vous pouvez ensuite paramétrer l’installation de la solution.…

Monitorez vos serveurs avec netdata Lire la suite »