mautic の plugin の reload 処理をみる 01
Published: 2021-07-08 23:08:15

![2021-07-09_07h08_18](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vrca3xy3trkuxpajkla2.png)

まず、上記の処理を追っていく。
```html
<div class="std-toolbar btn-group">
    <a data-toggle="ajax" href="/s/plugins/reload" class="btn btn-default">
        <span
            data-toggle="tooltip" title="" data-placement="left"
            data-original-title="Upload the plugin via FTP or some other protocol to the plugins directory then click this button to install/upgrade.">
            <i class="fa fa-cubes"></i> <span class="hidden-xs hidden-sm">Install/Upgrade Plugins</span>
        </span>
    </a>
</div>
```
ブラウザの開発者ツールを見ると上記のようになっていた。 `/s/plugins/reload` が紐付けられているため、このボタンの機能は plugin の reload 機能だと推測できる。

`app/bundles/PluginBundle/Config/config.php` の routes 定義にも以下が存在した。
```php
'mautic_plugin_reload' => [
    'path'       => '/plugins/reload',
    'controller' => 'MauticPluginBundle:Plugin:reload',
],
```

`reload` のアクションはそれほど大きくない。
https://github.com/mautic/mautic/blob/7d4b436891b8ca84b34d2b0f5856bbff2a721c3a/app/bundles/PluginBundle/Controller/PluginController.php#L418-L444

```php
/**
* Scans the addon bundles directly and loads bundles which are not registered to the database.
*
* @return JsonResponse
*/
public function reloadAction()
{
   if (!$this->get('mautic.security')->isGranted('plugin:plugins:manage')) {
       return $this->accessDenied();
   }

   $this->addFlash(
       $this->get('mautic.plugin.facade.reload')->reloadPlugins()
   );

   $viewParameters = [
       'page' => $this->get('session')->get('mautic.plugin.page'),
   ];

   // Refresh the index contents
   return $this->postActionRedirect(
       [
           略
       ]
   );
}
```

### mautic.plugin.facade.reload はなんだろう
DI コンテナから取得しているようなので psysh で確認する

```bash
$ bin/console psysh --env=dev
>>> $container->get('mautic.plugin.facade.reload')
=> Mautic\PluginBundle\Facade\ReloadFacade {#4588}
```

## ReloadFacade.php
https://github.com/mautic/mautic/blob/7d4b436891b8ca84b34d2b0f5856bbff2a721c3a/app/bundles/PluginBundle/Facade/ReloadFacade.php
```php
class ReloadFacade
{
    private $pluginModel;
    private $reloadHelper;
    private $translator;

    public function __construct(PluginModel $pluginModel, ReloadHelper $reloadHelper, TranslatorInterface $translator)
    {
        $this->pluginModel  = $pluginModel;
        $this->reloadHelper = $reloadHelper;
        $this->translator   = $translator;
    }

    /**
     * This method finds all plguins that needs to be enabled, disabled, installed and updated
     * and do all those actions.
     *
     * Returns humanly understandable message about its doings.
     *
     * @return string
     */
    public function reloadPlugins()
    {
        $plugins                 = $this->pluginModel->getAllPluginsConfig();
        $pluginMetadata          = $this->pluginModel->getPluginsMetadata();
        $installedPlugins        = $this->pluginModel->getInstalledPlugins();
        $installedPluginTables   = $this->pluginModel->getInstalledPluginTables($pluginMetadata);
        $installedPluginsSchemas = $this->pluginModel->createPluginSchemas($installedPluginTables);
        $disabledPlugins         = $this->reloadHelper->disableMissingPlugins($plugins, $installedPlugins);
        $enabledPlugins          = $this->reloadHelper->enableFoundPlugins($plugins, $installedPlugins);
        $updatedPlugins          = $this->reloadHelper->updatePlugins($plugins, $installedPlugins, $pluginMetadata, $installedPluginsSchemas);
        $installedPlugins        = $this->reloadHelper->installPlugins($plugins, $installedPlugins, $pluginMetadata, $installedPluginsSchemas);
        $persist                 = array_values($disabledPlugins + $enabledPlugins + $updatedPlugins + $installedPlugins);

        if (!empty($persist)) {
            $this->pluginModel->saveEntities($persist);
        }

        // Alert the user to the number of additions
        return $this->translator->trans(
            'mautic.plugin.notice.reloaded',
            [
                '%added%'    => count($installedPlugins),
                '%disabled%' => count($disabledPlugins),
                '%updated%'  => count($updatedPlugins),
            ],
            'flashes'
        );
    }
}
```
多くの処理が移譲されているので、このクラス自体は大きくない。

この処理は、私がやったことがあるユースケースでは、新しくプラグインを追加して、それを読み込むために、 cache を clear してから、このボタンを押すというものだ。
今回はその観点を軸にみていく。

### PluginModel

まず、`PluginModel` の登場が多いのでこれが何かみていく。
[MODELS - Mautic Developer Documentation](https://developer.mautic.org/#models)

上記の資料に Models に関する解説があり、簡単には Controller と View の間でのデータ処理を受け持つとなっている。これは、単に MVC の Model と考えていいのだろうか？ まだ Symfony の理解が浅く、Entity との関わり方などが頭で整理できていない。

`config.php` を見ると以下の定義がある。
```php
'models' => [
    'mautic.plugin.model.plugin' => [
        'class'     => \Mautic\PluginBundle\Model\PluginModel::class,
        'arguments' => [
            'mautic.lead.model.field',
            'mautic.helper.core_parameters',
            'mautic.helper.bundle',
        ],
    ],

    'mautic.plugin.model.integration_entity' => [
        'class' => Mautic\PluginBundle\Model\IntegrationEntityModel::class,
    ],
],
```

### mautic.helper.bundle / BundleHelper
`PluginModel` の constructor に `BundleHelper` が指定されているが、これを見ておく。

これは `app/bundles/CoreBundle/Helper/BundleHelper.php` が実態で `CoreBundle` の持ち物になっている。`PluginBundle` は別途存在するが、 `CoreBundle` はプラグインに関してもその全体を把握しているということのようだ。

```php
class BundleHelper
{
    private $coreBundles   = [];
    private $pluginBundles = [];
    private $allBundles    = [];

    /**
     * BundleHelper constructor.
     */
    public function __construct(array $coreBundles, array $pluginBundles)
    {
        $this->coreBundles   = $coreBundles;
        $this->pluginBundles = $pluginBundles;
        $this->allBundles    = array_merge($coreBundles, $pluginBundles);
    }
```

では、この constructor の 2 つの引数を確認する。
`CoreBundle` の `config.php` を確認すると以下のようになっている。

```php
'mautic.helper.bundle' => [
    'class'     => 'Mautic\CoreBundle\Helper\BundleHelper',
    'arguments' => [
        '%mautic.bundles%',
        '%mautic.plugin.bundles%',
    ],
],
```

内容を調べてみると以下のようになっている。
```bash
$ bin/console debug:container --parameter=mautic.bundles
 ---------------- -----------------------------------------------------------------
  Parameter        Value
 ---------------- -----------------------------------------------------------------
  mautic.bundles   {"MauticCoreBundle":{"isPlugin":false,"base":"Core","bundle"...
 ---------------- -----------------------------------------------------------------
 
 $ bin/console debug:container --parameter=mautic.plugin.bundles
 ----------------------- -----------------------------------------------------------------
  Parameter               Value
 ----------------------- -----------------------------------------------------------------
  mautic.plugin.bundles   {"MauticOutlookBundle":{"isPlugin":true,"base":"MauticOutloo...
 ----------------------- -----------------------------------------------------------------
```

psysh で `$container->getParameter('mautic.plugin.bundles')` をすれば、より詳細な情報も得られます。

このパラメータがセットされる箇所は、軽く検索した感じは `app/Config/config.php` の以下しかなかったので、ここで設定されたら使われ続けるよう。
https://github.com/mautic/mautic/blob/7d4b436891b8ca84b34d2b0f5856bbff2a721c3a/app/config/config.php#L28-L29

次は `ReloadFacade.php` に戻って、 `reloadPlugins()` メソッドから見ていきたいと思います。