<?php
namespace Customize\EventListener;
use Eccube\Common\EccubeConfig;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\{
Event\RequestEvent,
KernelEvents
};
class IntroductionCodeListener implements EventSubscriberInterface
{
/** @var SessionInterface */
private $session;
/** @var EccubeConfig */
private $eccubeConfig;
public function __construct(SessionInterface $session, EccubeConfig $eccubeConfig)
{
$this->session = $session;
$this->eccubeConfig = $eccubeConfig;
}
public static function getSubscribedEvents()
{
// NOTE: 数字が大きいほど早く実行される。16は、Symfonyのコアコンポーネントやその他のミドルウェアの実行より前に
// しかし、最重要な初期化処理の後に実行されるように設定
return [
KernelEvents::REQUEST => ['onKernelRequest', 16],
];
}
/**
* 紹介コードのリクエストを処理
*
* @param RequestEvent $event
* @return void
*/
public function onKernelRequest(RequestEvent $event): void
{
$request = $event->getRequest();
// 商品詳細ページへのリクエストかチェック
if (!preg_match('#^/products/detail/\d+#', $request->getPathInfo())) {
return;
}
// リファラルコードのパラメータを取得
$introductionCode = $request->query->get('introduction_code');
if ($introductionCode) {
// 紹介コードのバリデーション
$validLength = $this->eccubeConfig->get('kofun_introduction_code_len');
if (!preg_match('/^\d{'.$validLength.'}$/', $introductionCode)) {
return; // 不正な形式の場合は保存しない
}
$productId = $this->extractProductId($request->getPathInfo());
if ($productId) {
// 既存の紹介コード情報を取得
$productIntroductionCodes = $this->session->get('product_introduction_codes', []);
// 商品IDをキーとして紹介コードを保存
$productIntroductionCodes[$productId] = $introductionCode;
// セッションに保存
$this->session->set('product_introduction_codes', $productIntroductionCodes);
}
}
}
/**
* URLから商品IDを抽出
*/
private function extractProductId(string $pathInfo): ?int
{
if (preg_match('#/products/detail/(\d+)#', $pathInfo, $matches)) {
return (int) $matches[1];
}
return null;
}
}