La communication entre modules

Introduction



Certains modules doivent communiquer avec les autres pour avoir différentes informations.
C'est le cas du module recherche par exemple qui a besoin de connaitre un certain nombre de choses.
Cette communication n'est pas seulement limitée aux modules, elle peut également se faire entre plusieurs modules, l'administration ou le noyau.

Mise en pratique



Nous avons besoin de créer un seul et même fichier dans notre module. Celui-ci contiendra une classe.
La syntaxe est là suivante : LeNomDeVotreModuleExtensionPointProvider.
Par exemple, pour le module newsletter, la syntaxe est : NewsletterExtensionPointProvider.
Nous allons donc créer un fichier LeNomDeVotreModuleExtensionPointProvider.class.php.
A l'intérieur de ce fichier, nous allons créer une classe fille de ExtensionPointProvider avec comme nom : LeNomDeVotreModuleExtensionPointProvider.
Le constructeur de la classe attend un paramètre qui est l'identifiant du module (le nom du dossier du module).
Cela donne :
Code PHP :
class LeNomDeVotreModuleExtensionPointProvider extends ExtensionPointProvider
{
    public function __construct()
    {
        parent::__construct('VotreModule');
    }
}
?>

Notre fichier de communication est fin prêt à être utilisé.

Les différentes possibilités



Maintenant que votre fichier est prêt, il faut implémenter diverses fonctions.
Nous allons citer les principales interfaces présentes au sein de PHPBoost.

La réécriture des urls



Pour ajouter la règle de réécriture des urls dans le htaccess de manière automatique, vous devez ajouter une fonction url_mappings() à votre ExtensionPointProvider.
Celle-ci devra retourner un objet de la classe UrlMappings prennant en paramètre un tableau avec la liste des fichiers que vous utilisez comme Dispatcher.
Exemple :
Code PHP :
public function url_mappings()
{
    return new UrlMappings(array(new DispatcherUrlMapping('/contact/index.php')));
}

Les menus



Pour ajouter un ou plusieurs menus, vous devez ajouter une fonction menus() à votre ExtensionPointProvider.
Elle doit retourner un objet ModuleMenus qui prend en paramètre un tableau contenant les objets de vos menus.
Code PHP :
public function menus()
{
    return new ModuleMenus(array(new NewsletterModuleMiniMenu()));
}

Ensuite il vous faut créer le menu en question. Pour l'exemple plus haut (module newsletter) voici le contenu de la classe NewsletterModuleMiniMenu :
Code PHP :
<?php
/*##################################################
 *                          NewsletterModuleMiniMenu.class.php
 *                            -------------------
 *   begin                : October 08, 2011
 *   copyright            : (C) 2011 Kevin MASSY
 *   email                : soldier.weasel@gmail.com
 *
 *
 ###################################################
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 ###################################################*/
class NewsletterModuleMiniMenu extends ModuleMiniMenu
{    
    public function get_default_block()
    {
        // Retourne la position du block par défaut, se référer au constantes dans la classe Menu
        return self::BLOCK_POSITION__TOP_FOOTER;
    }
 
    // Retourne ce qui doit être affiché dans la gestion des menus (facultatif)
    public function admin_display()
    {
        return '';
    }
 
    public function get_menu_id()
    {
        return 'module-mini-nomdumodule';
    }
 
    public function get_menu_title()
    {
        return 'Module title';
    }
 
    public function is_displayed()
    {
        //Vérifiez ici les autorisations d'affichage si besoin
        return true;
    }
    public function get_menu_content()
    {
        $tpl = new FileTemplate('newsletter/newsletter_mini.tpl');
 
        // Permet d'assigner les variables tpl au template pour pouvoir ensuite donner un affichage différent selon la colonne où est situé le menu
        MenuService::assign_positions_conditions($tpl, $this->get_block());
 
        $lang = LangLoader::get('newsletter_common', 'newsletter');
        $tpl->put_all(array(
            'SUBSCRIBE' => $lang['newsletter.subscribe_newsletters'],
            'UNSUBSCRIBE' => $lang['newsletter.unsubscribe_newsletters'],
            'USER_MAIL' => (AppContext::get_current_user()->get_attribute('user_mail') != '') ? AppContext::get_current_user()->get_attribute('user_mail') : '',
            'L_NEWSLETTER' => $lang['newsletter'],
            'L_SUBMIT' => $lang['newsletter.submit'],
            'L_ARCHIVES' => $lang['newsletter.archives']
        ));
        // Retourne l'affichage du menu
        return $tpl->render();
    }
}
?>

Page d'accueil



Vous pouvez à travers votre module, ajouter une page d'accueil pour pouvoir ensuite la définir en tant qu'index de votre site.
Vous devez créer une classe (et donc un fichier) MonModuleHomePageExtensionPoint.
Cette classe doit implémenter l'interface HomePageExtensionPoint et contenir une fonction get_home_page() renvoyant une instance de la classe DefaultHomePage.
Exemple :
Code PHP :
<?php
/*##################################################
 *                     NewsletterHomePageExtensionPoint.class.php
 *                            -------------------
 *   begin                : February 12, 2012
 *   copyright            : (C) 2012 Julien BRISWALTER
 *   email                : j1.seth@phpboost.com
 *
 *
 ###################################################
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 ###################################################*/
class NewsletterHomePageExtensionPoint implements HomePageExtensionPoint
{
    public function get_home_page()
    {
        return new DefaultHomePage($this->get_title(), $this->get_view());
    }
    private function get_title()
    {
        // Titre de la page
        return LangLoader::get_message('newsletter', 'newsletter_common', 'newsletter');
    }
    private function get_view()
    {
        // Retourne un object Template (StringTemplate ou FileTemplate)
        return NewsletterModuleHomePage::get_view();
    }
}
?>

Ensuite, vous devez ajouter une fonction home_page() à votre ExtensionPointProvider.
Elle doit retourner l'objet de la classe que vous venez de créer précédemment.

Fichiers CSS



Pour profiter du système de cache CSS et permettre la personnalisation de vos modules dans les différents thèmes, vous devez ajouter une fonction css_files() à votre ExtensionPointProvider.
Celle-ci doit renvoyer un objet de la classe ModuleCssFiles.
Exemple :
Code PHP :
public function css_files()
{
    $module_css_files = new ModuleCssFiles();
    $module_css_files->adding_running_module_displayed_file('ce_fichier_est_chargé_seulement_sur_le_module.css');
    $module_css_files->adding_always_displayed_file('ce_fichier_est_chargé_sur_toute_les_pages_du_site.css');
    return $module_css_files;
}

Sitemap



Pour intégrer votre module au sitemap et au plan du site, il faut créer une classe MonModuleSitemapExtensionPoint qui implémente l'interface SitemapExtensionPoint.
Deux fonctions devront être présentes dans cette classe : get_public_sitemap() et get_user_sitemap().
Les deux sont identiques, sauf sur un point : l'une renvoie le sitemap public, et l'autre le sitemap pour les utilisateurs connectés.
Vous devrez renvoyer un objet ModuleMap.
Voici une implémentation type :
Code PHP :
<?php
/*##################################################
 *                       NewsletterSitemapExtensionPoint.class.php
*                            -------------------
*   begin                : May 30, 2012
*   copyright            : (C) 2012 Kevin MASSY
*   email                : soldier.weasel@gmail.com
*
*
###################################################
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*
###################################################*/
class NewsletterSitemapExtensionPoint implements SitemapExtensionPoint
{
    public function get_public_sitemap()
    {
        return $this->get_module_map(Sitemap::AUTH_PUBLIC);
    }
    public function get_user_sitemap()
    {
        return $this->get_module_map(Sitemap::AUTH_USER);
    }
    private function get_module_map($auth_mode)
    {
        $lang = LangLoader::get('newsletter_common', 'newsletter');
        // Informations : nom du module, url vers le module et fréquence de mise à jour du sitemap
        $link = new SitemapLink($lang['newsletter'], NewsletterUrlBuilder::home(), Sitemap::FREQ_MONTHLY, Sitemap::PRIORITY_MAX);
        //SitemapLink et en deuxième paramètre l'identifiant du module (le nom du dossier du module)
        $module_map = new ModuleMap($link, 'newsletter');
        $streams = NewsletterStreamsCache::load()->get_streams();
        $config = NewsletterConfig::load();
        $user = AppContext::get_current_user();
        foreach ($streams as $id => $properties)
        {
            if ($auth_mode == Sitemap::AUTH_PUBLIC)
            {
                $is_authorized = is_array($properties['authorizations']) ? Authorizations::check_auth(RANK_TYPE, User::VISITOR_LEVEL, $properties['authorizations'], NewsletterAuthorizationsService::AUTH_READ) : Authorizations::check_auth(RANK_TYPE, User::VISITOR_LEVEL, $config->get_authorizations(), NewsletterAuthorizationsService::AUTH_READ);
            }
            else
            {
                $is_authorized = is_array($properties['authorizations']) ? $user->check_auth($properties['authorizations'], NewsletterAuthorizationsService::AUTH_READ) : $user->check_auth($config->get_authorizations(), NewsletterAuthorizationsService::AUTH_READ);
            }
            if ($is_authorized && $properties['visible'])
            {
                // On créer une section du sitemap avec le lien qui contient le nom du lien et son url
                $link = new SitemapLink($properties['name'], NewsletterUrlBuilder::archives($id));
                $section = new SitemapSection($link);
                // On ajoute la section au module map
                $module_map->add($section);
            }
        }
        //On renvoie l'objet
        return $module_map;
    }
}
?>