# Plugin development

This section shows you how to develop plugins which can be used in Voyager.

## Setting up your development environment

This chapter shows you the easiest way to develop your plugin.

Choose one of the [templates](#templates) we provide and create a repository from it. Open `composer.json` and change `name` to whatever you want.\
Next, push your changes to Github.\
Now you are ready to require your package to your base Laravel installation.\
Go to your Laravel installation, open `composer.json` and add the following:

```json
"minimum-stability": "dev",
"require": {
    "your/name": "*"
},
"repositories": [
    {
        "type": "path",
        "url": "path/to/your/plugin"
    }
]
```

`your/name` is the name you used in the `composer.json` file of your plugin.\
Next run `composer update` in your laravel installation.\
After that you are able to simply reload your page and immediately see any changes you made.

## Basics

Each plugin requires some steps to be recognized by Voyager.

**Service Provider**\
Registers the plugin(s):

```php
<?php

namespace My\Plugin;

use Illuminate\Support\ServiceProvider;
use Voyager\Admin\Manager\Plugins as PluginManager;

class MyPluginServiceProvider extends ServiceProvider
{
    public function boot(PluginManager $pluginmanager)
    {
        $pluginmanager->addPlugin(\My\Plugin\MyPlugin::class);
    }
}
```

::: info One package can provide multiple plugins.\
For example, a plugin could provide multiple themes or even different types of plugins like authorization and authentication.\
All plugins can be enabled/disabled independently. Make sure they don't depend on each other! :::

**Plugin class**

The plugin class represents the actual plugin and its methods:

```php
<?php

namespace My\Plugin;

use Voyager\Admin\Contracts\Plugins\GenericPlugin;

class MyPlugin implements GenericPlugin
{
    public $name = 'My plugin';
    public $description = 'This is my plugin!';
    public $repository = 'my/plugin';
    public $website = 'https://github.com/my/plugin';

    // Methods depending on your plugin-type, providers and filters.

    public function __construct() {
        // Optionally provide a README file that can be displayed in the plugin UI
        $this->readme = realpath(dirname(__DIR__, 1).'/README.md');
    }
}
```

**composer.json**

To be able to find your plugin through Voyagers UI you have to provide the tag `voyager2-plugin` in your composer.json file:

```json
{
    "keywords": ["voyager2-plugin"],
}
```

## Types

Plugins can be of various types:

| **Type**       | **Class**                                                                                                                                                 | **Description**                                                            |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Authentication | [\Voyager\Admin\Contracts\Plugins\AuthenticationPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/AuthenticationPlugin.php) | Handles authentication of users inside Voyager (login, password reset etc) |
| Authorization  | [\Voyager\Admin\Contracts\Plugins\AuthorizationPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/AuthorizationPlugin.php)   | Handles permissions for users and actions                                  |
| Formfield      | [\Voyager\Admin\Contracts\Plugins\FormfieldPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/FormfieldPlugin.php)           | Provides one or many formfields                                            |
| Generic        | [\Voyager\Admin\Contracts\Plugins\GenericPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/GenericPlugin.php)               | A plugin that doesn't fit the other types                                  |
| Theme          | [\Voyager\Admin\Contracts\Plugins\ThemePlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/ThemePlugin.php)                   | Provides one or many themes                                                |

Each type has individual methods you have to implement in your plugin class.\
Check the Github link to find out more about those methods.

::: info Because the plugin type classes are interfaces you can implement multiple types in one plugin! :::

## Providers

Voyager uses provider traits to provide various things. Those are:

| **Type**       | **Class**                                                                                                                                                 | **Description**                                                            |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Authentication | [\Voyager\Admin\Contracts\Plugins\AuthenticationPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/AuthenticationPlugin.php) | Handles authentication of users inside Voyager (login, password reset etc) |
| Authorization  | [\Voyager\Admin\Contracts\Plugins\AuthorizationPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/AuthorizationPlugin.php)   | Handles permissions for users and actions                                  |
| Formfield      | [\Voyager\Admin\Contracts\Plugins\FormfieldPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/FormfieldPlugin.php)           | Provides one or many formfields                                            |
| Generic        | [\Voyager\Admin\Contracts\Plugins\GenericPlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/GenericPlugin.php)               | A plugin that doesn't fit the other types                                  |
| Theme          | [\Voyager\Admin\Contracts\Plugins\ThemePlugin](https://github.com/voyager-admin/voyager/blob/2.x/src/Contracts/Plugins/ThemePlugin.php)                   | Provides one or many themes                                                |

## Filter

Filter allow a plugin to filter and manipulate various data displayed in Voyager:

| **Type**  | **Class**                                                 | **Description**                              | **Documentation**                                                                            |
| --------- | --------------------------------------------------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------- |
| Layouts   | Voyager\Admin\Contracts\Plugins\Features\Filter\Layouts   | Filter the layouts for a given BREAD         | [Here](https://github.com/voyager-admin/voyager/blob/2.x/plugins/filter/README.md#layouts)   |
| MenuItems | Voyager\Admin\Contracts\Plugins\Features\Filter\MenuItems | Filter menu-items for the main and user-menu | [Here](https://github.com/voyager-admin/voyager/blob/2.x/plugins/filter/README.md#menuitems) |
| Widgets   | Voyager\Admin\Contracts\Plugins\Features\Filter\Widgets   | Filter widgets shown on the dashboard        | [Here](https://github.com/voyager-admin/voyager/blob/2.x/plugins/filter/README.md#widgets)   |
| Media     | Voyager\Admin\Contracts\Plugins\Features\Filter\Media     | Filter media files in the current directory  | [Here](https://github.com/voyager-admin/voyager/blob/2.x/plugins/filter/README.md#media)     |

## Templates

We created templates for all types of plugins on Github to get you started easily:

| Type           | Link                                                        |
| -------------- | ----------------------------------------------------------- |
| Authentication | https://github.com/voyager-admin/authentication-boilerplate |
| Authorization  | https://github.com/voyager-admin/authorization-boilerplate  |
| Formfield      | https://github.com/voyager-admin/formfield-boilerplate      |
| Generic        | https://github.com/voyager-admin/generic-boilerplate        |
| Theme          | https://github.com/voyager-admin/theme-boilerplate          |

## Readme

You can specify a markdown file that will be shown in a modal on the plugins page.\
To do so, provide an absolute path `$readme` pointing to your markdown file.\
Whenever you use image in this file, you have to provide a URL `$readme_assets_path` pointing where the browser can access them.\
For example:

```php
use Voyager\Admin\Contracts\Plugins\GenericPlugin;

class MyPlugin implements GenericPlugin
{
    public function __construct()
    {
        $this->readme = realpath(dirname(__DIR__, 1).'/README.md');
        $this->readme_assets_path = 'https://raw.githubusercontent.com/me/my-plugin/branch/';
    }
}
```
