<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet title="XSL formatting" type="text/xsl" href="https://dotclear.watch/feed/rss2/xslt" ?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>DotclearWatch / Blog - Mot-clé - factory</title>
    <link>https://dotclear.watch/</link>
    <atom:link href="https://dotclear.watch/feed/tag/factory/rss2" rel="self" type="application/rss+xml" />
    <description>Suivez l'évolution du moteur de blogs Dotclear.</description>
    <language>fr</language>
    <pubDate>Sun, 19 Apr 2026 21:23:09 +0200</pubDate>
    <copyright>Tous droits réservés © Jean-Christian Denis</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>Dotclear</generator>
          <item>
        <title>[2.36] Modification des conteneurs</title>
        <link>https://dotclear.watch/Billet/%5B2.36%5D-Modification-des-conteneurs</link>
        <guid isPermaLink="false">urn:md5:56ec421497f9dea239c3da9d9a8876cf</guid>
        <pubDate>Tue, 02 Sep 2025 09:33:00 +0200</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.36</category>
                          <category>2.36</category>
                  <category>container</category>
                  <category>factory</category>
                <description>&lt;p&gt;Avec les corrections des divers bugs du coeur de Dotclear 2.36, la classe de Container a été améliorée.&lt;/p&gt; &lt;p&gt;&lt;a class=&quot;ref-post&quot; href=&quot;https://dotclear.watch/Billet/2.36&quot; title=&quot;Article rédigé pour Dotclear 2.36&quot;&gt;&lt;img alt=&quot;badge Dotclear 2.36&quot; src=&quot;https://img.shields.io/badge/Dotclear-2.36-blue?style=for-the-badge&quot; /&gt; &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Le gestionnaire de service (Container) embarqué dans Dotclear ne permettait pas de passer à ses services le container lui-même, c'est désormais possible depuis Dotclear 2.36. Une autre limite du container était qu'on ne pouvait pas récupèrer d'instance d'une service pour un usage isolé sans propager les intercations à tout le container. Pour faire simple si on modifiait les paramètres d'un service, cela modifiait ce service pour tout le script. Il est désomrais possible de créer des instances de service à usage ponctuel.&lt;/p&gt;

&lt;p&gt;L'appel d'un service avec le paramètre NULL permet d'avoir une instance isolée de ce service. Les valeurs TRUE et FALSE de ce paramètre ont toujours les mêmes fonction qu'avant.&lt;/p&gt;

&lt;p&gt;Voici un exemple complet montrant le passage du container au service et l'utilisation du paramétre NULL à la récupération du service :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php 

use Dotclear\Helper\Container\Container;
use Dotclear\Helper\Conttainer\Factories;

// Class du service
class MonService
{
    protected int $nb = 0;

    // On passe le container directement au service
    public function __construct(
        protected MonContainer $container
    ) {

    }

    // On met en mémoire du service un nombre
    public function nombre(int $nb): void
    {
        $this-&amp;gt;nb = $nb;
    }

    // On lance un calcul en utilisant une methode du container
    public function calcul(): string
    {
        $somme = $this-&amp;gt;container-&amp;gt;ajoute($this-&amp;gt;nb);

        return 'resultat : ' . $somme . &quot;\n&quot;;
    }
}

// Class du container
class MonContainer extends Container
{
    public const CONTAINER_ID = 'moncontainer';

    public function __construct()
    {
        parent::__construct(Factories::getFactory(static::CONTAINER_ID));
    }

    // Methode qui fait une addition
    public function ajoute(int $nb): int
    {
        return $nb + $nb;
    }
}

// On ajoute le service au container
Factories::addService('moncontainer', 'monservice', MonService::class);

// On crée l'instance du container
$container = new MonContainer();

// On récupère une instance du service depuis le container
$a = $container-&amp;gt;get('monservice');

// On lui donne un nombre
$a-&amp;gt;nombre(2);

// On fait une première fois le calcul
echo $a-&amp;gt;calcul(); // resultat : 4

// On donne un autre nombre à notre instance du sevice
$a-&amp;gt;nombre(3);

// On calcul, le résultat prend en compte le dernier nombre soumis
echo $a-&amp;gt;calcul(); // resultat : 6

// On recupère une instance du service depuis le container
$b = $container-&amp;gt;get('monservice');

// Même sans soumettre de nombre, 
// on voit que le calcul se fait sur la même instance de service que précédement.
echo $b-&amp;gt;calcul(); // resultat : 6

// On vérifie, et effectivement les deux instances a et b sont en réalité la même
echo $a-&amp;gt;calcul(); // resultat : 6

// On récupère une nouvelle instance avec le parametre null
$c = $container-&amp;gt;get('monservice', null);

// On donne à cette instance un nombre
$c-&amp;gt;nombre(4);

// Le calcul prend bien en compte ce nombre
echo $c-&amp;gt;calcul(); // resultat : 8

// On refait le calcul sur l'instance précédente, elle a bien gardé en mémoire le nombre précèdent
echo $b-&amp;gt;calcul(); // resultat : 6

// Ce sont bien cette fois deux instances distinctes

// On récupère une instance du service depuis le container
$d = $container-&amp;gt;get('monsevrice');

// On fait un calcul sans donner de nombre
echo $d-&amp;gt;calcul(); // resultat: 6

// on voit que $c avec le paremetre null n'a pas d'influence sur les autres instances&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Attention aux effets de bords&lt;/u&gt;, les objets partagés dans ces instances peuvent être modifiés dans une instance et renvoyer un résultat inattendu dans une autre instance !&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A noter que tous les constructeurs des classes de premier niveau de Dotclear, celles qui sont disponibles dans le container principal, utilisables depuis App::xxx() ont désormais le container comme paramètre.&lt;br /&gt;
Par exemple classe Auth est passée de ça :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-php&quot;&gt;class Auth
{
    // ...
    /**
     * Constructs a new instance.
     *
     *@param   BlogInterface               $blog           The blog instance
     * @param   BlogsInterface              $blogs          The blogs handler
     * @param   ConfigInterface             $config         The configuration instance
     * @param   DatabaseInterface           $db             The database handler instance
     * @param   SessionInterface            $session        The session handler
     * @param   UserPreferencesInterface    $user_prefs     The user preferences instance
     * @param   UsersInterface              $users          The users handler
     */
    public function __construct(
        protected BlogInterface $blog,
        protected BlogsInterface $blogs,
        protected ConfigInterface $config,
        protected DatabaseInterface $db,
        protected SessionInterface $session,
        public UserpreferencesInterface $user_prefs,
        protected UsersInterface $users
    ) {
        // ...
    }
    // ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;à ça :&lt;/p&gt;

&lt;pre&gt;
&lt;code class=&quot;language-php&quot;&gt;class Auth
{
    // ...
    /**
     * Constructs a new instance.
     *
     * @param   Core    $core   The core container
     */
    public function __construct(
        protected Core $core
    ) {
        // ...
    }
    // ...
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Certains y veront le grand retour de $core, mais il n'en est rien, car cela n'est effectif que dans les classes de premier niveau, associées au container.&lt;br /&gt;
 &lt;/p&gt;

&lt;h3 id=&quot;process&quot;&gt;Appel aux classes de context&lt;/h3&gt;

&lt;p&gt;Les instances de classes appartenant aux contextes (Utility) telles que Frontend, Backend, Upgrade et Install sont désormais disponibles comme méthodes du contexte. Il n'est plus nécessaire de déclarer l'utilisation des classes comme &lt;strong&gt;\Dotclear\Core\Backend\Favorites::class&lt;/strong&gt; pour les utiliser, car elles sont maintenant directement disponibles dans l'objet du contexte, ce qui donnera pour l'exemple &lt;strong&gt;App::backend()-&amp;gt;favorites()&lt;/strong&gt;;&lt;/p&gt;

&lt;p&gt;Voici une liste des classes de second niveau pour le Backend :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Dotclear\Core\Backend\Action::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;action(), (nouvelle classe, voir plus bas)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Auth::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;auth(), (nouvelle classe, voir plus bas)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Combos::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;combos(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Favorites::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;favorites(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;filter(), (nouvelle classe, voir plus bas)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Helper::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;helper(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing(), (nouvelle classe, voir plus bas)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\MediaPage::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;mediaPage(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Menus::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;menus(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\ModulesList::class =&amp;gt; App::backend()-&amp;gt;modulesList(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Notices::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;notices-),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Page::class =&amp;gt; App::backend()-&amp;gt;page(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Resources::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;resources(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\ThemeConfig::class =&amp;gt; App::backend()-&amp;gt;themeConfig(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\ThemesList::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;themesList(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Url::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;url(),&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\UserPref::class&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;userPref(),&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les nouvelles classes de Backend utiles aux listes que sont Action, Filter et Listing fournissent les instances des objets suivant :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Dotclear\Core\Backend\Action\ActionsBlogs =&amp;gt; App::backend()-&amp;gt;action()-&amp;gt;blogs(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Action\ActionsComments&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;action()-&amp;gt;comments(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Action\ActionsPosts =&amp;gt; App::backend()-&amp;gt;action()-&amp;gt;posts(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter\FilterBlogs =&amp;gt; App::backend()-&amp;gt;filter()-&amp;gt;blogs(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter\FilterComments&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;filter()-&amp;gt;comments(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter\FilterMedia&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;filter()-&amp;gt;media(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter\FilterPosts&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;filter()-&amp;gt;posts(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Filter\FilterUsers =&amp;gt; App::backend()-&amp;gt;filter()-&amp;gt;users(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingBlogs =&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;blogs(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingCommnets&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;comments(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingMedia&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;media(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingPosts =&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;posts(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingPostsMini&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;postsMini(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\ListingUsers&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;users(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Listing\Pager&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;listing()-&amp;gt;pager(...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une autre nouvelle classe fournit les instances des objets nécessaires aux connections tierces :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Dotclear\Core\Backend\Auth\Otp&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;auth()-&amp;gt;otp(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Auth\WebAuthn&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;auth()-&amp;gt;webauthn(...)&lt;/li&gt;
	&lt;li&gt;Dotclear\Core\Backend\Auth\OAuth2Client&amp;nbsp;=&amp;gt; App::backend()-&amp;gt;auth()-&amp;gt;oauth2(...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Voici une liste des classes de second niveau pour le Frontend :&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Doclear\Core\Frontend\Ctx::class&amp;nbsp;=&amp;gt; App::frontend()-&amp;gt;context(),&lt;/li&gt;
	&lt;li&gt;Doclear\Core\Frontend\Tpl::class&amp;nbsp;=&amp;gt; App::frontend()-&amp;gt;template(),&lt;/li&gt;
	&lt;li&gt;Doclear\Core\Frontend\XmlRpc::class&amp;nbsp;=&amp;gt; App::frontend()-&amp;gt;xmlrpc(),&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les plugins et thèmes, en pouvant accèder directement depuis le contexte à ces objets, ne devraient plus avoir à déclarer des classes appartenant aux Backend ou Frontend hormis lors de la création de liste pour étendre une classe.&lt;br /&gt;
.&lt;/p&gt;</description>
        
                  <comments>https://dotclear.watch/Billet/%5B2.36%5D-Modification-des-conteneurs#comment-form</comments>
          <wfw:comment>https://dotclear.watch/Billet/%5B2.36%5D-Modification-des-conteneurs#comment-form</wfw:comment>
          <wfw:commentRss>https://dotclear.watch/feed/atom/comments/446</wfw:commentRss>
              </item>
          <item>
        <title>Remplacer une classe de premier niveau</title>
        <link>https://dotclear.watch/Billet/Remplacer-une-classe-de-premier-niveau-en-2.28</link>
        <guid isPermaLink="false">urn:md5:b4b07c44e57f9060b7c9e721709fea02</guid>
        <pubDate>Fri, 13 Oct 2023 08:00:00 +0200</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>Articles</category>
                          <category>2.28</category>
                  <category>container</category>
                  <category>core</category>
                  <category>factory</category>
                <description>&lt;p&gt;Dans cet article nous allons voir de façon très succincte comment remplacer une des classes du cœur de Dotclear en utilisant un conteneur de services.&lt;/p&gt; &lt;p&gt;Autant le dire tout de suite, ça ne va pas servir à tout le monde, et uniquement pour des cas bien précis, par des utilisateurs connaissant cette façon de coder.&lt;/p&gt;

&lt;h5&gt;Définition&lt;/h5&gt;


&lt;blockquote&gt;&lt;p&gt;- Mais c'est quoi un conteneur, un service, une usine ?&lt;br /&gt;
- C'est un &lt;a href=&quot;https://fr.wikipedia.org/wiki/Patron_de_conception&quot; hreflang=&quot;fr&quot; title=&quot;Définition de Design Partern su rWikipedia&quot;&gt;patron de conception&lt;/a&gt; aka design pattern.&lt;br /&gt;
- Mais encore ?&lt;br /&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Profitant du passage aux espaces de nom PHP, le cœur de Dotclear, appelé &lt;strong&gt;core&lt;/strong&gt; ou &lt;strong&gt;dcCore&lt;/strong&gt;, a disparu au profit d'un conteneur qui s'occupe uniquement de fournir &lt;a href=&quot;https://dotclear.watch/Billet/Le-conteneur-principal&quot;&gt;les classes maitresses&lt;/a&gt; de Dotclear, ces classes sont définies et leur objets générés par le conteneur, appelé &lt;strong&gt;Core&lt;/strong&gt;. (Original comme nom !) Tout ce petit monde suivant des règles bien précises écrites dans des interfaces.&lt;br /&gt;
Pour faire simple:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Un service est un ensemble de méthodes dédiées à une tâche, par exemple la gestion des behaviors, regroupées dans une classe&lt;/li&gt;
&lt;li&gt;Le conteneur &lt;strong&gt;Container&lt;/strong&gt; fournit à l'utilisateur les objets prêt à l'emploi, ici App:: avec App::unService()&lt;/li&gt;
&lt;li&gt;L'usine &lt;strong&gt;Factory&lt;/strong&gt; fournit ces classes, sans que l'utilisateur sache lesquelles sont réellement chargées.&lt;/li&gt;
&lt;li&gt;Les interfaces &lt;strong&gt;xxxInterface&lt;/strong&gt; définissent les règles que doivent suivre les classes de l'usine. exemple: BehaviorInterface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette technique va permettre de remplacer toutes les classes accessibles depuis App::xxx()&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Déclaration&lt;/h5&gt;

&lt;p&gt;Il faut commencer par déclarer notre service, une classe dédiée &lt;code&gt;\Dotclear\Helper\Container\Factories&lt;/code&gt; est là pour ça, on va lui dire d'ajouter notre service. Le plus simple est de lui dire depuis le fichier &lt;code&gt;inc/config.php&lt;/code&gt; de l'installation, dans l'exemple qui suit, on veut simplement remplacer une seule méthode de la classe &lt;strong&gt;Error&lt;/strong&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
//... contenu du fichier inc/config.php

// Notre service n&amp;#039;utilise pas d&amp;#039;espace de nom, on le récupère directement
require_once __DIR__ . &amp;#039;/../MyError.php&amp;#039;;

// On dit à la maison mère que notre service va être utilisé dans le core de Dotclear pour le service ErrorInterface::class
\Dotclear\Helper\Container\Factories::addService(&amp;#039;core&amp;#039;, ErrorInterface::class, MyError::class);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Voilà notre service remplace celui de Dotclear.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Service&lt;/h5&gt;

&lt;p&gt;Passons à notre service. Il doit obligatoirement suivre des règles strictes pour pouvoir être utilisé à la place d'un autre, voici le contenu de notre fichier &lt;code&gt;MyError.php&lt;/code&gt; :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;&amp;lt;?php
// On va reprendre la classe d&amp;#039;erreur et ses méthodes
use Dotclear\Core\Error;
// Pas besoin d&amp;#039;implémenter l&amp;#039;interface qui l&amp;#039;est déjà par la classe Error
//use Dotclear\Interface\Core\ErrorInterface;

// on crée notre classe d&amp;#039;erreur qui va étendre celle par défaut.
class MyError extends Error
{
    // on remplace uniquement la méthode qui nous intéresse
    public function add(string $msg): void
    {
        // notre classe va arrêter net le script sur une erreur au lieu de renvoyer un bandeau par exemple
        exit($msg);
    }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Cet exemple est simple, il permet de montrer la mécanique d'utilisation de &lt;code&gt;Factories&lt;/code&gt;, si vous souhaitez remplacer la gestion de connexion à la base de données cela va être bien plus compliqué !&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Liste des classes maîtresses&lt;/h5&gt;

&lt;p&gt;Voici la liste des appels depuis l'application et des interfaces associées :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;App::auth(): &lt;code&gt;\Dotclear\Interface\Core\AuthInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::behavior(): &lt;code&gt;\Dotclear\Interface\Core\BehaviorInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::blog(): &lt;code&gt;\Dotclear\Interface\Core\BlogInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::blogSettings(): &lt;code&gt;\Dotclear\Interface\Core\BlogSettingsInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::blogs(): &lt;code&gt;\Dotclear\Interface\Core\BlogsInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::blogWorkspace(): &lt;code&gt;\Dotclear\Interface\Core\BlogWorkspaceInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::categories(): &lt;code&gt;\Dotclear\Interface\Core\CategoriesInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::cache(): &lt;code&gt;\Dotclear\Interface\Core\CacheInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::con(): &lt;code&gt;\Dotclear\Interface\Core\ConnectionInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::error(): &lt;code&gt;\Dotclear\Interface\Core\ErrorInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::filter(): &lt;code&gt;\Dotclear\Interface\Core\FilterInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::formater(): &lt;code&gt;\Dotclear\Interface\Core\FormaterInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::lang(): &lt;code&gt;\Dotclear\Interface\Core\LangInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::log(): &lt;code&gt;\Dotclear\Interface\Core\LogInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::media(): &lt;code&gt;\Dotclear\Interface\Core\MediaInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::meta(): &lt;code&gt;\Dotclear\Interface\Core\MetaInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::nonce(): &lt;code&gt;\Dotclear\Interface\Core\NonceInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::notice(): &lt;code&gt;\Dotclear\Interface\Core\NoticeInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::plugins(): &lt;code&gt;\Dotclear\Interface\Module\ModulesInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::postMedia(): &lt;code&gt;\Dotclear\Interface\Core\PostMediaInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::postTypes(): &lt;code&gt;\Dotclear\Interface\Core\PostTypesInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::rest(): &lt;code&gt;\Dotclear\Interface\Core\RestInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::session(): &lt;code&gt;\Dotclear\Interface\Core\SessionInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::themes(): &lt;code&gt;\Dotclear\Interface\Module\ModulesInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::trackback(): &lt;code&gt;\Dotclear\Interface\Core\TrackbackInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::url(): &lt;code&gt;\Dotclear\Interface\Core\UrlInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::users(): &lt;code&gt;\Dotclear\Interface\Core\UsersInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::userPreferences(): &lt;code&gt;\Dotclear\Interface\Core\UserPreferencesInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::userWorkspace(): &lt;code&gt;\Dotclear\Interface\Core\UserWorkspaceInterface&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;App::version(): &lt;code&gt;\Dotclear\Interface\Core\VersionInterface&lt;/code&gt;,&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le nom de l'interface sera le nom du service dans l'usine.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.28 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
                  <comments>https://dotclear.watch/Billet/Remplacer-une-classe-de-premier-niveau-en-2.28#comment-form</comments>
          <wfw:comment>https://dotclear.watch/Billet/Remplacer-une-classe-de-premier-niveau-en-2.28#comment-form</wfw:comment>
          <wfw:commentRss>https://dotclear.watch/feed/atom/comments/33</wfw:commentRss>
              </item>
          <item>
        <title>Le conteneur principal</title>
        <link>https://dotclear.watch/Billet/Le-conteneur-principal-en-2.28</link>
        <guid isPermaLink="false">urn:md5:42dc775565c5a181f7b6d9a55cd1fc07</guid>
        <pubDate>Fri, 13 Oct 2023 08:00:00 +0200</pubDate>
        <dc:creator>Jean-Christian Denis</dc:creator>
                  <category>2.28</category>
                          <category>app</category>
                  <category>container</category>
                  <category>factory</category>
                  <category>interface</category>
                  <category>service</category>
                <description>&lt;p&gt;La &lt;a href=&quot;https://dotclear.watch/Billet/Release-2.28&quot;&gt;version 2.28&lt;/a&gt; de Dotclear intégre un nouveau système de conteneur pour l'application qui remplace dcCore.&lt;/p&gt; &lt;p&gt;Grâce aux avancées de &lt;a href=&quot;https://dotclear.watch/Billet/Release-2.27&quot;&gt;Dotclear 2.27&lt;/a&gt;, cette nouvelle version 2.28 peut désormais proposer l'accès à la quasi totalité de l'application à partir d'un seul point &lt;strong&gt;App::&lt;/strong&gt;. Le core, aka dcCore, &lt;a href=&quot;https://dotclear.watch/Billet/Les-d%C3%A9pr%C3%A9ci%C3%A9s-du-core-en-2.28&quot;&gt;passe en déprécié&lt;/a&gt; et ses méthodes et propriétés sont regroupées dans des classes dédiées à un ensemble de tâches de même style. Une nouvelle gestion par conteneur et services accompagnée d'un nouvelle gestion d'exception permet de proposer ces classes à tout moment sans avoir besoin de les instancier. Autre nouveauté de taille qui pourra être exploitée par la suite, ces classes deviennent remplaçables ! Ce qui devra être utilisé pour des classes d'authentification ou de connexion tiers par exemple.&lt;br /&gt;
&lt;br /&gt;
Pour résumer, voici deux exemples simples de la nouvelle façon d'appeler les classes de l'ancien dcCore :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// Avant 2.28 :
dcCore::app()-&amp;gt;auth-&amp;gt;use_prefs;
// A partir 2.28, dcAuth fait partie du conteneur et ses propriétés deviennent des méthodes :
App::auth()-&amp;gt;prefs();

// Avant 2.28 :
dcCore::app()-&amp;gt;getAllBlogStatus();
// A partir de 2.28 les méthodes de l&amp;#039;ancien dcCore sont regroupées dans des classes à thème :
App::blogs()-&amp;gt;getAllBlogStatus();&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Voici la liste complète des classes composants ce nouveau Core de Dotclear :&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Configuration&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::config(): ConfigInterface&lt;/code&gt;&lt;br /&gt;
Cette classe est une nouveauté de dotclear 2.28, elle regroupe toutes les informations de &lt;a href=&quot;https://dotclear.watch/Billet/Configuration-de-l-application-en-2.28&quot;&gt;configuration de l'application&lt;/a&gt;.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Authentification&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::auth(): AuthInterface&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;auth&lt;/del&gt;&lt;br /&gt;
Anciennement dcAuth, c'est la classe de gestion de l'utilisateur.&lt;br /&gt;
Deux nouvelles méthodes sont disponibles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openUserCursor(): Cursor&lt;/code&gt; : renvoie un Cursor sur la table des utilisateurs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openPermCursor(): Cursor&lt;/code&gt; : renvoie un Cursor sur la table des permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'utilisation d'une classe tiers d'authentification est encore permise en 2.28, mais il faudra utiliser le nouveau système de remplacement de classe par la suite.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Comportement&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::behavior(): BehaviorInterface&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;xxxBehaviorxxx(xxx)&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe toutes les méthodes dépréciées de dcCore en rapport aux behaviors.&lt;br /&gt;
L'ancienne méthode &lt;strong&gt;getBehaviors()&lt;/strong&gt; est dédoublée :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getBehavior(string $behavior): array&lt;/code&gt; : renvoie un groupe de behaviors,&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getBehaviors(): array&lt;/code&gt; : renvoie tous les behaviors&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Blog&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::blog(): BlogInterface&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;blog, new dcBLog()&lt;/del&gt;&lt;br /&gt;
Anciennement dcBlog, c'est la classe de gestion du blog courant. Cette classe subit des changements majeures dans son utilisation.&lt;br /&gt;
Désormais cette classe existe toujours dans l'application. Il ne faut plus tester le chargement du blog avec &lt;strong&gt;!is_null(dcCore::app()-&amp;gt;blog)&lt;/strong&gt; mais &lt;code&gt;App::blog()-&amp;gt;isDefined()&lt;/code&gt;.&lt;br /&gt;
Il ne faut plus créer une nouvelle instance de dcBlog lorsqu'on veut naviguer entre deux blogs en cours de script, Il faut partir de l'instance existante et charger un autre blog dedans, puis recharger le premier si besoin. On peut mettre en id vide pour décharger un blog.&lt;br /&gt;
Une nouvelle méthode est donc disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::blog()-&amp;gt;loadFromBlog(string $blog_id): BlogInterface&lt;/code&gt; : renvoie l'instance de Blog chargé d'un autre blog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exemple de chargement :&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-php&quot;&gt;// On récupère l&amp;#039;ID de blog courant
$old_id = App::blog()-&amp;gt;id();
// On charge le blog qu&amp;#039;on souhaite modifier
App::blog()-&amp;gt;loadFromBlog(&amp;#039;SecondBlog&amp;#039;);
// On le modifie
App::blog()-&amp;gt;triggerBlog();
// On recharge le blog courant
App::blog()-&amp;gt;loadFromBlog($old_id);&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;De nouvelles méthodes sont disponibles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openBlogCursor(): Cursor&lt;/code&gt; : Ouvre un Cursor sur la table blog&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openPostCursor(): Cursor&lt;/code&gt; : Ouvre un Cursor sur la table post&lt;/li&gt;
&lt;li&gt;&lt;code&gt;openCommentCursor(): Cursor&lt;/code&gt; : Ouvre un Cursor sur la table comment&lt;/li&gt;
&lt;li&gt;&lt;code&gt;isDefined(): bool&lt;/code&gt; : Vérifie si un blog est chargé dans la classe ou non&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les propriétés publiques de la classe passent en déprécié, il faut désormais utiliser les méthodes idoines :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;id : &lt;code&gt;App::blog()-&amp;gt;id(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;uid : &lt;code&gt;App::blog()-&amp;gt;uid(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;name : &lt;code&gt;App::blog()-&amp;gt;name(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;desc : &lt;code&gt;App::blog()-&amp;gt;desc(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;url : &lt;code&gt;App::blog()-&amp;gt;url(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;host : &lt;code&gt;App::blog()-&amp;gt;host(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;creadt : &lt;code&gt;App::blog()-&amp;gt;creadt(): int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;upddt : &lt;code&gt;App::blog()-&amp;gt;upddt(): int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;status : &lt;code&gt;App::blog()-&amp;gt;status(): int&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;settings : &lt;code&gt;App::blog()-&amp;gt;settings(): BlogSettingsInterface&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;themes_path : &lt;code&gt;App::blog()-&amp;gt;themesPath(): string&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;dcCore::app()-&amp;gt;blog-&amp;gt;pblic_path : &lt;code&gt;App::blog()-&amp;gt;publicPath(): string&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Paramètres de blog&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::blogSettings(): BlogSettingsInterface&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;blog-&amp;gt;settings, new dcSettings();&lt;/del&gt;&lt;br /&gt;
Anciennement dcSettings, c'est la classe de gestion des paramètres de blog. Cette classe subit également un changement majeur dans son utilisation. Pour créer une nouvelle instance de BlogSettings, il faut utiliser une nouvelle méthode de la classe qui renverra une instance prête à l'emploie :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::blogSettings()-&amp;gt;createFromBlog(?string $blog_id): BlogSettingsInterface&lt;/code&gt; : renvoie une nouvelle instance de BlogSettings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On peut également utiliser &lt;code&gt;App::blog()-&amp;gt;settings()-&amp;gt;createFromBlog(?string $blog_id)&lt;/code&gt;.&lt;br /&gt;
Ses méthodes en xxxNamespace() passent en déprécié, il faut utiliser leurs méthodes associées xxxWorkspace().&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Espace de paramètres de blog&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::blogWorspace(), App::blog()-&amp;gt;settings()-&amp;gt;get(xxx), App::blog()-&amp;gt;settings()-&amp;gt;addWorspace(xxx)&lt;/code&gt;&lt;br /&gt;
Comme la classe précédente une nouvelle méthode fait son apparition pour créer une nouvelle instance de BlogWorkspace :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::blogWorkspace()-&amp;gt;createFromBlog(?string $blog_id, string $workspace, ?MetaRecord $rs = null): BlogWorkspaceInterface&lt;/code&gt; : renvoie une nouvelle instance de BlogWorkspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openBlogWorkspaceCursor(): Cursor&lt;/code&gt; : renvoie un Cursor sur la table des espaces de paramètres de blog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La méthode dumpNamespace() passe en déprécié, il faut utiliser dumpWorkspace().&lt;/p&gt;

&lt;h5&gt;Blogs&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App:blogs()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;xxxBlogsxxx()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe toutes les tâches en rapport à la gestion des blogs.&lt;br /&gt;
Changement par rapport à la version 2.27, la méthode getBlog() renverra toujours une instance de Blog. Ceci est dû au changement de comportement de la classe Blog.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Cache&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App:cache()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;emptyTemplatesCache(), dcCore::app()-&amp;gt;cache&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, Elle inclue une méthode de l'ancien core :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;emptyTemplatesCache(): void&lt;/code&gt; : vide le cache des templates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et une nouvelle méthode pour le cache des dépôts de modules :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;emptyModulesStoreCache(): void&lt;/code&gt; : vide le cache des dépôts tiers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Elle remplace également la gestion des fichiers et timestamps utilisés pour le cache coté public et qui était dans un simple tableau dcCore::app()-&amp;gt;cache :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;resetFiles(): void&lt;/code&gt; : Raz de la litses des fichiers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addFile(string $file): void&lt;/code&gt; : Ajoute un fichier&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addFiles(array $files): void&lt;/code&gt; : Ajoute plusieurs fichiers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getFiles(): array&lt;/code&gt; : Renvoie la liste des fichiers&lt;/li&gt;
&lt;li&gt;&lt;code&gt;function resetTimes(): void&lt;/code&gt; : Raz des timestamps&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addTime(int $time): void&lt;/code&gt; : Ajoute un timestamp&lt;/li&gt;
&lt;li&gt;&lt;code&gt;addTimes(array $times): void&lt;/code&gt; : Ajoute plusieurs timestamps&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getTimes(): array&lt;/code&gt; : Renvoie la listes des timestamps&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Catégories&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::categories(), App::blog()-&amp;gt;categories()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;blog-&amp;gt;categories, new dcCategories()&lt;/del&gt;&lt;br /&gt;
Anciennement dcCategories, c'est la classe de gestion des catégories d'un blog. Elle inclut désormais la classe NestedTree.&lt;br /&gt;
Comme vu sur de précédentes classes une nouvelle méthode fait son apparition pour créer une nouvelle instance de Categories :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::blog()-&amp;gt;categories()-&amp;gt;createFromBlog(string $blog_id): CategoriesInterface&lt;/code&gt; : renvoie une nouvelle instance de Categories.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openCategoryCursor(): Cursor&lt;/code&gt; : renvoie un Cursor sur la table des catégories&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Toutes les propriétés de la classe passent en &lt;em&gt;protected&lt;/em&gt;.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Connexion&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::con()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;con&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle permet le lien entre l'ancien chargement de gestionnaire de base de donnée et le nouveau système de chargement des classes du Core.
L'utilisation d'une classe tiers de connexion est encore permise en 2.28, mais il faudra utiliser le nouveau système remplacement de classe par la suite.&lt;br /&gt;
Elle inclut désormais le préfixe des tables disponibles en faisant &lt;code&gt;App::con()-&amp;gt;prefix()&lt;/code&gt;.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Déprécié&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App:deprecated()&lt;/code&gt;&lt;br /&gt;
Cette classe est disponible dans le Core ou en version statique. Elle permet de loguer en mode DEV d'éventuelles méthodes dépréciées.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Erreur&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::error()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;error&lt;/del&gt;&lt;br /&gt;
C'est la classe de gestion d'erreur non bloquante du Core.&lt;br /&gt;
Sa méthode &lt;strong&gt;toHTML()&lt;/strong&gt; passe en dépréciée, il faut utiliser votre propre parser à la place.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Filtre&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::filter()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;wiki, dcCore::app()-&amp;gt;xxxWikiXxx(), dcCore::app()-&amp;gt;HTMLfilter()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe toutes les méthodes et propriétés dédiées à la syntaxe wiki et HTML de texte.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Formateur&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App:formater()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;xxxFormaterXxx()&lt;/del&gt;-&lt;br /&gt;
Nouvelle classe de la version 2.28 elle regroupe toutes les méthodes de gestion des formateurs de texte.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Langue&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::lang()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;lang&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle s'occupe de la langue courante.&lt;br /&gt;
Deux méthodes sont disponibles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getLang(): string&lt;/code&gt; : renvoie le code de la langue courante&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setLang(string $lang): void&lt;/code&gt; : enregistre le code de la langue courante.&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Lexique&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::lexical()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcUtils::xxxlexicalxxx()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe toutes les méthodes en rapport au champs lexical d'une langue.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Log&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::log()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;log&lt;/del&gt;&lt;br /&gt;
Anciennement dcLog, cette classe s'occupe de la gestion de log.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openLogCursor(): Cursor&lt;/code&gt; : Ouvre un Cursor sur la table de log&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;L'ancienne méthode &lt;strong&gt;getTable()&lt;/strong&gt; passe en dépréciée, il faut utiliser la constante de classe disponible sur &lt;code&gt;App::log()::LOG_TABLE_NAME&lt;/code&gt;.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Média&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::media()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;media&lt;/del&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcMedia&lt;/strong&gt;, cette classe s'occupe de la gestion des média et comme vu précédemment, il ne faut plus créer une instance de &lt;strong&gt;dcMedia&lt;/strong&gt; mais toujours utiliser celle du &lt;strong&gt;Core&lt;/strong&gt;.&lt;br /&gt;
Pour définir le type de media, auparavant dans son constructeur, il faut utiliser la nouvelle méthode :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;setFilterMimeType(string $type): void&lt;/code&gt; : définit le type de media&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ses propriétés publiques deviennent dépréciées, il faut par exemple utiliser la méthode :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getThumbnailFilePattern(string $type = ''): string&lt;/code&gt; : renvoie la définition d'un pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;D'autres nouvelles méthodes sont disponibles :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openMediaCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des média&lt;/li&gt;
&lt;li&gt;&lt;code&gt;postMedia(): PostMediaInterface&lt;/code&gt; : retourne l'instance de PostMedia&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Métadonnée&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::meta()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;meta&lt;/del&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcMeta&lt;/strong&gt;, cette classe gère les métadonnées de dotclear.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openMetaCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des métadonnées&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Nonce&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::nonce()&lt;/code&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe les méthodes en rapport à la validation de formulaires.&lt;br /&gt;
L'ancienne méthode &lt;strong&gt;formNonce()&lt;/strong&gt; est dédoublée :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getFormNonce(): string&lt;/code&gt; : renvoie le contenu HTML&lt;/li&gt;
&lt;li&gt;&lt;code&gt;formNonce(): Hidden&lt;/code&gt; : renvoie l'élément de Form de type Hidden&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Notification&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::notice()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;notices&lt;/del&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcNotices&lt;/strong&gt;, cette classe gère en base les notices.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openNoticeCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Media de billets&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App:postMedia(), App::media()-&amp;gt;postMedia()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;postmedia&lt;/del&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcPostMedia&lt;/strong&gt;, cette classe gère les media de billets.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openPostMediaCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des media de billets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Les constantes des noms des tables de media et post media sont disponibles dans cette classe :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::postMedia()::MEDIA_TABLE_NAME&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;App::postMedia()::POST_MEDIA_TABLE_NAME&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A noter que lorsqu'un blog est chargé dans la classe &lt;strong&gt;Blog&lt;/strong&gt; via &lt;code&gt;App::blog()-&amp;gt;loadFromBlog()&lt;/code&gt;, il est également chargé dans l'instance de la classe &lt;strong&gt;PostMedia&lt;/strong&gt;.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Type de billets&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::postTypes()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;getPostxxxURL(), dcCore::app()-&amp;gt;xxxPostType()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe les méthodes en relation aux types de billets.&lt;br /&gt;
Les anciennes méthodes sont toujours utilisables mais il est recommandé d'utiliser l'autre nouvelle classe de définition d'un type de billet &lt;strong&gt;PostType&lt;/strong&gt;. (cf billet sur dcCore déprécié)&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Service REST&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::rest()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;xxxRestXxx()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe les méthodes relatives au service REST.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Session&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::session()&lt;/code&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle adapte l'ancienne classe de gestion de session à la nouvelle gestion de classe de Core.&lt;br /&gt;
Une nouvelle méthode est disponible pour créer simplement une nouvelle session à partir d'un nom de cookie (pratique pour les plugins et thèmes) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::session()-&amp;gt;createFromCookieName(string $cookie_name): SessionInterface&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Rétroliens&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::trackback()&lt;/code&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcTrackback&lt;/strong&gt;, cette classe gère les rétroliens et pingback.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openTrackbackCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des rétroliens&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Préférences utilisateur&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::userPrerefences()&lt;/code&gt;&lt;br /&gt;
Anciennement &lt;strong&gt;dcPrefs&lt;/strong&gt;, cette classe gère les préférences utilisateur. Elle est disponible pour l'utilisateur en cours dans &lt;code&gt;App::auth()-&amp;gt;prefs()&lt;/code&gt;.
Comme nombre de classes de Core, cette classe est toujours disponible et instanciée dans App::userPreferences(), pour avoir une nouvelle instance il faut donc utiliser sa méthode :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;createFromUser(string $user_id, ?string $user_workspace = null): UserPreferencesInterface&lt;/code&gt; : Créé une nouvelle instance des préférences utilisateur&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Espace de préférences utilisateur&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::userWorkspace(), App::auth()-&amp;gt;perfs()-&amp;gt;get(xxx), App::auth()-&amp;gt;prefs()-&amp;gt;addWorspace(xxx)&lt;/code&gt;&lt;br /&gt;
Comme la classe précédente une nouvelle méthode fait son apparition pour créer une nouvelle instance de UserWorkspace :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;createFromUser(?string $user_id, string $workspace, ?MetaRecord $rs = null): UserWorkspaceInterface&lt;/code&gt; : renvoie une nouvelle instance de UserWorkspace.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openUserWorkspaceCursor(): Cursor&lt;/code&gt; : renvoie un Cursor sur la table des espaces de préférences utilisateur&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Utilisateurs&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::users()&lt;/code&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle regroupe toutes les méthodes relatives aux utilisateurs.&lt;br /&gt;&lt;/p&gt;

&lt;h5&gt;Versions&lt;/h5&gt;

&lt;p&gt;&lt;code&gt;App::version()&lt;/code&gt;&lt;br /&gt;
&lt;del&gt;dcCore::app()-&amp;gt;xxxVersionXxx()&lt;/del&gt;&lt;br /&gt;
Nouvelle classe de la version 2.28, elle gère les version de module (et core) en base.&lt;br /&gt;
Une nouvelle méthode est disponible :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;openVersionCursor(): Cursor&lt;/code&gt; : ouvre un Cursor sur la table des versions&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;Autres&lt;/h5&gt;

&lt;p&gt;De plugs certaines classes plus spéciales sont accessibles depuis App::xxx() :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;App::backend()&lt;/code&gt; : Gestion de l'interface d'administration&lt;/li&gt;
&lt;li&gt;&lt;code&gt;App::frontend()&lt;/code&gt; : Gestion de l'interface publique&lt;/li&gt;
&lt;li&gt;&lt;code&gt;App::url()&lt;/code&gt; : Anciennement &lt;strong&gt;dcUrlHandler&lt;/strong&gt; de dcCore::app()-&amp;gt;url&lt;/li&gt;
&lt;li&gt;&lt;code&gt;App::task()&lt;/code&gt; : Uniquement utilisé par les plugins et thèmes pour tester le contexte avec &lt;code&gt;App::task()-&amp;gt;checkContext(...)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;En savoir plus&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dotclear.watch/Billet/Les-d%C3%A9pr%C3%A9ci%C3%A9s-du-core-en-2.28&quot;&gt;dcCore déprécié&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br /&gt;
&lt;em&gt;&lt;q&gt;Le contenu de ce document a été écrit suivant le code de la version 2.28 de Dotclear.&lt;/q&gt;&lt;/em&gt;&lt;/p&gt;</description>
        
              </item>
      </channel>
</rss>
