EC-CUBE4 会員ランクプラグインを拡張して、ランク別に送料を変更できるカスタムをしたお話

とある会員ランクプラグインを改造してほしい、という要望がありました。

有料プラグインを直接カスタムなんて方法はやりたくないのですが、プラグインをいじらずに実装できそうだったので、プラグインに手を入れずカスタムを行った方法をお話します。

#要望の内容
要望はいたって単純で、会員ランク別に送料を変更したいという内容でした。

東京への発送で、ブロンズ会員なら700円、シルバー会員なら500円といった感じです。

##仕様
１、管理画面から会員毎に都道府県別の送料を設定できる。
２、購入手続きの送料計算で、会員別に設定した送料に変更する。

##利用した技術

プラグインのテンプレートを上書きできるように対応 #4527
https://github.com/EC-CUBE/ec-cube/pull/4527

購入フローのカスタマイズ
https://doc4.ec-cube.net/customize_service#%E8%B3%BC%E5%85%A5%E3%83%95%E3%83%AD%E3%83%BC%E3%81%AE%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA-2424

###会員毎に都道府県別の送料を設定
会員リストはプラグインが用意したページになります。
そのページを上書き出来るように4.0.5からなってるので、会員リストに送料を設定するリンクを追加しました。
（僕がカスタムした時は、まだ4.0.5がリリースされる前だったので、EC-CUBEのコアファイルをいじっています。）

「/app/template/plugin/[プラグインコード]」のフォルダを作成し、プラグインと同じ階層でカスタムしたいテンプレートを追加します。

今回は「/app/Plugin/[プラグインコード]/Resource/template/admin/Customer/index.twig」を編集したいので、そのファイルを、「/app/template/plugin/[プラグインコード]/admin/Customer/index.twig」にコピーして編集します。

そうすることで、プラグインを直接いじらず、プラグインが用意したページを編集できます。
あとは、会員毎に送料を設定するページは「Customize」フォルダで作成します。

ちょっと長くなるので、ソースは割愛。（すみません）

会員ランクに紐づけた送料テーブル（Entity）の作成。
送料設定ページのControllerの作成。
送料設定のFROMを作成。
などなど行ってます。

###購入フローのカスタマイズ
会員ランク毎に、送料の設定が管理画面で出来るようになったら、購入フローをカスタマイズして、会員ランクによって送料を変更します。

今回は「/app/Customize/Service/PurchaseFlow/Processor/CustomerRankDeliveryFeePreprocessor.php」を作成しました。

```CustomerRankDeliveryFeePreprocessor.php
namespace Customize\Service\PurchaseFlow\Processor;

use Customize\Repository\CustomerRankDeliveryFeeRepository;
use Eccube\Annotation\ShoppingFlow;
use Eccube\Entity\ItemHolderInterface;
use Eccube\Entity\Order;
use Eccube\Service\PurchaseFlow\ItemHolderPreprocessor;
use Eccube\Service\PurchaseFlow\PurchaseContext;
use Eccube\Service\PurchaseFlow\Processor\DeliveryFeePreprocessor;

/**
 * @ShoppingFlow()
 */
class CustomerRankDeliveryFeePreprocessor implements ItemHolderPreprocessor
{

    /**
     * @var CustomerRankDeliveryFeeRepository
     */
    protected $customerRankDeliveryFeeRepository;

    /**
     * OrderType constructor.
     *
     * @param CustomerRankDeliveryFeeRepository $customerRankDeliveryFeeRepository
     */
    public function __construct(
        CustomerRankDeliveryFeeRepository $customerRankDeliveryFeeRepository
    ) {
        $this->customerRankDeliveryFeeRepository = $customerRankDeliveryFeeRepository;
    }

    /**
     * @param ItemHolderInterface $itemHolder
     * @param PurchaseContext $context
     */
    public function process(ItemHolderInterface $itemHolder, PurchaseContext $context)
    {

        if (!$itemHolder instanceof Order) {
            return;
        }

        $Customer = $itemHolder->getCustomer();
        if (is_null($Customer)) {
            // ゲスト購入の場合は会員ランク別送料に変更しない。
            return;
        }

        $CustomerRank = $Customer->getCustomerRank();
        if (is_null($CustomerRank)) {
            // 会員ランクが設定されていない場合は会員ランク別送料に変更しない。
            return;
        }

        // 配送先別に送料をチェック
        foreach ($itemHolder->getShippings() as $Shipping) {
            // 配送先の明細をチェック
            foreach ($Shipping->getOrderItems() as $Item) {
                // 送料明細を探す
                if ($Item->getProcessorName() == DeliveryFeePreprocessor::class) {
                    // 送料無料の明細かどうか確認（数量が0の場合は送料無料）
                    if ($Item->getQuantity() == 0) {
                        // 送料無料の場合は次の配送先へ
                        continue 2;
                    }

                    //会員ランクの送料を取得
                    $DeliveryFee = $this->customerRankDeliveryFeeRepository
                        ->findOneBy(
                            [
                                'CustomerRank' => $CustomerRank,
                                'Pref' => $Shipping->getPref(),
                            ]
                        );

                    if (is_null($DeliveryFee)) {
                        // 送料設定が見つからない場合は次の配送先へ
                        continue 2;
                    }
                    //送料の変更
                    $Item->setPrice($DeliveryFee->getFee());
                }
            }
        }
    }
}
```
#まとめ
プラグインを拡張したといっても、プラグインに手を入れたのは、テンプレートを上書き機能を利用して、会員リストページに送料設定ページのリンクを入れただけ。

その他は会員ランクに紐づけならが、Customizeフォルダでカスタムを行った感じです。

プラグインのテンプレートを上書き出来るようになっただけでも、カスタマイズする人としては嬉しいです！
カスタムできる幅が広がりました。

プラグインに手を入れたカスタムはやりたくないですからね。。。