<?php
/**
* Copyright(c) 2018 SYSTEM_KD
* Date: 2018/09/30
*/
namespace Plugin\Schedule\Service;
use Doctrine\ORM\EntityManagerInterface;
use Eccube\Entity\Category;
use Eccube\Entity\Page;
use Eccube\Entity\Product;
use Eccube\Entity\ProductCategory;
use Eccube\Repository\CategoryRepository;
use Eccube\Repository\PageRepository;
use Eccube\Repository\ProductRepository;
use Plugin\Schedule\Entity\ScheduleTime;
use Plugin\Schedule\Entity\ScheduleTimeAddTrait;
use Plugin\Schedule\Repository\ScheduleTimeRepository;
use Plugin\Schedule\Utils\ScheduleUtility;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Translation\TranslatorInterface;
class ScheduleService
{
/** @var EntityManagerInterface */
protected $entityManager;
/** @var ProductRepository */
protected $productRepository;
/** @var PageRepository */
protected $pageRepository;
/** @var CategoryRepository */
protected $categoryRepository;
/** @var TranslatorInterface */
protected $translator;
/** @var ScheduleTimeRepository */
protected $scheduleTimeRepository;
/** @var ScheduleUtility */
protected $scheduleUtility;
/** @var ScheduleHelper */
protected $scheduleHelper;
public function __construct(
EntityManagerInterface $entityManager,
ProductRepository $productRepository,
PageRepository $pageRepository,
CategoryRepository $categoryRepository,
ScheduleTimeRepository $scheduleTimeRepository,
TranslatorInterface $translator,
ScheduleUtility $scheduleUtility,
ScheduleHelper $scheduleHelper
)
{
$this->entityManager = $entityManager;
$this->productRepository = $productRepository;
$this->pageRepository = $pageRepository;
$this->categoryRepository = $categoryRepository;
$this->translator = $translator;
$this->scheduleTimeRepository = $scheduleTimeRepository;
$this->scheduleUtility = $scheduleUtility;
$this->scheduleHelper = $scheduleHelper;
}
/**
* 公開開始・終了日の更新
*
* @param $entity
* @param ScheduleTime $ScheduleTime
*/
public function updateScheduleTime($entity, ScheduleTime $ScheduleTime)
{
if (!is_null($ScheduleTime)) {
$time_type = $ScheduleTime->getScheduleType();
if ($ScheduleTime::PRODUCT_TYPE == $time_type) {
// 公開日時が未設定の場合は、レコード削除
$time_from = $ScheduleTime->getTimeFrom();
$time_to = $ScheduleTime->getTimeTo();
// 時間をクリア
$ScheduleTime->setTimeOnlyFrom(null);
$ScheduleTime->setTimeOnlyTo(null);
} else {
// 公開時間が未設定の場合は、レコード削除
$time_from = $ScheduleTime->getTimeOnlyFrom();
$time_to = $ScheduleTime->getTimeOnlyTo();
// 期間をクリア
$ScheduleTime->setTimeFrom(null);
$ScheduleTime->setTimeTo(null);
}
// 公開日時or時間が未設定の場合は、レコード削除
if (is_null($time_from) && is_null($time_to)) {
// ScheduleTime削除
if (!empty($ScheduleTime->getId())) {
$entity->setScheduleTime(null);
$this->entityManager->remove($ScheduleTime);
$this->entityManager->flush();
return;
}
}
// 更新
$this->entityManager->persist($ScheduleTime);
$this->entityManager->flush();
$entity->setScheduleTime($ScheduleTime);
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
}
/**
* @param Category $entity 紐づく親情報を設定
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
public function updateChainScheduleTime(Category $entity)
{
$scheduleTime = $entity->getScheduleTime();
// 紐づく親カテゴリIDを取得
$chainSchedule = $this->getChainSchedule($entity);
if (is_null($scheduleTime)
|| (is_null($scheduleTime->getTimeFrom()) && is_null($scheduleTime->getTimeTo()))) {
// ScheduleTime がクリアされた場合
// 現在自分自身に紐付いている情報を抽出し、親に紐づけ変更
$this->scheduleTimeRepository->updateChainScheduleTime($entity->getScheduleTime(), $chainSchedule);
// 公開情報が付与されていないデータを、親に紐づけ
$this->scheduleTimeRepository->insertChainScheduleTime($entity, $chainSchedule);
} else {
// ScheduleTimeが設定された場合
// 自分の子の中で親に紐付いているものを抽出し、自分に紐づけ変更
$this->scheduleTimeRepository->categoryChildrenUpdate($entity, $chainSchedule);
// 公開情報が付与されていないデータを、自分に紐づけ
$this->scheduleTimeRepository->insertChainScheduleTime($entity, $entity->getScheduleTime());
}
$scheduleTime->setChainScheduleTime($chainSchedule);
$this->entityManager->persist($scheduleTime);
$this->entityManager->flush();
}
/**
* ScheduleTimeが設定された親情報を返却
*
* @param Category $category
* @return ScheduleTime|null
*/
private function getChainSchedule(Category $category)
{
while (true) {
$Parent = $category->getParent();
if (is_null($Parent)) break;
$parentScheduleTime = $Parent->getScheduleTime();
if (!is_null($parentScheduleTime)) {
$time_from = $parentScheduleTime->getTimeFrom();
$time_to = $parentScheduleTime->getTimeTo();
// 親特定
if (!is_null($time_from) || !is_null($time_to)) {
return $parentScheduleTime;
}
}
$category = $Parent;
}
return null;
}
/**
* EntityとScheduleTimeの紐づけ
*
* @param ScheduleTimeAddTrait $entity
* @param ScheduleTime $scheduleTime
*/
public function linkScheduleTime($entity, ScheduleTime $scheduleTime)
{
$entity->setScheduleTime($scheduleTime);
$this->entityManager->persist($entity);
$this->entityManager->flush();
}
/**
* 非公開時の表示判定
*
* @param $product_id
* @return bool
*/
public function isViewProduct($product_id)
{
$Product = $this->getTargetProduct($product_id);
$ScheduleTime = $Product->getScheduleTime();
if (is_null($ScheduleTime)) {
// 公開時間指定なし
return true;
}
return ($ScheduleTime->isViewFlg());
}
/**
* 公開状態判定
*
* @param ScheduleTime $ScheduleTime
* @return bool
* @throws \Exception
*/
private function isActiveTime(ScheduleTime $ScheduleTime)
{
$active = true;
if ($ScheduleTime::PRODUCT_TIME_ONLY_TYPE == $ScheduleTime->getScheduleType()) {
$nowTime = $this->scheduleUtility->getNowTimeOnly();
// 公開時間判定
if (!is_null($ScheduleTime->getTimeOnlyFrom())) {
if ($ScheduleTime->getTimeOnlyFrom() > $nowTime) {
$active = false;
}
}
if (!is_null($ScheduleTime->getTimeOnlyTo())) {
if ($ScheduleTime->getTimeOnlyTo() <= $nowTime) {
$active = false;
}
}
} else {
$toDay = new \DateTime();
// 公開期間判定
if (!is_null($ScheduleTime->getTimeFrom())) {
if ($ScheduleTime->getTimeFrom() > $toDay) {
$active = false;
}
}
if (!is_null($ScheduleTime->getTimeTo())) {
if ($ScheduleTime->getTimeTo() < $toDay) {
$active = false;
}
}
}
return $active;
}
/**
* 商品公開状態判定
*
* @param $product_id
* @return bool true:公開 false:非公開
* @throws \Exception
*/
public function isActiveTimeProduct($product_id)
{
$Product = $this->getTargetProduct($product_id);
$ScheduleTime = $Product->getScheduleTime();
if (is_null($ScheduleTime->getId())) {
// 公開時間指定なし
// カテゴリ条件チェック
return $this->isActiveTimeCategories($Product);
}
// 公開日時判定
$active = $this->isActiveTime($ScheduleTime);
return $active;
}
/**
* 所属するカテゴリでの公開状態チェック
* 非公開ファースト 1つでも非公開のカテゴリがある場合非公開とする
*
* @param Product $product
* @return bool true:公開 false:非公開
* @throws \Exception
*/
public function isActiveTimeCategories(Product $product)
{
// 所属するカテゴリ取得
$productCategories = $product->getProductCategories();
$active = true;
/** @var ProductCategory $productCategory */
foreach ($productCategories as $productCategory) {
$category = $productCategory->getCategory();
if (!$this->isActiveTimeCategory($category)) {
$active = false;
break;
}
}
return $active;
}
/**
* カテゴリの公開状態判定
*
* @param Category $category
* @return bool true:公開 false:非公開
* @throws \Exception
*/
private function isActiveTimeCategory(Category $category)
{
$ScheduleTime = $category->getScheduleTime();
if (is_null($ScheduleTime)) {
// 公開時間指定なし
return true;
}
$active = $this->isActiveTime($ScheduleTime);
return $active;
}
/**
* 販売終了判定
*
* @param $product_id
* @return bool
* @throws \Exception
*/
public function isActiveTimeProductEnd($product_id)
{
$Product = $this->getTargetProduct($product_id);
$ScheduleTime = $Product->getScheduleTime();
if (is_null($ScheduleTime)) {
// 公開時間指定なし
return true;
}
$toDay = new \DateTime();
$isActiveEnd = false;
if($ScheduleTime::PRODUCT_TIME_ONLY_TYPE == $ScheduleTime->getScheduleType()) {
if(!is_null($ScheduleTime->getTimeOnlyTo())) {
if ($ScheduleTime->getTimeOnlyTo() <= $toDay->format('Hi')) {
$isActiveEnd = true;
}
}
} else {
if (!is_null($ScheduleTime->getTimeTo())) {
if ($ScheduleTime->getTimeTo() <= $toDay) {
$isActiveEnd = true;
}
}
}
return $isActiveEnd;
}
/**
* @param $product_id
* @return Product
*/
private function getTargetProduct($product_id)
{
if ($product_id instanceof Product) {
$Product = $product_id;
} else {
$Product = $this->productRepository->find($product_id);
}
if (is_null($Product)) {
throw new NotFoundHttpException();
}
return $Product;
}
/**
* 公開日時判定ページ用
*
* @param Page $page
* @return bool
* @throws \Exception
*/
public function isActiveTimePage(Page $page)
{
$ScheduleTime = $page->getScheduleTime();
return $this->isActiveTime($ScheduleTime);
}
/**
* カテゴリの公開日時情報を返却
*
* @return array
*/
public function getCategoryScheduleList()
{
$Categories = $this->categoryRepository->findAll();
$timeList = [];
/** @var Category $category */
foreach ($Categories as $category) {
$scheduleTime = $category->getScheduleTime();
if (is_null($scheduleTime)) {
$timeList[$category->getId()] = "";
} else {
if (!is_null($scheduleTime->getTimeFrom()) || !is_null($scheduleTime->getTimeTo())) {
$msg = "公開日時:";
if (!is_null($scheduleTime->getTimeFrom())) {
$msg .= $scheduleTime->getTimeFromString();
}
$msg .= ' ~ ';
if (!is_null($scheduleTime->getTimeTo())) {
$msg .= $scheduleTime->getTimeToString();
}
} else {
$msg = '';
}
$timeList[$category->getId()] = $msg;
}
}
return $timeList;
}
/**
* 商品が公開される公開日時を返却
*
* @param Product $product
* @return ScheduleTime|null
*/
public function getActiveScheduleTime(Product $product)
{
// 商品に公開日時が設定されている場合 最優先
$scheduleTime = $product->getScheduleTime();
if (!is_null($scheduleTime) && !empty($scheduleTime->getId())) {
return $scheduleTime;
}
// 設定されているカテゴリからアクティブな時間を取得
$productCategories = $product->getProductCategories();
$scheduleTimeTemp = new ScheduleTime();
/** @var ProductCategory $productCategory */
foreach ($productCategories as $productCategory) {
// 最大のFrom と 最小のToを取得
$category = $productCategory->getCategory();
$scheduleTime = $category->getScheduleTime();
if (is_null($scheduleTime)) {
// 公開時間指定なし
continue;
}
// 最大のFrom 設定
if (is_null($scheduleTimeTemp->getTimeFrom())) {
$scheduleTimeTemp->setTimeFrom($scheduleTime->getTimeFrom());
} else if (!is_null($scheduleTime->getTimeFrom())) {
if ($scheduleTimeTemp->getTimeFrom() < $scheduleTime->getTimeFrom()) {
$scheduleTimeTemp->setTimeFrom($scheduleTime->getTimeFrom());
}
}
// 最小のTo 設定
if (is_null($scheduleTimeTemp->getTimeTo())) {
$scheduleTimeTemp->setTimeTo($scheduleTime->getTimeTo());
} else if (!is_null($scheduleTime->getTimeTo())) {
if ($scheduleTimeTemp->getTimeTo() > $scheduleTime->getTimeTo()) {
$scheduleTimeTemp->setTimeTo($scheduleTime->getTimeTo());
}
}
// view
// いずれか1つでも表示がある場合は表示優先
if (!$scheduleTimeTemp->isTimeViewFlg()) {
$scheduleTimeTemp->setTimeViewFlg($scheduleTime->isTimeViewFlg());
}
}
return $scheduleTimeTemp;
}
/**
* 商品が公開される公開日時を文字列で返却
*
* @param Product $product
* @return array
*/
public function getActiveScheduleTimeToString(Product $product)
{
$scheduleTimeTmp = $this->getActiveScheduleTime($product);
$scheduleFromMsg = $this->translator->trans('schedule.time_empty');
$scheduleToMsg = $this->translator->trans('schedule.time_empty');
if (ScheduleTime::PRODUCT_TIME_ONLY_TYPE == $scheduleTimeTmp->getScheduleType()) {
// 公開時間
if (!is_null($scheduleTimeTmp->getTimeOnlyFrom())) {
$scheduleFromMsg = $this->scheduleHelper->getTimeFormat($scheduleTimeTmp->getTimeOnlyFrom());
}
if (!is_null($scheduleTimeTmp->getTimeOnlyTo())) {
$scheduleToMsg = $this->scheduleHelper->getTimeFormat($scheduleTimeTmp->getTimeOnlyTo());
}
} else {
// 公開期間
if (!is_null($scheduleTimeTmp->getTimeFrom()) && !is_null($scheduleTimeTmp->getTimeTo())) {
if ($scheduleTimeTmp->getTimeFrom() > $scheduleTimeTmp->getTimeTo()) {
// 公開不可の設定状態
$scheduleFromMsg = $this->translator->trans('schedule.time_ng');
$scheduleToMsg = $this->translator->trans('schedule.time_ng');
} else {
$scheduleFromMsg = $scheduleTimeTmp->getTimeFromString();
$scheduleToMsg = $scheduleTimeTmp->getTimeToString();
}
} else {
if (!is_null($scheduleTimeTmp->getTimeFrom())) {
$scheduleFromMsg = $scheduleTimeTmp->getTimeFromString();
}
if (!is_null($scheduleTimeTmp->getTimeTo())) {
$scheduleToMsg = $scheduleTimeTmp->getTimeToString();
}
}
}
return [
'scheduleFromMsg' => $scheduleFromMsg,
'scheduleToMsg' => $scheduleToMsg
];
}
/**
* 公開設定が時間か判定
*
* @param $Product Product
* @return bool true:時間 false:期間
*/
public function isScheduleTypeTimeOnly(Product $Product)
{
$ScheduleTime = $Product->getScheduleTime();
if (!is_null($ScheduleTime)) {
if ($ScheduleTime::PRODUCT_TIME_ONLY_TYPE == $ScheduleTime->getScheduleType()) {
return true;
}
}
return false;
}
}