  You're browsing the documentation for an old version of SupportPal. Consider upgrading to the [latest version](https://docs.supportpal.com/current/Plugin+Development+Extending+Templates). 

# Plugin Development: Extending Templates

#### Previous Section: [Model Events](Plugin+Development+Model+Events)

---

Plugins give you the option to inject data in to and completely override existing templates.

Example cases where this is useful:

- Showing user's products/services as options in a custom field (our WHMCS Information plugin) - uses a [View Composer](#ModifyingViewData)
- Showing user's billing details in the ticket view (our WHMCS Information plugin) - uses a [View Hook](#ViewHooks)
- Showing social media details about the user (our Twitter and Facebook channels) - makes use of [Overriding Views](#OverridingViews)

## Understanding View Names

View names are constructed based on the folder structure where the directory separator (/) is replaced by a period (.).

For example, the following template file path `resources/templates/operator/integration/ticket/ticket.twig` maps to '`operator.integration.ticket.ticket`'. The `resources/templates` is stripped away because this is the base path to the templates directory.

In the subsequent sections of this page, wildcards can be used for path components that we don't know. For example, '`operator.*.ticket.ticket`' would cover the ticket view in all templates.

The above naming convention applies to views stored under the `resources/templates/` folder. For any views within a plugin's `Views` folder, the view name is prepended by the plugin namespace. For example the file `addons/Plugins/HelloWorld/Views/settings.twig` maps to '`Plugins#HelloWorld::settings`'.

## Modifying View Data

It's possible to access and modifying existing view data (variables) using view composers. View composers are callbacks that are called just before the view is rendered and shown to the user. They can be define using closures or classes, as demonstrated below:

```

    // Using class based composers...
    \View::composer('operator.default.ticket.ticket', 'App\Plugin\HelloWorld\Listeners\TicketComposer');

    // Using Closure based composers...
    \View::composer('operator.default.ticket.ticket', function ($view) {
        // Fetch ticket model.
        $ticket = $view->ticket;

        ...
    });

```

The class based composer should be defined as below - the `compose()` function will be called automatically:

Listeners/TicketComposer.php

```

<?php
namespace Addons\Plugins\HelloWorld\Listeners;

use Illuminate\View\View;

class TicketComposer
{
    /**
     * Bind data to the view.
     *
     * @param  View  $view
     * @return void
     */
    public function compose(View $view)
    {
        // Fetch ticket model.
        $ticket = $view->ticket;

        ...
    }
}

```

For more information please read: <https://laravel.com/docs/6.x/views#view-composers>.

## View Hooks

A view hook is an event that is fired when that line in the template file is being rendered. We can use event listeners to inject HTML into the view without having to actually modify the template itself.

These hooks are declared with the `View.fireHook` function call in our default template files. A number of hook points have been provided by default, as listed below, but it's also possible to define your own in custom templates or your own plugin template files if needed.

```

    {{ View.fireHook('frontend.footer') }}

```

We then just need to listen for the event and return *escaped* HTML. The example below will include the HTML in the footer of the template on every frontend page.

```

    // Using class based hooks...
    \View::hook('frontend.footer', 'App\Plugin\HelloWorld\Listeners\FooterHook');

    // Using Closure based hooks...
    \View::hook('frontend.footer', function () {
        return '<script>...</script>';
    });

```

The class based hook should be defined as below - the `hook()` function will be called automatically:

Listeners/FooterHook.php

```

<?php
namespace Addons\Plugins\HelloWorld\Listeners;

class FooterHook
{
    /**
     * Inject data into the view.
     *
     * @return string
     */
    public function hook()
    {
        return '<script>...</script>';
    }
}

```

  Any HTML you return will be displayed directly without any escaping. If you are handling user submitted content, please ensure to escape it before returning it. The `e` function is a shorthand version of running `htmlspecialchars`. 

### Combining with View Composers

Combining template hooks with view composers allows us to access view data and create context aware template hooks. For example, in our Twitter channel we only want to modify the reply options if the user is currently viewing a Twitter channel ticket. Note that channels use a `Channels#` prefix for the namespace rather than plugins which are `Plugins#`.

```

    // In operator ticket view only
    \View::composer('operator.*.ticket.ticket', function ($view) {
        if ($view->ticket->channel_id != 5) {
            return;
        }

        \View::hook('operator.ticket_reply_options', function () {
            return \TemplateView::other('Channels#Twitter::ticket.forms.reply_options')->render();
        });
    });

```

### Available Hooks

#### Frontend

   Event Name Area    **General**   `frontend.head` Inside <head> Add any necessary CSS and other assets here that needs to be loaded before the rest of the page loads. JS and jQuery should be added in `frontend.body_end`.   `frontend.body_start` Below <body>    `frontend.header_start` Start of header    `frontend.navigation` End of navigation The navigation is the links shown under the user's name when logged in or the full navigation in mobile view. Use the same HTML format as existing links for it to work in both cases.   `frontend.header_end` End of header    `frontend.wrapper_start` Start of main area This includes the main title and breadcrumb.   `frontend.content_start` Start of main content area    `frontend.content_inner_start` Start of main content inner area This is the section within the white box.   `frontend.content_inner_end` End of main content inner area This is the section within the white box.   `frontend.content_end` End of main content area    `frontend.sidebar_start` Start of sidebar The sidebar is only shown on certain pages.   `frontend.sidebar_end` End of sidebar The sidebar is only shown on certain pages.   `frontend.wrapper_end` End of main area    `frontend.footer` Page footer    `frontend.body_end` Above </body> Add any CSS, JS, jQuery and other assets here that can be ran after the rest of the page loads.   **Dashboard**   `frontend.dashboard` Help desk section links Add custom frontend sections here.  #### Operator

   Event Name Area    **General**   `operator.head` Inside <head> Add any necessary CSS and other assets here that needs to be loaded before the rest of the page loads. JS and jQuery should be added in `operator.body_end`.   `operator.body_start` Below <body>    `operator.header_start` Start of header    `operator.navigation` Header navigation The navigation is used both in the header and also in mobile view, use the same HTML format as existing links/dropdowns for it to work in both cases.   `operator.header_end` End of header    `operator.wrapper_start` Start of main area This includes the sidebar if present.   `operator.content_start` Start of right content area This starts outside the padded inner content area.   `operator.content_inner_start` Start of left content inner area    `operator.content_inner_end` End of left content inner area    `operator.content_end` End of left content area This ends outside the padded inner content area.   `operator.wrapper_end` End of main area This includes the sidebar if present.   `operator.footer` Page footer    `operator.body_end` Above </body> Add any CSS, JS, jQuery and other assets here that can be ran after the rest of the page loads.   `operator.sidebar_start` Start of sidebar Only visible on certain pages.   `operator.sidebar_end` End of sidebar Only visible on certain pages.   **Ticket**   `operator.ticket_messages` Ticket view messages Above or below the add reply form depending on the order selected in personal or system settings.   `operator.ticket_tab` Ticket view tab Add a tab (the link) to the ticket view.   `operator.ticket_tab_content` Ticket view tab content Add a tab (the tab content) to the ticket view.   `operator.ticket_reply_options` Ticket view reply options Add additional reply options here, will show at top of list.   **User**   `operator.user_tab` User tab Add a tab (the link) to the user pages, such as user profile.   `operator.user_tab_content` User tab content Add a tab (the tab content) to the user pages, such as user profile.  ## Overriding Views

Overriding views will replace the current view with the named view and render that instead. This is achieved using view composer events and simply overriding the path to the template using the `setPath` function on the `View` object. The path can either be an absolute path or the name of the view.

In the example below, our Twitter chnnale overrides the ticket message view with a Twitter specific message view which has additional functionality such as retweet and like buttons. Note that channels use a `Channels#` prefix for the namespace rather than plugins which are `Plugins#`.

```

    \View::composer('operator.default.ticket.message', function ($view) {
        $view->setPath('Channels#Twitter::ticket.message');
    });

```

---

#### Next Section: [Scheduled Tasks](Plugin+Development+Scheduled+Tasks)