DEV Community

Yoichi Dan
Yoichi Dan

Posted on

mautic の plugin の reload 処理をみる 02

ReloadFacade#reloadPlugins

reload の実態となるメソッドを見ていきます。

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);
    }
Enter fullscreen mode Exit fullscreen mode

PluginModel

以降では内部を理解するために細かく実行しているが、 PluginModel 自体をpsysh で取得しておけば自由に試せる。

>>> $pluginModel = $container->get('mautic.plugin.model.plugin')
Enter fullscreen mode Exit fullscreen mode

pluginModel->getAllPluginsConfig();

ここは内部的には BundleHelper を見ているため、一つ前の記事で見た通りで %mautic.plugin.bundles% のパラメータを参照している。

pluginModel->getPluginsMetadata()

PluginModel は以下のようになっている。

public function getPluginsMetadata()
{
    $allMetadata     = $this->em->getMetadataFactory()->getAllMetadata();
    $pluginsMetadata = [];

    foreach ($allMetadata as $meta) {
        $namespace = $meta->namespace;

        if (false !== strpos($namespace, 'MauticPlugin')) {
            $bundleName = preg_replace('/\\\Entity$/', '', $namespace);
            if (!isset($pluginsMetadata[$bundleName])) {
                $pluginsMetadata[$bundleName] = [];
            }
            $pluginsMetadata[$bundleName][$meta->getName()] = $meta;
        }
    }

    return $pluginsMetadata;
}
Enter fullscreen mode Exit fullscreen mode

最初に取得している Metadata は以下で psysh で取得できる。

>>> $em = $container->get('doctrine')->getManager();
>>> $em->getMetadataFactory()->getAllMetadata()
   [
     Doctrine\ORM\Mapping\ClassMetadata {#5392
       +name: "Mautic\PluginBundle\Entity\IntegrationEntity",
       +namespace: "Mautic\PluginBundle\Entity",
       +rootEntityName: "Mautic\PluginBundle\Entity\IntegrationEntity",
       +customGeneratorDefinition: null,
       +customRepositoryClassName: "Mautic\PluginBundle\Entity\IntegrationEntityRepository",
       +isMappedSuperclass: false,
       +isEmbeddedClass: false,
Enter fullscreen mode Exit fullscreen mode

上記の通りで、Doctrine\ORM\Mapping\ClassMetadata の一覧が大量に取得できる。( count したら 101 ありました)

取得した Metadata から namespace に MauticPlugin が入っているものだけを取得し、末尾の \Entity を除外したものを集めている。

pluginModel->getInstalledPlugins()

class PluginModel extends FormModel {
    public function getInstalledPlugins()
    {
        return $this->getEntities(
            [
                'index' => 'bundle',
            ]
        );
    }

    public function getRepository()
    {
        return $this->em->getRepository('MauticPluginBundle:Plugin');
    }

// FormModel の親クラスが AbstractCommonModel
abstract class AbstractCommonModel {
    public function getEntities(array $args = [])
    {
        //set the translator
        $repo = $this->getRepository();

        if ($repo instanceof CommonRepository) {
            $repo->setTranslator($this->translator);
            $repo->setCurrentUser($this->userHelper->getUser());

            return $repo->getEntities($args);
        }

        return [];
    }
Enter fullscreen mode Exit fullscreen mode

getEntities 内で呼ばれる getRepositoryPluginModel#getRepository なので、 PluginBundle\Entity\PluginRepository が使われる。これは CommonRepository を継承しているので、instanceof も問題ない。

実行すると以下のように取得できる。

>>> $em->getRepository('MauticPluginBundle:Plugin')->getEntities(['index' => 'bundle',]);
=> [
     "MauticCitrixBundle" => Mautic\PluginBundle\Entity\Plugin {#4605},
     "MauticClearbitBundle" => Mautic\PluginBundle\Entity\Plugin {#4653},
     "MauticCloudStorageBundle" => Mautic\PluginBundle\Entity\Plugin {#4634},
     "MauticCrmBundle" => Mautic\PluginBundle\Entity\Plugin {#4662},
     "MauticEmailMarketingBundle" => Mautic\PluginBundle\Entity\Plugin {#4657},
     "MauticFullContactBundle" => Mautic\PluginBundle\Entity\Plugin {#4603},
     "MauticGmailBundle" => Mautic\PluginBundle\Entity\Plugin {#4593},
     "GrapesJsBuilderBundle" => Mautic\PluginBundle\Entity\Plugin {#4621},
     "HelloWorldBundle" => Mautic\PluginBundle\Entity\Plugin {#4573},
     "MauticFocusBundle" => Mautic\PluginBundle\Entity\Plugin {#4613},
     "MauticTagManagerBundle" => Mautic\PluginBundle\Entity\Plugin {#4616},
     "MauticOutlookBundle" => Mautic\PluginBundle\Entity\Plugin {#4665},
     "MauticSocialBundle" => Mautic\PluginBundle\Entity\Plugin {#4681},
     "MauticZapierBundle" => Mautic\PluginBundle\Entity\Plugin {#4678},
   ]
>>>
Enter fullscreen mode Exit fullscreen mode

getAllPluginsConfig と getInstalledPlugins

名前の通りではあるが、getAllPluginsConfig はあくまで設定情報として取得しているものであって、実際に mautic にインストールされているかは分からないものも含まれている。

逆に getInstalledPlugins はインストールされているかを DB から抽出している。

pluginModel->getInstalledPluginTables

public function getInstalledPluginTables(array $pluginsMetadata)
{
    $currentSchema          = $this->em->getConnection()->getSchemaManager()->createSchema();
    $installedPluginsTables = [];

    foreach ($pluginsMetadata as $bundleName => $pluginMetadata) {
        foreach ($pluginMetadata as $meta) {
            $table = $meta->getTableName();

            if (!isset($installedPluginsTables[$bundleName])) {
                $installedPluginsTables[$bundleName] = [];
            }

            if ($currentSchema->hasTable($table)) {
                $installedPluginsTables[$bundleName][] = $currentSchema->getTable($table);
            }
        }
    }

    return $installedPluginsTables;
}
Enter fullscreen mode Exit fullscreen mode

$pluginsMetadata はすでに取得しているが、一つ例をあげておくと以下のようになる。

>>> $pluginModel->getPluginsMetadata();
>>> array_key_first($pluginMetadata)
=> "MauticPlugin\HelloWorldBundle"
>>> $metadata = $pluginMetadata["MauticPlugin\HelloWorldBundle"]
=> [
     "MauticPlugin\HelloWorldBundle\Entity\World" => Doctrine\ORM\Mapping\ClassMetadata {#5750
       +name: "MauticPlugin\HelloWorldBundle\Entity\World",
       +namespace: "MauticPlugin\HelloWorldBundle\Entity",
...
>>> array_key_first($metadata)
=> "MauticPlugin\HelloWorldBundle\Entity\World"
>>> $meta = $metadata["MauticPlugin\HelloWorldBundle\Entity\World"]
=> Doctrine\ORM\Mapping\ClassMetadata {#5658
     +name: "MauticPlugin\HelloWorldBundle\Entity\World",
     +namespace: "MauticPlugin\HelloWorldBundle\Entity",
     +rootEntityName: "MauticPlugin\HelloWorldBundle\Entity\World",
...
>>> $meta->getTableName();
=> "hello_world"
Enter fullscreen mode Exit fullscreen mode

後は $currentSchema に入っている情報と突き合わせて、テーブル情報を収集している。

インストール直後とかだとそれほど数は多くない。 (HelloWorldBundle は追加で入れているもの)
テーブルを複数使っているプラグインがあることも分かる。

>>> $installedPluginTables = $pluginModel->getInstalledPluginTables($pluginMetadata)
=> [
     "MauticPlugin\HelloWorldBundle" => [
       Doctrine\DBAL\Schema\Table {#11257},
     ],
     "MauticPlugin\MauticTagManagerBundle" => [
       Doctrine\DBAL\Schema\Table {#11724},
     ],
     "MauticPlugin\MauticCitrixBundle" => [
       Doctrine\DBAL\Schema\Table {#12562},
     ],
     "MauticPlugin\MauticSocialBundle" => [
       Doctrine\DBAL\Schema\Table {#12089},
       Doctrine\DBAL\Schema\Table {#12032},
       Doctrine\DBAL\Schema\Table {#13314},
       Doctrine\DBAL\Schema\Table {#13260},
       Doctrine\DBAL\Schema\Table {#12066},
     ],
     "MauticPlugin\MauticCrmBundle" => [
       Doctrine\DBAL\Schema\Table {#12576},
     ],
     "MauticPlugin\GrapesJsBuilderBundle" => [
       Doctrine\DBAL\Schema\Table {#6726},
     ],
     "MauticPlugin\MauticFocusBundle" => [
       Doctrine\DBAL\Schema\Table {#11069},
       Doctrine\DBAL\Schema\Table {#11101},
     ],
   ]
Enter fullscreen mode Exit fullscreen mode

pluginModel->createPluginSchemas

PluginModel はこれが最後。

public function createPluginSchemas(array $installedPluginsTables)
{
    $installedPluginsSchemas = [];
    foreach ($installedPluginsTables as $bundleName => $tables) {
        $installedPluginsSchemas[$bundleName] = new Schema($tables);
    }

    return $installedPluginsSchemas;
}
Enter fullscreen mode Exit fullscreen mode

メソッド名が create になっているが、このメソッドで DB にデータを作成する訳ではない。
単純に $installedPluginsTables のマッピングを変えているだけで値を Schema のオブジェクトに変更している。

ここまでで PluginModel を使ったプラグイン情報の収集部分を見た。
次回は ReloadHelper でのプラグインの更新処理を確認していく。

Top comments (0)