<?php
/*
* This file is part of EC-CUBE
*
* Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
*
* http://www.ec-cube.co.jp/
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Customize\Controller;
use Eccube\Controller\AbstractController;
use Eccube\Entity\BaseInfo;
use Eccube\Entity\Master\CustomerStatus;
use Eccube\Event\EccubeEvents;
use Eccube\Event\EventArgs;
use Customize\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 Customize\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\Repository\SchoolRepository;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Customize\Form\Type\Front\SchoolCertificationType;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Customize\Repository\BrotherRepository;
use Customize\Entity\Brother;
class EntryController extends AbstractController
{
/**
* @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;
/**
* @var schoolRepository
*/
protected $schoolRepository;
protected $session;
/**
* @var BrotherRepository
*/
protected $brotherRepository;
/**
* 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 SchoolRepository $schoolRepository
* @param SessionInterface $session
*/
public function __construct(
CartService $cartService,
CustomerStatusRepository $customerStatusRepository,
MailService $mailService,
BaseInfoRepository $baseInfoRepository,
CustomerRepository $customerRepository,
EncoderFactoryInterface $encoderFactory,
ValidatorInterface $validatorInterface,
TokenStorageInterface $tokenStorage,
PageRepository $pageRepository,
SchoolRepository $schoolRepository,
SessionInterface $session,
BrotherRepository $brotherRepository
) {
$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->schoolRepository = $schoolRepository;
$this->session = $session;
$this->brotherRepository = $brotherRepository;
}
/**
* 会員登録完了画面.
*
* @Route("/entry/complete", name="entry_complete", methods={"GET"})
* @Template("Entry/complete.twig")
*/
public function complete()
{
return [];
}
/**
* 会員登録画面.
*
* @Route("/entry/{gcd}", name="entry", methods={"GET", "POST"}, defaults={"gcd"=null})
* @Route("/entry", name="entry_confirm", methods={"GET", "POST"})
* @Template("Entry/index.twig")
*/
public function index(Request $request, $gcd)
{
if ($this->isGranted('ROLE_USER')) {
log_info('認証済のためログイン処理をスキップ');
return $this->redirectToRoute('mypage');
}
/** @var $Customer \Eccube\Entity\Customer */
$Customer = $this->customerRepository->newCustomer();
$School = null;
$SchoolId = $this->session->get('eccube.school');
if ($SchoolId > 0) {
$School = $this->schoolRepository->find($SchoolId);
if ($School) {
$Customer->setSchool($School);
$Customer->setSchoolCode($School->getSchoolCode());
}
}
if (!$School) {
$builder = $this->formFactory->createNamedBuilder('', SchoolCertificationType::class, null, ['allow_extra_fields' => true]);
$form = $builder->getForm();
} else {
/* @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();
}
$form->handleRequest($request);
$certification_error_flg = 0;
$school_not_found = false;
if ($form->isSubmitted() && $form->isValid()) {
switch ($request->get('mode')) {
case 'certify':
if ($gcd) {
$School2 = $this->schoolRepository->findOneBy([
'entry_url' => $gcd,
'school_key' => $form->get('school_key')->getData(),
]);
} else {
$School2 = $form->get('School')->getData();
if ($School2->isVisibleSchoolKey() && $School2->getSchoolKey() !== $form->get('school_key')->getData()) {
$School2 = null;
}
}
if (!$School2) {
$certification_error_flg = 1;
} else {
$this->session->set('eccube.school', $School2->getSchoolId());
return $this->redirectToRoute('entry');
}
break;
case 'confirm':
log_info('会員登録確認開始');
log_info('会員登録確認完了');
$brothers = $request->get('brothers', '');
$this->session->set('brothers', $brothers);
$brothers = json_decode($brothers);
if (!empty($brothers)) {
foreach ($brothers as $brother) {
$brother_school = $this->schoolRepository->find($brother->school_id);
if ($brother_school) {
$brother->school_name = $brother_school->getSchoolName();
} else {
$brother->school_name = null;
}
}
}
return $this->render(
'Entry/confirm.twig',
[
'form' => $form->createView(),
'School' => $School,
'Brothers' => $brothers,
'Page' => $this->pageRepository->getPageByRoute('entry_confirm'),
]
);
case 'complete':
log_info('会員登録開始');
$encoder = $this->encoderFactory->getEncoder($Customer);
$salt = $encoder->createSalt();
$password = $encoder->encodePassword($Customer->getPlainPassword(), $salt);
$secretKey = $this->customerRepository->getUniqueSecretKey();
$phoneNumber = $Customer->getTel01() . $Customer->getTel02() . $Customer->getTel03();
$Customer
->setSalt($salt)
->setPassword($password)
->setSecretKey($secretKey)
->setPhoneNumber($phoneNumber)
->setPoint(0)
->setMailmagaFlg(1)
->setSchool($School);
$this->entityManager->persist($Customer);
$this->entityManager->flush();
$brothers = $this->session->get('brothers', '');
$brothers = json_decode($brothers);
$this->createOrUpdateBrothers($brothers, [], $Customer);
log_info('会員登録完了');
$event = new EventArgs(
[
'form' => $form,
'Customer' => $Customer,
],
$request
);
$this->eventDispatcher->dispatch($event, EccubeEvents::FRONT_ENTRY_INDEX_COMPLETE);
$this->session->set('eccube.school', 0);
$activateFlg = $this->BaseInfo->isOptionCustomerActivate();
// 仮会員設定が有効な場合は、確認メールを送信し完了画面表示.
if ($activateFlg && !empty($Customer->getEmail())) {
$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 {
// 仮会員設定が無効な場合は、会員登録を完了させる.
if(!empty($Customer->getEmail())){
$qtyInCart = $this->entryActivate($request, $Customer->getSecretKey());
// URLを変更するため完了画面にリダイレクト
return $this->redirectToRoute('entry_activate', [
'secret_key' => $Customer->getSecretKey(),
'qtyInCart' => $qtyInCart,
]);
}
else
return $this->redirectToRoute('homepage');
}
}
}
if (!$School) {
$School2 = null;
if ($gcd) {
$School2 = $this->schoolRepository->findOneBy(['entry_url' => $gcd]);
if (!$School2) {
$school_not_found = true;
}
}
return $this->render(
"Entry/school_certification.twig",
array(
'School' => $School2,
'gcd' => $gcd,
'certification_error_flg' => $certification_error_flg,
'school_not_found' => $school_not_found,
'form' => $form->createView(),
'Schools' => $this->schoolRepository->findAll()
)
);
} else {
return [
'form' => $form->createView(),
'School' => $School,
'Schools' => $this->schoolRepository->findAll(),
];
}
}
/**
* 会員のアクティベート(本会員化)を行う.
*
* @Route("/entry/activate/{secret_key}/{qtyInCart}", name="entry_activate", methods={"GET"})
* @Template("Entry/activate.twig")
*/
public function activate(Request $request, $secret_key, $qtyInCart = null)
{
$errors = $this->recursiveValidator->validate(
$secret_key,
[
new Assert\NotBlank(),
new Assert\Regex(
[
'pattern' => '/^[a-zA-Z0-9]+$/',
]
),
]
);
if (!is_null($qtyInCart)) {
return [
'qtyInCart' => $qtyInCart,
];
} elseif ($request->getMethod() === 'GET' && count($errors) === 0) {
// 会員登録処理を行う
$qtyInCart = $this->entryActivate($request, $secret_key);
return [
'qtyInCart' => $qtyInCart,
];
}
throw new HttpException\NotFoundHttpException();
}
/**
* 会員登録処理を行う
*
* @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)) {
return $this->redirectToRoute('homepage');
}
$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;
}
private function createOrUpdateBrothers($brothers, $deleted_brothers, $Customer)
{
foreach ($deleted_brothers as $brother_id) {
$d_brother = $this->brotherRepository->find($brother_id);
$d_brother->setDelFlg(true);
$d_brother->setUpdateDate(new \DateTime());
$this->entityManager->persist($d_brother);
}
if (!empty($brothers)) {
foreach ($brothers as $brother) {
if (is_object($brother)) {
$brother = (array)$brother;
}
if (!empty($brother['id'])) {
$e_brother = $this->brotherRepository->find($brother['id']);
} else {
$e_brother = new Brother();
}
$e_brother->setCustomer($Customer);
$e_brother->setName($brother['name']);
$e_brother->setSchoolYear($brother['school_year']);
$e_brother->setSchoolClass($brother['school_class']);
$e_brother->setSchool($this->schoolRepository->find($brother['school_id']));
$e_brother->setDelFlg(false);
$e_brother->setCreateDate(new \DateTime());
$e_brother->setUpdateDate(new \DateTime());
$this->entityManager->persist($e_brother);
}
$this->entityManager->flush();
}
}
/**
* @Route("/validate_brothers", name="validate_brothers", methods={"POST"})
*/
public function validateBrothers(Request $request){
$brothers = $request->get('brothers', []);
$invalid_brothers = [];
foreach ($brothers as $brother) {
if($this->schoolRepository->find($brother['school_id'])->getSchoolKey() !== $brother['school_key']){
$invalid_brothers[] = $brother['school_key'];
}
}
return $this->json(['invalid_brothers' => $invalid_brothers]);
}
}