  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 `app/Plugins/HelloWorld/Views/settings.twig` maps to '`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 App\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/5.5/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 App\Plugins\HelloWorld\Listeners;

class FooterHook
{
    /**
     * Inject data into the view.
     *
     * @return void
     */
    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 integration we only want to modify the reply options if the user is currently viewing a Twitter channel ticket.

```

    // 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('Twitter::ticket.forms.reply_options')->render();
        });
    });

```

### Available Hooks

#### Frontend

   Event Name Area    **General**   `frontend.head` Inside <head> Add any necessary JS/CSS here that needs to be loaded before the rest of the page loads.   `frontend.body_start` Below <body>    `frontend.header_start` Start of header    `frontend.header_end` End of header    `frontend.wrapper_start` Start of main area    `frontend.content_start` Start of left content area This includes the main title and breadcrumb.   `frontend.content_inner_start` Start of left content inner area This is the section within the white box.   `frontend.content_inner_end` End of left content inner area This is the section within the white box.   `frontend.content_end` End of left content area This includes the main title and breadcrumb.   `frontend.sidebar_start` Start of sidebar    `frontend.navigation` End of navigation The navigation is used both in the sidebar and also in mobile view, use the same HTML format as existing links for it to work in both cases.   `frontend.sidebar_end` End of sidebar    `frontend.wrapper_end` End of main area    `frontend.footer` Page footer    `frontend.body_end` Above </body> Add any JS/CSS 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 JS/CSS here that needs to be loaded before the rest of the page loads.   `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 JS/CSS 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 here.   `operator.ticket_tab_content` Ticket view tab content Add a tab (the tab content) to the ticket view here.   `operator.ticket_reply_options` Ticket view reply options Add additional reply options here, will show at top of list.  ## 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 integration overrides the ticket message view with a Twitter specific message view which has additional functionality such as retweet and like buttons:

```

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

```

---

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