{"id":231121,"date":"2022-12-15T11:05:00","date_gmt":"2022-12-15T08:05:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=231121"},"modified":"2022-12-17T15:09:27","modified_gmt":"2022-12-17T12:09:27","slug":"widgets-wordpress-refactorisation-partie-4","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/fr\/widgets-wordpress-refactorisation-partie-4\/","title":{"rendered":"Widgets WordPress : refactorisation, partie 4"},"content":{"rendered":"\n<p>Nous avons impl\u00e9ment\u00e9 un nombre important de modifications dans le WordPress Widget Boilerplate. Si vous n&rsquo;avez pas suivi, je vous recommande de commencer au d\u00e9but de la s\u00e9rie et de rattraper votre retard.<\/p>\n<p>Si, toutefois, vous avez suivi et que vous utilisez \u00e9galement certains des outils de qualit\u00e9 du code qui examinent l&rsquo;\u00e9tat du projet, vous remarquerez une poign\u00e9e d&rsquo;erreurs dans la console.<\/p>\n<p>Normalement, c&rsquo;est le point o\u00f9 je recommande de pr\u00eater attention \u00e0 ce qu&rsquo;il partage, puis de corriger tout ce qu&rsquo;il rapporte, mais nous n&rsquo;en sommes pas encore l\u00e0.<\/p>\n<p>Par exemple, certaines des erreurs que nos outils affichent actuellement sont bas\u00e9es sur le fait que nous avons des variables inutilis\u00e9es. Bien s\u00fbr, c&rsquo;est le cas, car nous n&rsquo;avons pas commenc\u00e9 \u00e0 cr\u00e9er un widget.<\/p>\n<p>Mais il reste encore quelques classes concr\u00e8tes que nous devons impl\u00e9menter.<\/p>\n<h2>Le passe-partout du widget WordPress\u00a0: refactorisation, partie 4<\/h2>\n<p>L&rsquo;un des probl\u00e8mes qui existent toujours dans le code tel qu&rsquo;il est actuellement est que le constructeur du widget enregistre des fonctions et ce n&rsquo;est pas une bonne chose.<\/p>\n<p>Le but d&rsquo;un constructeur est de d\u00e9finir les valeurs des propri\u00e9t\u00e9s de la classe, et non d&rsquo;impl\u00e9menter un type de logique. Ceci pour plusieurs raisons\u00a0:<\/p>\n<ul>\n<li>il cr\u00e9e un fort couplage ou des d\u00e9pendances entre les classes du projet chaque fois qu&rsquo;une classe donn\u00e9e est instanci\u00e9e,<\/li>\n<li>il introduit une logique m\u00e9tier dans une fonction qui n&rsquo;est pas destin\u00e9e \u00e0 contenir ladite fonctionnalit\u00e9,<\/li>\n<li>il est difficile de tester une classe de mani\u00e8re isol\u00e9e.<\/li>\n<\/ul>\n<p>La fa\u00e7on de g\u00e9rer cela est double :<\/p>\n<ol>\n<li>ajouter un registre que nous pouvons utiliser pour enregistrer des classes dans l&rsquo;application (et les faire circuler avec le moins de d\u00e9pendances possible, ce que j&rsquo;expliquerai plus tard),<\/li>\n<li>cr\u00e9er des abonn\u00e9s capables de g\u00e9rer la logique m\u00e9tier sur une base sp\u00e9cifique au hook.<\/li>\n<\/ol>\n<p>Au cours des trois prochains articles\u00a0:<\/p>\n<ol>\n<li>nous allons envisager de cr\u00e9er un registre,<\/li>\n<li>comment on peut l&rsquo;introduire dans le fichier bootstrap,<\/li>\n<li>puis envisagez de cr\u00e9er des abonn\u00e9s pour chacune de nos fonctions (ce qui ne devrait pas \u00eatre trop difficile compte tenu de ce que nous avons fait dans le post pr\u00e9c\u00e9dent et de ce que nous faisons dans ce post).<\/li>\n<\/ol>\n<h3>Cr\u00e9er le registre<\/h3>\n<p>Avant d&rsquo;\u00e9crire le code du registre, il est important de noter son objectif principal. En termes simples, la classe est cens\u00e9e contenir une r\u00e9f\u00e9rence \u00e0 toute classe qui est, ahem, enregistr\u00e9e avec elle.<\/p>\n<p>Cela se fait en passant une r\u00e9f\u00e9rence \u00e0 un objet donn\u00e9 \u00e0 une fonction et en la liant \u00e9galement \u00e0 une cl\u00e9 afin que nous puissions facilement la r\u00e9cup\u00e9rer plus tard.<\/p>\n<h4>Consid\u00e9rations initiales<\/h4>\n<p>Mais il y a certaines choses \u00e0 consid\u00e9rer. Par exemple:<\/p>\n<p>si un objet existe d\u00e9j\u00e0 dans le registre pour une cl\u00e9 donn\u00e9e, alors nous devons lever une exception &#8211; si un utilisateur essaie de r\u00e9cup\u00e9rer un objet dans le registre avec une cl\u00e9 donn\u00e9e, alors il devrait lever une exception<\/p>\n<p>Bien s\u00fbr, il ne doit pas n\u00e9cessairement lever d&rsquo;exceptions. Au lieu de cela, il peut \u00e9galement afficher des messages d&rsquo;erreur, renvoyer des valeurs nulles ou vides, ou tout ce que vous choisissez.<\/p>\n<p>Deuxi\u00e8mement, le registre doit \u00eatre en mesure de renvoyer une liste de tous les abonn\u00e9s qui y sont contenus afin qu&rsquo;ils puissent \u00eatre enregistr\u00e9s avec WordPress (c&rsquo;est ce que nous allons voir dans le prochain article).<\/p>\n<p>Pour ce faire, cependant, nous devons nous assurer qu&rsquo;il prend en charge tous les abonn\u00e9s et c&rsquo;est l\u00e0 que la notion de AbstractSubscriber du <a href=\"https:\/\/wordpress.mediadoma.com\/fr\/widgets-wordpress-refactorisation-partie-3\/\" title=\"post pr\u00e9c\u00e9dent\">post pr\u00e9c\u00e9dent<\/a> entre en jeu. Autrement dit, tant qu&rsquo;une classe est une classe enfant de cette classe, tout va bien.<\/p>\n<h4>Cr\u00e9ation du registre<\/h4>\n<p>Cela dit, planifions ce qui suit\u00a0:<\/p>\n<ul>\n<li>Nous allons cr\u00e9er une classe Registry et la placer dans un espace de noms Utilities (et donc un r\u00e9pertoire) si elle n&rsquo;existe pas d\u00e9j\u00e0 dans votre travail.<\/li>\n<li>Nous demanderons au registre de conserver une r\u00e9f\u00e9rence \u00e0 tous ses objets dans un tableau associatif.<\/li>\n<li>Nous avons besoin de m\u00e9thodes pour <strong>ajouter<\/strong> et <strong>obtenir<\/strong> un abonn\u00e9 individuel, puis une pour r\u00e9cup\u00e9rer la liste des abonn\u00e9s entiers.<\/li>\n<\/ul>\n<p>Le stub de la classe ressemblera <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-00-registry-stub-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">\u00e0 ceci\u00a0:<\/a><\/p>\n<pre><code>&lt;?php\n\nclass Registry extends AbstractSubscriber\n{\n    public function __construct()\n    {\n    }\n\n    public function add($id, $obj)\n    {\n    }\n\n    public function get($id)\n    {\n    }\n\n    public function getRegisteredSubscribers()\n    {\n    }\n}\n<\/code><\/pre>\n<p>Ensuite, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-01-registry-constructor-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">nous pouvons d\u00e9finir la propri\u00e9t\u00e9 de base<\/a>, un tableau, et l&rsquo;initialiser dans le constructeur\u00a0:<\/p>\n<pre><code>&lt;?php\n\nclass Registry\n{\n    private $registry;\n\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/\/ ...\n\n}<\/code><\/pre>\n<p>Apr\u00e8s cela, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-02-registry-add-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">nous pouvons cr\u00e9er la m\u00e9thode add<\/a>. N&rsquo;oubliez pas que dans mon impl\u00e9mentation, je choisis de lever une exception si une cl\u00e9 est d\u00e9j\u00e0 d\u00e9finie, mais vous n&rsquo;avez pas \u00e0 le faire.<\/p>\n<pre><code>&lt;?php\n\npublic function add($id, $obj)\n{\n    if (isset($this-&gt;registry[$id])) {\n        throw new Exception('An object already exists for this given key.');\n    }\n    $this-&gt;registry[$id] = $obj;\n}<\/code><\/pre>\n<p>De m\u00eame, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-03-registry-get-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">la m\u00e9thode get<\/a> renverra une r\u00e9f\u00e9rence \u00e0 l&rsquo;instance d&rsquo;un objet identifi\u00e9 avec cette cl\u00e9. Si la cl\u00e9 n&rsquo;est pas d\u00e9finie, elle l\u00e8vera une exception. S&rsquo;il est d\u00e9fini, mais qu&rsquo;aucun objet n&rsquo;existe, nous renverrons null.<\/p>\n<pre><code>&lt;?php\n\npublic function get($id)\n{\n    if (!isset($this-&gt;registry[$id])) {\n        throw new Exception('No object exists for the specified key.');\n    }\n\n    return $this-&gt;registry[$id] ?? null;\n}<\/code><\/pre>\n<p>Enfin, nous avons besoin d&rsquo;une m\u00e9thode pour renvoyer tous les abonn\u00e9s enregistr\u00e9s. Dans un prochain article, l&rsquo;utilisation de cela deviendra beaucoup plus apparente, mais pour l&rsquo;instant, notez que nous allons cr\u00e9er un tableau de n&rsquo;importe quelle classe qui est une instance de la classe <strong>AbstractSubscriber ,<\/strong> <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-04-registry-get-subscribers-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">puis nous renverrons le tableau filtr\u00e9.<\/a><\/p>\n<pre><code>&lt;?php\n\npublic function getRegisteredSubscribers()\n{\n    $subscribers = [];\n    foreach ($this-&gt;registry as $object) {\n        if ($object instanceof AbstractSubscriber) {\n            $subscribers[] = $object;\n        }\n    }\n\n    return array_filter($subscribers);\n}<\/code><\/pre>\n<p>\u00c0 ce stade, <a href=\"https:\/\/gist.github.com\/tommcfarlin\/b45606bde5d777e88fd5e3988f610dea#file-05-registry-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">nous avons la classe<\/a> compl\u00e8te (compl\u00e8te avec la documentation):<\/p>\n<pre><code>&lt;?php\n\n\/*\n * This file is part of the WordPress Widget Boilerplate\n *\n * (c) Tom McFarlin &lt;tom@tommcfarlin.com&gt;\n *\n * This source file is subject to the GPL license that is bundled\n * with this source code in the file LICENSE.\n *\/\n\nnamespace WordPressWidgetBoilerplateUtilities;\n\nuse Exception;\nuse WordPressWidgetBoilerplateSubscriberAbstractSubscriber;\n\n\/**\n * This class services as a simple container that can be used to pass objects\n * around the plugin.\n *\n * To use this class you'd make a call to the registry by saying Registry-&gt;get(),\n * then making a class to `register()` and `retrieve()` on an instance of the object.\n *\/\nclass Registry\n{\n    \/**\n     * @var array an array used to maintain the objects registered with the plugin\n     *\/\n    private $registry;\n\n    \/**\n     * Initializes the class by setting up the registry.\n     *\/\n    public function __construct()\n    {\n        $this-&gt;registry = [];\n    }\n\n    \/**\n     * Registers an object with the registry with the specified ID; however, will throw an\n     * exception if the ID is already referencing an object.\n     *\n     * @param string $id  an ID by which the specified object will be referenced\n     * @param mixed  $obj an instance of an object to store in the registry\n     *\n     * @throws Exception if an object already exists for the specified key\n     *\/\n    public function add($id, $obj)\n    {\n        if (isset($this-&gt;registry[$id])) {\n            throw new Exception('An object already exists for this given key.');\n        }\n        $this-&gt;registry[$id] = $obj;\n    }\n\n    \/**\n     * @param string $id the ID for the object that we wish to retrieve\n     *\n     * @throws Exception if no object exists for the specified key\n     *\n     * @return mixed a reference to the object or null\n     *\/\n    public function get($id)\n    {\n        if (!isset($this-&gt;registry[$id])) {\n            throw new Exception('No object exists for the specified key.');\n        }\n\n        return $this-&gt;registry[$id] ?? null;\n    }\n\n    \/**\n     * @return array all of the the Subscribers that should be registered with WordPress\n     *\/\n    public function getRegisteredSubscribers()\n    {\n        $subscribers = [];\n        foreach ($this-&gt;registry as $object) {\n            if ($object instanceof AbstractSubscriber) {\n                $subscribers[] = $object;\n            }\n        }\n\n        return array_filter($subscribers);\n    }\n}\n<\/code><\/pre>\n<p>Nous devons maintenant l&rsquo;ajouter au bootstrap de notre plugin.<\/p>\n<h2>Avant le bootstrap, bien que<\/h2>\n<p>Comme mentionn\u00e9 pr\u00e9c\u00e9demment dans le post, nous devons ajouter ceci au bootstrap du plugin. Pour ce faire, cependant, nous devons d\u00e9finir notre propre filtre afin de pouvoir facilement passer le registre autour du reste du plugin (le moment venu).<\/p>\n<p>Avant de faire cela, cependant, il est important de s&rsquo;assurer que vous ma\u00eetrisez bien le registre que nous venons de cr\u00e9er, qu&rsquo;il s&rsquo;int\u00e8gre dans le plugin et que vous suivez avec la branche de <a href=\"https:\/\/github.com\/tommcfarlin\/WordPress-Widget-Boilerplate\/tree\/develop\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">d\u00e9veloppement que nous avons jusqu&rsquo;\u00e0 pr\u00e9sent.<\/a><\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Source d&rsquo;enregistrement:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Un probl\u00e8me qui existe toujours dans le code tel qu&rsquo;il est actuellement est que le constructeur du widget WordPress enregistre des fonctions et ce n&rsquo;est pas une bonne chose.<\/p>\n","protected":false},"author":1,"featured_media":223984,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[893,717,862],"tags":[1167],"class_list":["post-231121","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-code-2","category-developpeur","category-wordpress-3","tag-affiai-fr"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/231121","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/comments?post=231121"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/posts\/231121\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media\/223984"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/media?parent=231121"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/categories?post=231121"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/fr\/wp-json\/wp\/v2\/tags?post=231121"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}