tas2580
Blog über Webentwicklung

Link im Header einfügen

Viele Extensions fügen neue Seiten hinzu und benötigen dazu einen Link in der Navigation im Header. Um dort einen Link einzufügen braucht man ein Core Event und ein Template Event, natürlich muss man vorher wie hier beschrieben eine Seite erstellen auf die man linken kann. Wichtig ist das man bereits eine funktionierende Route hat bevor man die hier beschriebenen Schritte durchführt da sich sonst das Forum nicht mehr aufrufen lässt.

In dem Beispiel wird foo\bar als Extension Name verwendet, das sollte man durch den Namen seiner Extension austauschen.

Core Event

Für das Core Event benötigt man wie hier beschrieben ein Listener der ein Event triggert. Um ein Event im Header zu triggern fügt man in das Array in getSubscribedEvents das passende Event ein. Eine Liste mit allen verfügbaren Events gibt es im phpBB Wiki. Um einen Link in den Header einzufügen bietet sich das Event core.page_header an.

Die komplette Methode sieht dann also folgendermaßen aus:

    public static function getSubscribedEvents()
    {
        return array(
            'core.page_header'        => 'page_header',
        );
    }

In dem Array wird vorne das Event das wir benutzen wollen angegeben (core.page_header) und hinten die Methode (page_header) die aufgerufen werden soll. Damit es übersichtlicher bleibt nenne ich die Methoden immer gleich wie das Event, man kann für die Methode auch einen beliebigen anderen Namen verwenden. Wichtig ist nur das man nachher seine Methode auch so wie angegeben nennt.

Jetzt kann man seine Methode erstellen und dort den Link ausgeben, der Name der Methode muss mit dem oben in getSubscribedEvents angegebenen Namen übereinstimmen. Der Code dazu sieht folgendermaßen aus:

    public function page_header($event)
    {
	$this->user->add_lang_ext('foo/bar', 'link');
	$this->template->assign_vars(array(
		'U_MY_LINK'	=> $this->helper->route('foo_bar_index', array()),
	));
    }

Als erstes wird mit $this->user->add_lang_ext('foo/bar', 'link'); eine Sprachdatei hinzugefügt, foo/bar ist dabei der Name der Extension und link der Name der Sprachdatei. Da die Datei bei jedem Seitenaufruf auch außerhalb der Extension geladen wird empfiehlt es sich hier nicht die generelle Sprachdatei der Extension zu verwenden sondern eine die nur den Text für den Link enthält. So kann Speicher gespart werden und das Forum wird nicht unnötig langsam.

Im nächsten Schritt wird dann der Link an das Template gesendet. Der Code dazu ist 'U_MY_LINK' => $this->helper->route('foo_bar_index', array()),, hier steht vorne der Name der Template Variable (Links sollten immer mit U_ beginnen) und hinten die Route zur Seite die man verlinken will. Wichtig ist das der Name der Route genau mit der hier erstellten Route übereinstimmt.

Zum Schluss muss man noch die benötigten Objekte und Variablen einbinden, das geschieht über den Konstruktor. Dazu wird einfach jedes benötigte Objekt oder jede benötigte Variable als Parameter im Konstruktor abgefragt.

    public function __construct(\phpbb\controller\helper $helper, \phpbb\template\template $template, \phpbb\user $user)
    {
        $this->helper = $helper;
        $this->template = $template;
        $this->user = $user;
    }

Hier werden also die Objekte $helper, $template und $user geladen. Welche Objekte und Variablen man laden muss hängt vom Code der in den einzelnen Events benutzt wird ab. Grundsätzlich muss man jedes Objekt und jede Variable die man irgendwo in der Datei verwenden will hier auflisten. Innerhalb des Konstruktors werden die Objekte dann lokalen Variablen zugewiesen damit man später in seinen Methoden darauf zugreifen kann.

Am Ende muss man nur noch den Namespace der Datei anpassen namespace foo\bar\event;

Die komplette Datei /event/listener.php
<?php

/**
*
* @package phpBB Extension - bar
* @copyright (c) 2015 foo (https://example.com)
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/

namespace foo\bar\event;

/**
* @ignore
*/
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* Event listener
*/
class listener implements EventSubscriberInterface
{
    public static function getSubscribedEvents()
    {
        return array(
            'core.page_header'        => 'page_header',
        );
    }
    
    /** @var \phpbb\controller\helper */
    protected $helper;
	
    /** @var \phpbb\template\template */
    protected $template;

    /** @var  \phpbb\user */
    protected $user;

    /**
    * Constructor
    *
    * @param \phpbb\controller\helper			$helper		Controller helper object
    * @param \phpbb\template           			$template          Template object
    * @param \phpbb\user                  			$user                User object
    */
    public function __construct(\phpbb\controller\helper $helper, \phpbb\template\template $template, \phpbb\user $user)
    {
        $this->helper = $helper;
        $this->template = $template;
        $this->user = $user;
    }

    public function page_header($event)
    {
	$this->user->add_lang_ext('foo/bar', 'link');
	$this->template->assign_vars(array(
		'U_MY_LINK'	=> $this->helper->route('foo_bar_index', array()),
	));
    }
}

Services an den Listener weiterleiten

Damit die Objekte und Variablen die wir im Konstruktor des Listeners abfragen auch übergeben werden braucht man eine Datei mit dem Namen services.yml im Ordner config innerhalb seiner Extension. Falls die Datei schon durch einen Controler vorhanden ist kann einfach die vorhandene Datei erweitert werden. Dabei muss services: nicht erneut eingefügt werden da es ja schon vorhanden ist.
Eingerückt durch 4 Leerzeichen schreibt man den Namen seiner Extension gefolgt von dem Namen der Datei für den Listener getrennt durch Punkte (foo.bar.listener). Darunter mit 8 Leerzeichen eingerückt schreibt man den Namespace der Listener Klasse (class: foo\bar\event\listener).
Jetzt kann man unter arguments: alle Objekte und Variablen die man in seiner Listener Klasse verwendet auflisten. Wichtig ist dabei, dass die Reihenfolge genau mit der Reihenfolge im Konstruktor der Klasse übereinstimmt.

Die komplette Datei /config/services.yml
services:
    foo.bar.listener:
        class: foo\bar\event\listener
        arguments:
            - @controller.helper
            - @template
            - @user
        tags:
            - { name: event.listener }

In der Datei darf man keine Tabs verwenden, alle Einrückungen müssen durch Leerzeichen gemacht werden.

Die Sprachdatei

Damit der Text des Links angegeben werden kann benötigt man eine Sprachdatei. Die Datei legt man unter language/de/link.php an. Als Dateinamen verwendet man den Namen den man in der Listener Klasse angegeben hat, hier also link. Statt de kann man natürlich auch jedes andere Sprachkürzel verwenden. Wenn man mehrere Sprachen anbieten will muss man die Datei einfach mehrmals in den Ordnern mit dem jeweiligen Sprachkürzel anlegen.

Die komplette Datei /language/de/link.php
<?php
/**
*
* @package phpBB Extension - bar
* @copyright (c) 2015 foo (https://example.com)
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/

if (!defined('IN_PHPBB'))
{
	exit;
}

if (empty($lang) || !is_array($lang))
{
	$lang = array();
}
// DEVELOPERS PLEASE NOTE
//
// All language files should use UTF-8 as their encoding and the files must not contain a BOM.
//
// Placeholders can now contain order information, e.g. instead of
// 'Page %s of %s' you can (and should) write 'Page %1$s of %2$s', this allows
// translators to re-order the output of data while ensuring it remains correct
//
// You do not need this where single placeholders are used, e.g. 'Message %d' is fine
// equally where a string contains only two placeholders which are used to wrap text
// in a url you again do not need to specify an order e.g., 'Click %sHERE%s' is fine
//
// Some characters you may want to copy&paste:
// ’ » “ ” …
//
$lang = array_merge($lang, array(
	'MY_LINK'			=> 'Mein toller Link',
));

Das Template Event

Damit der Link auch im Template angezeigt wird benötigt man ein Template Event, eine Liste aller verfügbaren Template Events gibt es im phpBB Wiki. Für einen Link in der Navigation im Header bietet sich das Event overall_header_navigation_append an.
Man legt also unter styles/prosilver/template/event innerhalb seiner Extension die Datei overall_header_navigation_append.html an und schreibt dort den HTML Code für seinen Link rein.

Die komplette Datei /styles/prosilver/template/event/overall_header_navigation_append.html
<li class="small-icon no-bulletin"><a href="{U_MY_LINK}">{L_MY_LINK}</a></li>

Im a-Tag steht die Template Variable für den Link, so wie in der Listener Klasse angegeben (U_MY_LINK). Als Linktext wird die Sprachvariable die man in der Sprachdatei definiert hat verwendet. Damit phpBB die Variable als Sprachvariable erkennt muss ein L_ davor geschrieben werden.