EC-CUBE 4系のプラグイン開発について その1(管理画面側まで)

Date:

Share post:

以前から作成したいと考えていたのですが、今回ある程度形にできたので、今後の案件で開発する際の手順として書いておこうと思った次第です。

今回自分が作成したプラグインは「Cloudflare Turnstileウィジェット」プラグインです。

Cloudflare Turnstileは、CAPTCHA認証(よく知られるものにGoogle reCAPTCHAがあります。)の代替ツールになります。Google reCAPTCHAと比較した場合に以下のようなメリットが挙げられます。

  • 無料で10個のウィジェットまで無制限で使用できる(Google reCAPTCHAは無料での月間評価可能件数が100万件から10,000件に減少してしまいました。)
  • 非対話型で、ユーザーが行動(テキスト認証や画像認証)する必要がないので煩わしくない
  • 比較的実装が容易

自分が今まで携わった案件ではGoogle reCAPTCHAを使用していましたが、今後の案件でプラグイン導入・運用コストを抑えたいといった場合に一助となるのではないかということも少し考えた次第です。

まずは完成イメージを添付します。フロント画面からです。

次にプラグイン設定画面です。

それでは実際の手順を書いていきたいと思います。

(1)プラグインジェネレータを使用して、雛形を作成する

EC-CUBEのコマンドラインインターフェース(参考:https://doc4.ec-cube.net/quickstart/cli)で用意されているプラグインジェネレータを使用して、プラグインの雛形を作成します。以下コマンドで作成されます。

    $ cd [EC-CUBEのインストールディレクトリ]
    $ bin/console eccube:plugin:generate

プラグインの情報を入力していきます。今回はCloudflare Turnstile ウィジェットのプラグインを作成するので、以下のように入力しました。

    name [EC-CUBE Sample Plugin]:
    > EC-CUBE Cloudflare Turnstile Plugin

    code [Sample]:
    > Turnstile

    ver [1.0.0]:
    > 1.0.0

入力が完了すると、以下ディレクトリ構成でプラグインの雛形が作成されます。

    Turnstile
        ├── composer.json
        ├── Controller
        │   └── Admin
        │       └── ConfigController.php
        ├── Entity
        │   └── Config.php
        ├── Event.php
        ├── Form
        │   ├── Extension
        │   └── Type
        │       └── Admin
        │           └── ConfigType.php
        ├── Nav.php
        ├── (PluginManager.php) ← 自分で作成する必要がある
        ├── Repository
        │   └── ConfigRepository.php
        ├── Resources
        │   ├── doctrine
        │   ├── locale
        │   │   ├── messages.ja.yml
        │   │   └── validators.ja.yml
        │   └── template
        │       └── admin
        │           └── config.twig
        └── TwigBlock.php

(2)雛形に含まれるそれぞれのファイルと役割について

以下は生成時に設定されています。

・composer.json
プラグインの依存関係を記述するファイルです。
以下のように記述されています。
(1)で入力した情報が反映されているのが確認できると思います。

        {
            "name":"ec-cube/turnstile",  // プラグインのパッケージ名
            "version":"1.0.0",  // プラグインのバージョン
            "description":"EC-CUBE Cloudflare Turnstile Plugin",  // プラグイン名称
            "type":"eccube-plugin",  // パッケージタイプ
            "require":{
                "ec-cube/plugin-installer":"~0.0.7 || ^2.0"  // プラグインインストーラーのバージョン
            },
            "extra":{
                "code":"Turnstile"  // プラグインのコード名
            }
        }

以下は作成するプラグインの機能に応じて、それぞれのファイルを編集していくことになります。

・Controller/Admin/ConfigController.php
プラグインの管理画面のコントローラーです。

・Entity/Config.php
プラグインの設定情報を保持するエンティティです。

・Event.php
プラグインのイベントを定義するファイルです。

・Form/Type/Admin/ConfigType.php
プラグインの設定画面のフォームタイプです。

・Nav.php
プラグインの管理画面のナビゲーションを定義するファイルです。

・PluginManager.php
プラグインの管理を行うクラスです。

・Repository/ConfigRepository.php
プラグインの設定情報を取得するリポジトリです。

・Resources/locale/messages.ja.yml
プラグインの言語ファイルです。

・Resources/locale/validators.ja.yml
プラグインのバリデーションメッセージを定義するファイルです。

・Resources/template/admin/config.twig
プラグインの設定画面のテンプレートです。

・TwigBlock.php
プラグインのTwigブロックを定義するファイルです。

(3)管理画面側の機能の実装について

実際に機能を実装していく際に、自分は以下の手順で進めました。

①設定画面に必要な情報の洗い出しとEntityの作成

まずは、プラグインの設定画面に必要な情報を洗い出します。
今回のCloudflare Turnstile ウィジェットのプラグインの場合、以下の情報が必要でした。
(引用:https://developers.cloudflare.com/turnstile/get-started/

・Cloudflare Turnstileのサイトキー
・Cloudflare Turnstileのシークレットキー

あと、bot対応の対策が必要と思われるページで機能を有効にするかどうかの設定が必要と考えました。

・お問い合わせページ
・新規会員登録ページ
・パスワード再発行ページ
・会員ログインページ
・ショッピングログインページ
・非会員購入情報入力ページ
・注文手続きページ
・管理画面ログインページ

これらの情報を元に、プラグインジェネレータで作成されたEntity/Config.phpを編集しました。
EC-CUBE4系では、DBとデータをやり取りするためにDoctrineというORM(Object Relational Mapping)を使用しています。
ORMとはMySQLなどのRDBとオブジェクト指向プログラミング言語の間の非互換なデータをマッピングするためのプログラミング技法のことです。
EC-CUBEでは、Entityというクラス(オブジェクト)をDBのテーブル(今回の場合はplg_turnstile_config)にマッピングします。ここに必要なプロパティとGetterおよびSetterメソッドを記述していきます。

        (例)
        <?php

        namespace Plugin\Turnstile\Entity;

        use Doctrine\ORM\Mapping as ORM;

        if (!class_exists('\Plugin\Turnstile\Entity\Config', false)) {
            /**
             * Config
             *
             * @ORM\Table(name="plg_turnstile_config")
             * @ORM\Entity(repositoryClass="Plugin\Turnstile\Repository\ConfigRepository")
             */
            class Config
            {
                /**
                 * @var int
                 *
                 * @ORM\Column(name="id", type="integer", options={"unsigned":true})
                 * @ORM\Id
                 * @ORM\GeneratedValue(strategy="IDENTITY")
                 */
                private $id;

                /**
                 * @var string
                 *
                 * @ORM\Column(name="sitekey", type="string", length=50, nullable=true, options={"comment":"サイトキー"})
                 */
                private $sitekey;


                                                ・
                                                ・
                                                ・

                /**
                 * @return int
                 */
                public function getId()
                {
                    return $this->id;
                }

                /**
                 * Get sitekey.
                 * 
                 * @return string
                 */
                public function getSitekey()
                {
                    return $this->sitekey;
                }

                /**
                 * Set sitekey.
                 * 
                 * @param string $sitekey
                 *
                 * @return $this;
                 */
                public function setSitekey($sitekey)
                {
                    $this->sitekey = $sitekey;

                    return $this;
                }

                                                ・
                                                ・
                                                ・

            }
        }

②Repositoryについて

RepositoryはEntityのfetch(読み込み)を補助するためのクラスになりますが、今回の場合は特に使用する機能の実装は行なっていません。ですのでプラグインジェネレータが生成したままの状態です。

③設定画面のフォーム項目の作成

次に、設定画面のフォーム項目を作成します。
プラグインジェネレータで生成されたForm/Type/Admin/ConfigType.phpを編集してフォーム項目を作成します。

        (例)
        <?php

        namespace Plugin\Turnstile\Form\Type\Admin;

        use Eccube\Form\Type\ToggleSwitchType;

        use Plugin\Turnstile\Entity\Config;

        use Symfony\Component\Form\AbstractType;
        use Symfony\Component\Form\Extension\Core\Type\TextType;
        use Symfony\Component\Form\FormBuilderInterface;
        use Symfony\Component\OptionsResolver\OptionsResolver;
        use Symfony\Component\Validator\Constraints\Length;

        class ConfigType extends AbstractType
        {
            /**
             * {@inheritdoc}
             */
            public function buildForm(FormBuilderInterface $builder, array $options)
            {
                $builder
                    ->add('sitekey', TextType::class, [
                        'constraints' => [
                            new Length(['max' => 50]),
                        ],
                    ])

                                                ・
                                                ・
                                                ・

            }

            /**
             * {@inheritdoc}
             */
            public function configureOptions(OptionsResolver $resolver)
            {
                $resolver->setDefaults([
                    'data_class' => Config::class,
                ]);
            }
        }

④設定画面のテンプレートの作成

次に、設定画面のテンプレートを作成します。
プラグインジェネレータで生成されたResources/template/admin/config.twigを編集してテンプレートを作成します。

            (例)
            {% extends '@admin/default_frame.twig' %}

            {% set menus = ['store', 'plugin', 'plugin_list'] %}

            {% block title %}Turnstile{% endblock %}
            {% block sub_title %}プラグイン設定{% endblock %}

            {% form_theme form '@admin/Form/bootstrap_4_horizontal_layout.html.twig' %}

            {% block stylesheet %}スタイルがあれば適宜設定{% endblock stylesheet %}

            {% block javascript %}jsがあれば適宜設定{% endblock javascript %}

            {% block main %}
                <form role="form" method="post">

                    {{ form_widget(form._token) }}

                    <div class="c-contentsArea__cols">
                        <div class="c-contentsArea__primaryCol">
                            <div class="c-primaryCol">

                                <div class="card rounded border-0 mb-4">
                                    <div class="card-header"><span>Cloudflare Turnstile設定</span></div>
                                    <div class="card-body">
                                        <div class="row">
                                            <div class="col-3"><span>サイトキー</span></div>
                                            <div class="col mb-2">
                                                {{ form_widget(form.sitekey) }}
                                                {{ form_errors(form.sitekey) }}
                                            </div>
                                        </div>

                                                ・
                                                ・
                                                ・

                    <div class="c-conversionArea">
                        <div class="c-conversionArea__container">
                            <div class="row justify-content-between align-items-center">
                                <div class="col-6">
                                    <div class="c-conversionArea__leftBlockItem">
                                        <a class="c-baseLink"
                                           href="{{ url('admin_store_plugin') }}">
                                            <i class="fa fa-backward" aria-hidden="true"></i>
                                            <span>プラグイン一覧</span>
                                        </a>
                                    </div>
                                </div>
                                <div class="col-6">
                                    <div class="row align-items-center justify-content-end">
                                        <div class="col-auto">
                                            <button class="btn btn-ec-conversion px-5"
                                                    type="submit">登録</button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </form>
            {% endblock %}

⑤言語ファイルの編集について

テンプレートファイル作成時に必要となる文言を言語ファイルに追加します。

        (例)
        #------------------------------------------------------------------------------------
        # 設定:表示設定
        #------------------------------------------------------------------------------------
        admin.plugin.turnstile.config.inquiry: お問い合わせページ
        admin.plugin.turnstile.config.entry: 新規会員登録ページ
        admin.plugin.turnstile.config.forgot: パスワード再発行ページ
        admin.plugin.turnstile.config.mypage_login: 会員ログインページ
        admin.plugin.turnstile.config.shopping_login: ショッピングログインページ
        admin.plugin.turnstile.config.shopping_nonmember: 非会員購入情報入力ページ
        admin.plugin.turnstile.config.shopping: 注文手続きページ
        admin.plugin.turnstile.config.admin_login: 管理画面ログインページ

        #------------------------------------------------------------------------------------
        # ツールチップ
        #------------------------------------------------------------------------------------
        tooltip.plugin.turnstile.config.inquiry: お問い合わせページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.entry: 新規会員登録ページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.forgot: パスワード再発行ページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.mypage_login: 会員ログインページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.shopping_login: ショッピングログインページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.shopping_nonmember: 非会員購入情報入力ページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.shopping: 注文手続きページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。
        tooltip.plugin.turnstile.config.admin_login: 管理画面ログインページにCloudflare Turnstileウィジェットを表示する場合は「有効」にします。

⑥PluginManagerについて

プラグインルートディレクトリ内にPluginManager.phpを作成します。
PluginManager.phpには、プラグインのインストール・アンインストール・有効・無効・アップデートを行うときに必ず呼び出されるクラスを記述します。

        (例)
        <?php
        namespace Plugin\Turnstile;

        use Doctrine\ORM\EntityManagerInterface;
        use Eccube\Plugin\AbstractPluginManager;
        use Plugin\Turnstile\Entity\Config;
        use Symfony\Component\DependencyInjection\ContainerInterface;

        class PluginManager extends AbstractPluginManager
        {
            /**
             * プラグインインストール時の処理
             *
             * @param array $meta
             * @param ContainerInterface $container
             */
            public function install(array $meta, ContainerInterface $container)
            {

                                                ・
                                                ・
                                                ・

            }

            /**
             * プラグイン有効時の処理
             *
             * @param $meta
             * @param ContainerInterface $container
             */
            public function enable(array $meta, ContainerInterface $container)
            {
                    
                                                ・
                                                ・
                                                ・
            }

            /**
             * プラグインアンインストール時の処理
             *
             * @param array $meta
             * @param ContainerInterface $container
             */
            public function uninstall(array $meta, ContainerInterface $container)
            {
                        
                                                ・
                                                ・
                                                ・
            }
        }

(4)管理画面側の機能実装の確認について

ここまで行うと、プラグインを有効化させると管理画面にプラグインの設定画面が表示されるようになります。
プラグインのインストール、有効化と設定画面表示を確認してみたいと思います。

EC-CUBEのコマンドラインインターフェース(参考:https://doc4.ec-cube.net/quickstart/cli)で用意されている以下コマンドでプラグインをインストール、有効化します。

    $ cd [EC-CUBEのインストールディレクトリ]
    $ bin/console eccube:plugin:install --code=Turnstile
    $ bin/console eccube:plugin:enable --code=Turnstile

有効化したら、管理画面のプラグイン設定(歯車マーク)を参照します。
(参照する際にリロードしないと歯車マークが表示されない場合があります。表示されない時はキャッシュクリアを試してみてください。)

表示されていますね。
入力、保存できるかも合わせて確認してみます。(Form,Entityの確認です。)

保存もできていますね!

長くなってしまいましたので、次回はフロント側のウィジェット表示を実装していきたいと思います。

Related articles

EC-CUBE 4系のプラグイン開発について その...

前回、プラグインを一旦有効化させて管理...

Laravel Filamentを使用した管理画面...

前回Breezeをインストールしたこと...

Laravel Filamentを使用した管理画面...

前回、filamentでのリソース作成...

Laravel Filamentを使用した管理画面...

前回、Filamentをインストールし...