<?php
/**
* @version EC-CUBE4系
* @copyright 株式会社 翔 kakeru.co.jp
*
* 2021年12月22日カスタマイズ
*
* app\Customize\Controller\EntryController.php
*
* 新規会員登録 カスタマイズ
*
*
*
* ≡≡≡┏(^o^)┛
*****************************************************/
namespace Customize\Controller;
use Customize\Service\Google\ReCaptchaService;
use Customize\Service\MobileDetector as LmMobileDetector;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Master\CustomerStatus;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
#use Eccube\Form\Type\Front\EntryType;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Repository\CustomerRepository;
use Eccube\Repository\Master\CustomerStatusRepository;
use Eccube\Repository\PageRepository;
#use Eccube\Service\CartService;
use Eccube\Service\MailService;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception as HttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Symfony\Component\Validator\Constraints as Assert;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Customize\Form\Type\Front\EntryType;
use Customize\Service\CommonService;
use Customize\Converter\CustomerConverter;
use Customize\Service\CartService;
class EntryController extends \Eccube\Controller\EntryController
{
/**
* @var CustomerStatusRepository
*/
protected $customerStatusRepository;
/**
* @var ValidatorInterface
*/
protected $recursiveValidator;
/**
* @var MailService
*/
protected $mailService;
/**
* @var BaseInfo
*/
protected $BaseInfo;
/**
* @var CustomerRepository
*/
protected $customerRepository;
/**
* @var EncoderFactoryInterface
*/
protected $encoderFactory;
/**
* @var TokenStorageInterface
*/
protected $tokenStorage;
/**
* @var \Eccube\Service\CartService
*/
protected $cartService;
/**
* @var PageRepository
*/
protected $pageRepository;
protected $CommonService;
protected $CustomerConverter;
/**
* @var LmMobileDetector
*/
protected $mobileDetector;
protected $reCaptchaService;
/**
* EntryController constructor.
*
* @param CartService $cartService
* @param CustomerStatusRepository $customerStatusRepository
* @param MailService $mailService
* @param BaseInfoRepository $baseInfoRepository
* @param CustomerRepository $customerRepository
* @param EncoderFactoryInterface $encoderFactory
* @param ValidatorInterface $validatorInterface
* @param TokenStorageInterface $tokenStorage
* @param LmMobileDetector $mobileDetector
*/
public function __construct(
CartService $cartService,
CustomerStatusRepository $customerStatusRepository,
MailService $mailService,
BaseInfoRepository $baseInfoRepository,
CustomerRepository $customerRepository,
EncoderFactoryInterface $encoderFactory,
ValidatorInterface $validatorInterface,
TokenStorageInterface $tokenStorage,
PageRepository $pageRepository
,CommonService $CommonService
,CustomerConverter $CustomerConverter,
LmMobileDetector $mobileDetector,
ReCaptchaService $reCaptchaService
) {
$this->customerStatusRepository = $customerStatusRepository;
$this->mailService = $mailService;
$this->BaseInfo = $baseInfoRepository->get();
$this->customerRepository = $customerRepository;
$this->encoderFactory = $encoderFactory;
$this->recursiveValidator = $validatorInterface;
$this->tokenStorage = $tokenStorage;
$this->cartService = $cartService;
$this->pageRepository = $pageRepository;
$this->CommonService = $CommonService;
$this->CustomerConverter = $CustomerConverter;
$this->mobileDetector = $mobileDetector;
$this->reCaptchaService = $reCaptchaService;
}
/**
* 会員登録画面.
*
* @Route("/regi/", name="entry", methods={"GET", "POST"})
* @Route("/regi/", name="entry_confirm", methods={"GET", "POST"})
* @Template("Entry/index.twig")
*/
public function index(Request $request)
{
if ($this->isGranted('ROLE_USER')) {
log_info('認証済のためログイン処理をスキップ');
return $this->redirectToRoute('mypage');
}
$Entry = $request->request->get('entry');
$RequestEmail = $Entry['email'] ?? null;
$reCaptchaSiteKey = $this->reCaptchaService->getReCaptchaSiteKey();
if ($RequestEmail) {
$Entry['email'] = [
"first" => mb_convert_kana($RequestEmail['first'], 'a', 'UTF-8'),
"second" => mb_convert_kana($RequestEmail['second'], 'a', 'UTF-8')
];
$request->request->set('entry', $Entry);
}
/** @var $Customer \Eccube\Entity\Customer */
$Customer = $this->customerRepository->newCustomer();
/* @var $builder \Symfony\Component\Form\FormBuilderInterface */
$builder = $this->formFactory->createBuilder(EntryType::class, $Customer);
// $LmBuilder = $this->formFactory->createNamedBuilder('', Lm_EntryType::class);
$event = new EventArgs(
[
'builder' => $builder,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_ENTRY_INDEX_INITIALIZE );
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
#kakeru ここまでしないと初期と初期値を登録できない
if (is_null($request->request->get('entry'))){
//$melmaga = $req['customer_melmaga'] ?? 1;
$form->get('customer_melmaga')->setData(true);
}
$form->handleRequest($request);
if ($form->isSubmitted()) {
if (!$form->isValid()) {
$errors = $this->collectFormErrors($form);
$request->getSession()->getFlashBag()->add('form_debug', json_encode($errors, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
$this->isTokenValid();
if ($form->isValid()) {
switch ($request->get('mode')) {
case 'confirm':
$this->reCaptchaService->handleRequest($request);
log_info('会員登録確認開始');
log_info('会員登録確認完了');
return $this->render(
'Entry/confirm.twig',
[
'form' => $form->createView(),
'Page' => $this->pageRepository->getPageByRoute('entry_confirm'),
'BreadCrumbs' => [],
'reCaptchaSiteKey' => $reCaptchaSiteKey,
'path_info' => $request->getPathInfo(),
'customer_type' => $form->get('customer_type')->getData()
]
);
case 'complete':
$this->reCaptchaService->handleRequest($request);
log_info('会員登録開始');
$encoder = $this->encoderFactory->getEncoder($Customer);
$salt = $encoder->createSalt();
$password = $encoder->encodePassword($Customer->getPassword(), $salt);
$secretKey = $this->customerRepository->getUniqueSecretKey();
$Datas = $form->getData();
// Get company type to determine which fields to save
$customerType = $form->get('customer_type')->getData();
// Set custom fields on dtb_customer (entity extension)
$companyKana = $form->get('customer_company_kana')->getData();
$lastNameKana = $form->get('customer_last_name_kana')->getData();
$mobileNumber = $form->get('customer_mobile_number')->getData();
$uniformUsage = $form->get('customer_uniform_usage')->getData();
$uniformUsageOther = null;
if (is_array($uniformUsage) && in_array('8', $uniformUsage)) {
$uniformUsageOther = $form->get('customer_uniform_usage_other')->getData();
}
$Tel = $form->get('phone_number')->getData();
$Customer
->setSalt($salt)
->setPassword($password)
->setSecretKey($secretKey)
->setPoint(0)
->setPhoneNumber($Tel)
->setName02('');
$Customer->setCompanyKana($companyKana);
$Customer->setLastNameKana($lastNameKana);
$Customer->setMobileNumber($mobileNumber);
// Multi-selects saved as comma-separated strings in dtb_customer
$Customer->setUniformUsageOther($uniformUsageOther);
// Get uniform replacement frequency for all users (required field)
$uniformFreq = $form->get('customer_uniform_replacement_frequency')->getData();
$Customer->setUniformReplacementFrequency($uniformFreq);
$Customer->setCustomerType($customerType);
// Only save job-related fields if not individual (customer_type != '3')
if ($customerType !== '3') {
$usage = $form->get('customer_uniform_usage')->getData();
$jobCategory = $form->get('job_category')->getData();
$jobSubcategory = $form->get('job_subcategory')->getData();
$Customer->setUniformUsage(is_array($usage) ? implode(',', $usage) : $usage);
$Customer->setJobCategory($jobCategory);
$Customer->setJobSubcategory($jobSubcategory);
} else {
// For individual users, set empty values for job fields only
$Customer->setUniformUsage('');
$Customer->setJobCategory('');
$Customer->setJobSubcategory('');
}
$this->entityManager->persist($Customer);
$this->entityManager->flush();
#2021/12/23 LMDATAを渡す
$Columns = $this->CommonService->GetYaml('LmCustomer.yaml');
foreach ($Columns as $Column) {
switch ($Column) {
case 'customer_melmaga':
$LmDatas[$Column] = $form->get('customer_melmaga')->getData() ?? 0;
break;
case 'customer_cart_follow':
case 'customer_review_request':
$LmDatas[$Column] = 1;
break;
case 'customer_uniform_usage':
case 'customer_uniform_replacement_frequency':
case 'job_category':
case 'job_subcategory':
// Only save job-related fields if not individual
if ($customerType !== '3') {
$LmDatas[$Column] = $form->get($Column)->getData();
} else {
$LmDatas[$Column] = '';
}
break;
case 'customer_type':
$LmDatas[$Column] = $customerType;
break;
default:
$LmDatas[$Column] = $form->get($Column)->getData();
}
}
$LmCustomerId = $this->CustomerConverter->SetCustomer($Customer, $LmDatas);
$Customer->setLmCustomerId($LmCustomerId);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
log_info('会員登録完了');
$event = new EventArgs(
[
'form' => $form,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_ENTRY_INDEX_COMPLETE);
$activateFlg = $this->BaseInfo->isOptionCustomerActivate();
// 仮会員設定が有効な場合は、確認メールを送信し完了画面表示.
if ($activateFlg) {
$activateUrl = $this->generateUrl('entry_activate', ['secret_key' => $Customer->getSecretKey()], UrlGeneratorInterface::ABSOLUTE_URL);
// メール送信
$this->mailService->sendCustomerConfirmMail($Customer, $activateUrl);
if ($event->hasResponse()) {
return $event->getResponse();
}
log_info('仮会員登録完了画面へリダイレクト');
return $this->redirectToRoute('entry_complete');
} else {
// 仮会員設定が無効な場合は、会員登録を完了させる.
$qtyInCart = $this->entryActivate($request, $Customer->getSecretKey());
$redirect = $request->query->get('redirect');
if (in_array($redirect, ['cart', 'shopping'])) {
return $this->redirectToRoute($redirect);
}
#2022/11/29
if ($this->cartService->GetCartType()) {
return $this->redirectToRoute('shopping');
}
// URLを変更するため完了画面にリダイレクト
return $this->redirectToRoute('entry_activate', [
'secret_key' => $Customer->getSecretKey(),
'qtyInCart' => $qtyInCart,
'BreadCrumbs' => [],
]);
}
}
}
}
$route = $request->get('_route');
$isLogin = $route === 'shopping_entry';
$isRegister = $route === 'entry';
// Load job categories data from JSON
$jobCategoriesData = $this->loadJobCategoriesData();
return [
'form' => $form->createView(),
'BreadCrumbs' => [],
'isMobile' => $this->mobileDetector->isMobile(),
'isLogin' => $isLogin,
'isRegister' => $isRegister,
'reCaptchaSiteKey' => $reCaptchaSiteKey,
'jobCategoriesData' => $jobCategoriesData
];
}
/**
* 会員登録画面.
*
* @Route("/shopping/regi/", name="shopping_entry", methods={"GET", "POST"})
* @Template("Entry/index.twig")
*/
public function shoppingEntry(Request $request)
{
if ($this->isGranted('ROLE_USER')) {
log_info('認証済のためログイン処理をスキップ');
return $this->redirectToRoute('mypage');
}
$Entry = $request->request->get('entry');
$RequestEmail = (isset($Entry) && is_array($Entry) && isset($Entry['email'])) ? $Entry['email'] : null;
if ($RequestEmail) {
$Entry['email'] = [
"first" => mb_convert_kana($RequestEmail['first'], 'a', 'UTF-8'),
"second" => mb_convert_kana($RequestEmail['second'], 'a', 'UTF-8')
];
$request->request->set('entry', $Entry);
}
/** @var $Customer \Eccube\Entity\Customer */
$Customer = $this->customerRepository->newCustomer();
/* @var $builder \Symfony\Component\Form\FormBuilderInterface */
$builder = $this->formFactory->createBuilder(EntryType::class, $Customer);
$event = new EventArgs(
[
'builder' => $builder,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_ENTRY_INDEX_INITIALIZE );
/* @var $form \Symfony\Component\Form\FormInterface */
$form = $builder->getForm();
#kakeru ここまでしないと初期と初期値を登録できない
if (is_null($request->request->get('entry'))){
//$melmaga = $req['customer_melmaga'] ?? 1;
$form->get('customer_melmaga')->setData(true);
}
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
switch ($request->get('mode')) {
case 'confirm':
log_info('会員登録確認開始');
log_info('会員登録確認完了');
return $this->render(
'Entry/confirm.twig',
[
'form' => $form->createView(),
'Page' => $this->pageRepository->getPageByRoute('entry_confirm'),
'BreadCrumbs' => [],
'path_info' => $request->getPathInfo(),
'customer_type' => $form->get('customer_type')->getData()
]
);
case 'complete':
log_info('会員登録開始');
$encoder = $this->encoderFactory->getEncoder($Customer);
$salt = $encoder->createSalt();
$password = $encoder->encodePassword($Customer->getPassword(), $salt);
$secretKey = $this->customerRepository->getUniqueSecretKey();
$Datas= $form->getData();
$Tel = $form->get('phone_number')->getData();
$Customer
->setSalt($salt)
->setPassword($password)
->setSecretKey($secretKey)
->setPoint(0)
->setPhoneNumber($Tel)
->setName02('');
// Get company type to determine which fields to save
$customerType = $form->get('customer_type')->getData();
// Set custom fields on dtb_customer (entity extension)
$Customer->setCompanyKana($form->get('customer_company_kana')->getData());
$Customer->setLastNameKana($form->get('customer_last_name_kana')->getData());
$Customer->setMobileNumber($form->get('customer_mobile_number')->getData());
// Multi-selects saved as comma-separated strings in dtb_customer
$uniformUsage = $form->get('customer_uniform_usage')->getData();
$uniformUsageOther = null;
if (is_array($uniformUsage) && in_array('8', $uniformUsage)) {
$uniformUsageOther = $form->get('customer_uniform_usage_other')->getData();
}
$Customer->setUniformUsageOther($uniformUsageOther);
// Get uniform replacement frequency for all users (required field)
$uniformFreq = $form->get('customer_uniform_replacement_frequency')->getData();
$Customer->setUniformReplacementFrequency($uniformFreq);
$Customer->setCustomerType($customerType);
// Only save job-related fields if not individual (customer_type != '3')
if ($customerType !== '3') {
$usage = $form->get('customer_uniform_usage')->getData();
$jobCategory = $form->get('job_category')->getData();
$jobSubcategory = $form->get('job_subcategory')->getData();
$Customer->setUniformUsage(is_array($usage) ? implode(',', $usage) : $usage);
$Customer->setJobCategory($jobCategory);
$Customer->setJobSubcategory($jobSubcategory);
} else {
// For individual users, set empty values for job fields only
$Customer->setUniformUsage('');
$Customer->setJobCategory('');
$Customer->setJobSubcategory('');
}
$this->entityManager->persist($Customer);
$this->entityManager->flush();
#2021/12/23 LMDATAを渡す
$Columns = $this->CommonService->GetYaml('LmCustomer.yaml');
foreach ( $Columns as $Column){
switch ($Column){
case 'customer_melmaga':
$LmDatas[$Column]= $form->get('customer_melmaga')->getData() ?? 0 ;
break;
case 'customer_cart_follow':
case 'customer_review_request':
$LmDatas[$Column] = 1;
break;
case 'customer_uniform_usage':
case 'customer_uniform_replacement_frequency':
case 'job_category':
case 'job_subcategory':
// Only save job-related fields if not individual
if ($customerType !== '3') {
$LmDatas[$Column] = $form->get($Column)->getData();
} else {
$LmDatas[$Column] = '';
}
break;
case 'customer_type':
$LmDatas[$Column] = $customerType;
break;
default:
$LmDatas[$Column]= $form->get($Column)->getData();
}
}
$LmCustomerId =$this->CustomerConverter->SetCustomer($Customer,$LmDatas);
$Customer->setLmCustomerId($LmCustomerId);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
log_info('会員登録完了');
$event = new EventArgs(
[
'form' => $form,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_ENTRY_INDEX_COMPLETE, );
$activateFlg = $this->BaseInfo->isOptionCustomerActivate();
// 仮会員設定が有効な場合は、確認メールを送信し完了画面表示.
if ($activateFlg) {
$activateUrl = $this->generateUrl('entry_activate', ['secret_key' => $Customer->getSecretKey()], UrlGeneratorInterface::ABSOLUTE_URL);
// メール送信
$this->mailService->sendCustomerConfirmMail($Customer, $activateUrl);
if ($event->hasResponse()) {
return $event->getResponse();
}
log_info('仮会員登録完了画面へリダイレクト');
return $this->redirectToRoute('entry_complete');
} else {
// 仮会員設定が無効な場合は、会員登録を完了させる.
$qtyInCart = $this->entryActivate($request, $Customer->getSecretKey());
$redirect = $request->query->get('redirect');
if (in_array($redirect, ['cart', 'shopping'])) {
return $this->redirectToRoute($redirect);
}
#2022/11/29
if($this->cartService->GetCartType()){
return $this->redirectToRoute('shopping');
}
// URLを変更するため完了画面にリダイレクト
return $this->redirectToRoute('entry_activate', [
'secret_key' => $Customer->getSecretKey(),
'qtyInCart' => $qtyInCart,
'BreadCrumbs' => [],
]);
}
}
}
if ($form->isSubmitted() && !$form->isValid()) {
$errors = $this->collectFormErrors($form);
log_info('Entry form validation errors', ['context' => 'entry:shoppingEntry', 'errors' => $errors]);
$request->getSession()->getFlashBag()->add('form_debug', json_encode($errors, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
}
$route = $request->get('_route');
$isLogin = $route === 'shopping_entry';
$isRegister = $route === 'entry';
// Load job categories data from JSON
$jobCategoriesData = $this->loadJobCategoriesData();
return [
'form' => $form->createView(),
'BreadCrumbs' => [],
'isMobile' => $this->mobileDetector->isMobile(),
'isLogin' => $isLogin,
'isRegister' => $isRegister,
'jobCategoriesData' => $jobCategoriesData
];
}
/**
* 会員登録処理を行う
*
* @param Request $request
* @param $secret_key
*
* @return \Eccube\Entity\Cart|mixed
*/
private function entryActivate(Request $request, $secret_key)
{
log_info('本会員登録開始');
$Customer = $this->customerRepository->getProvisionalCustomerBySecretKey($secret_key);
if (is_null($Customer)) {
throw new HttpException\NotFoundHttpException();
}
$CustomerStatus = $this->customerStatusRepository->find(CustomerStatus::REGULAR);
$Customer->setStatus($CustomerStatus);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
log_info('本会員登録完了');
$event = new EventArgs(
[
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event,EccubeEvents::FRONT_ENTRY_ACTIVATE_COMPLETE );
// メール送信
$this->mailService->sendCustomerCompleteMail($Customer);
// Assign session carts into customer carts
$Carts = $this->cartService->getCarts();
$qtyInCart = 0;
foreach ($Carts as $Cart) {
$qtyInCart += $Cart->getTotalQuantity();
}
// 本会員登録してログイン状態にする
$token = new UsernamePasswordToken($Customer, null, 'customer', ['ROLE_USER']);
$this->tokenStorage->setToken($token);
$request->getSession()->migrate(true);
if ($qtyInCart) {
$this->cartService->save();
}
log_info('ログイン済に変更', [$this->getUser()->getId()]);
return $qtyInCart;
}
/**
* Load job categories data from JSON file
*/
private function loadJobCategoriesData()
{
$jsonPath = __DIR__ . '/../Resource/Json/JobCategoryOptions.json';
if (!file_exists($jsonPath)) {
return [];
}
$jsonContent = file_get_contents($jsonPath);
$data = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE) {
return [];
}
return $data['categories'] ?? [];
}
private function collectFormErrors(\Symfony\Component\Form\FormInterface $form): array
{
$errors = [];
foreach ($form->getErrors(true) as $error) {
$origin = $error->getOrigin();
$errors[] = [
'field' => $origin ? $origin->getName() : null,
'message' => $error->getMessage(),
];
}
return $errors;
}
}