<?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.
*
* カレンダーはPHP7.4出ないと動かないので注意
* 2024/03/27 k.saito
* index()のreturnに、爆速商品フラグを追加
*/
namespace Customize\Controller\Block;
use Carbon\Carbon;
use Eccube\Controller\Block\CalendarController;
use Eccube\Repository\CalendarRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
//kintone連携用
use Symfony\Component\HttpKernel\KernelInterface; //ルートディレクトリの取得に使用
use Customize\Service\kintoneCalendarService;
use Customize\Service\getJapanholidayService;
use Customize\Service\getProductCategoryService;
use Customize\Service\judgmentBakusokuKoukanService;
use Customize\Service\getAreaForCalendarService; //対応エリア情報
date_default_timezone_set('Asia/Tokyo');
class CustomCalendarController extends CalendarController
{
/**
* @var CalendarRepository
*/
protected $calendarRepository;
/**
* @var KernelInterface
*/
private $kernel;
/**
* @var kintoneCalendarService
*/
private $calendar;
/**
* @var getJapanholidayService
*/
private $getJapanholiday;
/**
* @var getProductCategoryService
*/
private $getProductCategory;
/**
* @var judgmentBakusokuKoukanService
*/
private $judgmentBakusokuKoukan;
/**
* @var getAreaForCalendarService
*/
private $areaInfomation;
/**
* CalendarController constructor.
*/
public function __construct(CalendarRepository $calendarRepository, KernelInterface $kernel, kintoneCalendarService $calendar, getJapanholidayService $getJapanholiday, getProductCategoryService $getProductCategory, judgmentBakusokuKoukanService $judgmentBakusokuKoukan, getAreaForCalendarService $areaInfomation)
{
$this->calendarRepository = $calendarRepository;
$this->kernel = $kernel;
$this->calendar = $calendar;
$this->getJapanholiday = $getJapanholiday;
$this->getProductCategory = $getProductCategory;
$this->judgmentBakusokuKoukan = $judgmentBakusokuKoukan;
$this->areaInfomation = $areaInfomation;
}
/**
* @Route("/block/calendar", name="block_calendar", methods={"GET"})
* @Template("Block/calendar.twig")
*/
public function index(Request $request)
{
$reservable = '⚪︎'; //予約可能(表示用)
$reservationNot = '×'; //予約不可能(表示用) setReservationDayメソッドに影響があるため変更不可。表示変更ならJqueryを修正する
$few = '△'; //予約残りわずか(表示用)
$undefined = '設定なし';
$area = $this->areaInfomation->getArea(); //対応エリアを取得する
$reservationDetail = []; //各カテゴリ対応スタッフの予約状況を表示
$subStaffReservationDetail = []; //エコキュートの場合のサブ担当者の予約状況を表示
$subStaffFlg = false;
$hidden_bakusoku = '0'; // 爆速商品フラグの初期セット
//カレンダーの曜日表示用で使用。getDayOfWeekStringの$weekdayから参照
$displayWeek = ['Sun' => '日', 'Mon' => '月', 'Tue' => '火', 'Wed' => '水', 'Thu' => '木', 'Fri' => '金', 'Sat' => '土'];
//本日の日付を設定する
//デバッグしやすいように/app/config/eccube/packages/kntn_calendar_date_set.yamlの設定情報で変更される
//defaultなら本日、default以外なら指定日
$dateSet = $this->getParameter('calendar_block_date_set');
if ($dateSet === 'default') {
//通常通り本日
$today = Carbon::now();
} else {
//デバッグモード 指定日
$today = Carbon::createFromDate($dateSet);
dump($today);
echo '本日は' . $today->copy()->format('Y-m-d H:i:s') . 'です。';
}
log_debug('今日は' . $today);
$todayStr = $today->toDateString();
$nextMonthDate = $today->copy()->addMonth()->startOfMonth(); //来月の月初
$holidayListOfTwoMonths = []; //定休日リスト
$holiday = ''; //祝日(GoogleAPI)
//商品カテゴリごとにスタッフを選ぶため
$category = $this->getProductCategory->getCategoryFromURL();
$categoryName = $category['name'];
if ($categoryName === 'エコキュート') {
$subStaffFlg = true;
}
//爆速商品対応か非対応でカレンダーの予約可能日を変更するため
$bakusokuflg = $this->judgmentBakusokuKoukan->judge();
log_debug('false(1以外)は爆速商品' . print_r($bakusokuflg, true));
if ($bakusokuflg == true) {
$hidden_bakusoku = '1';
}
//GoogleAPIリクエスト数節約の為、祝日ファイルを読み込む
$csvfile = $this->kernel->getProjectDir() . '/php/file/holiday.csv';
$holiday = file_get_contents($csvfile);
$holiday = explode(',', $holiday);
//祝日ファイルを読み込んでいない場合はGoogleから取得
if ($holiday[0] !== $todayStr) {
//dump('祝日CSV書き込み');
$this->getJapanholiday->getHoliday($today->copy());
$holiday = file_get_contents($csvfile);
$holiday = explode(',', $holiday);
}
array_shift($holiday); //$holiday[0]はフラグの為、削除する
$firstDateOfThisMonth = $today->copy()->startOfMonth();
$firstDateOfNextMonth = $today->copy()->startOfMonth()->addMonth()->startOfMonth();
$endDateOfNextMonth = $today->copy()->startOfMonth()->addMonth()->endOfMonth();
// 2ヶ月間の定休日を取得
$RegularHolidaysOfTwoMonths = $this->calendarRepository->getHolidayList($firstDateOfThisMonth, $endDateOfNextMonth);
// 今月のカレンダー配列を取得
$thisMonthCalendar = $this->createCalendar($firstDateOfThisMonth);
// 来月のカレンダー配列を取得
dump($firstDateOfNextMonth);
$nextMonthCalendar = $this->createCalendar($firstDateOfNextMonth);
dump($nextMonthCalendar);
// 定休日リストを取得
foreach ($RegularHolidaysOfTwoMonths as $RegularHoliday) {
$holidayListOfTwoMonths[] = $RegularHoliday->getHoliday()->setTime(0, 0, 0);
}
$todayCopy = $today->copy();
$todayCopyNextMonth = $today->copy()->startOfMonth()->addMonth();
//今月用
// 今月のカレンダー配列に定休日フラグを設定
$thisMonthCalendar = $this->setHolidayAndTodayFlag($thisMonthCalendar, $holidayListOfTwoMonths, $todayCopy);
//カレンダーに各エリアごとの予約枠を作成する(初期化)
//$thisMonthCalendar = $this->calendar->initializationTargetMonthCalendar($thisMonthCalendar, $area, $undefined);
//各エリアに応じた平日の予約状況の詳細を作成(参照渡し)
$this->calendar->makeReservationDetail($todayCopy, $area, $categoryName, $reservationDetail, $subStaffReservationDetail, $subStaffFlg);
dump($reservationDetail);
//カレンダーに平日の予約不可日を設定(ECCUBEカレンダーとスタッフの予約状況詳細$reservationDetail、$subStaffReservationDetailを連携)
$thisMonthCalendar = $this->calendar->setReservationDay($thisMonthCalendar, $reservationDetail, $subStaffReservationDetail, $todayCopy, $area, $category, $reservable, $reservationNot, $few, $subStaffFlg);
dump($thisMonthCalendar);
//ECCUBEカレンダーの定休日と祝日を予約不可にする
$thisMonthCalendar = $this->calendar->setReservationHoliDay($thisMonthCalendar, $holidayListOfTwoMonths, $holiday, $todayCopy, $area, $reservationNot);
//ECCUBEカレンダーの本日以前、本日から4日を予約不可にする。商品の在庫が存在する場合は本日を予約可能にする(当日のAMは選択不可だが当日の10時まではPMの選択を可能にする)
$notReservationDay = []; //予約不可日
$noReservationDayEnd = ''; // 爆速商品以外の場合に不可にする日付の最終日
$this->calendar->setNotReservationToday($thisMonthCalendar, $bakusokuflg, $area, $holidayListOfTwoMonths, $holiday, $todayCopy, $reservationNot, $notReservationDay, $noReservationDayEnd); //今月のカレンダーと予約不可日が返される
dump($noReservationDayEnd);
//来月用
// 来月のカレンダー配列に定休日フラグを設定
$nextMonthCalendar = $this->setHolidayAndTodayFlag($nextMonthCalendar, $holidayListOfTwoMonths, $todayCopyNextMonth);
//カレンダーに各エリアごとの予約枠を作成する(初期化)
//$nextMonthCalendar = $this->calendar->initializationTargetMonthCalendar($nextMonthCalendar, $area, $undefined);
//カレンダーに平日の予約不可日を設定
$nextMonthCalendar = $this->calendar->setReservationDay($nextMonthCalendar, $reservationDetail, $subStaffReservationDetail, $nextMonthDate, $area, $category, $reservable, $reservationNot, $few, $subStaffFlg);
//ECCUBEカレンダーの定休日と祝日を予約不可にする
$nextMonthCalendar = $this->calendar->setReservationHoliDay($nextMonthCalendar, $holidayListOfTwoMonths, $holiday, $todayCopyNextMonth, $area, $reservationNot);
//ECCUBEカレンダーの本日以前、本日から4日を予約不可にする。商品の在庫が存在する場合は本日を予約可能にする(当日のAMは選択不可だが当日の10時まではPMの選択を可能にする)
$nextMonthCalendar = $this->calendar->setNotReservationNextCalendar($nextMonthCalendar, $area, $todayCopy, $reservationNot, $notReservationDay, $noReservationDayEnd);
//$nextMonthCalendar = $this->calendar->setNotReservationNextCalendar($thisMonthCalendar, $bakusokuflg, $area, $holidayListOfTwoMonths, $holiday, $todayCopy, $reservationNot, $notReservationDay);
dump($thisMonthCalendar);
// 各カレンダータイトルを作成
$monthFormat = $this->translator->trans('front.block.calendar.month_format');
$thisMonthTitle = $firstDateOfThisMonth->format($monthFormat);
$nextMonthTitle = $firstDateOfNextMonth->format($monthFormat);
return [
'ThisMonthTitle' => $thisMonthTitle,
'NextMonthTitle' => $nextMonthTitle,
'ThisMonthCalendar' => $thisMonthCalendar,
'NextMonthCalendar' => $nextMonthCalendar,
'debug' => $reservationDetail, //debug
'subdebug' => $subStaffReservationDetail, //debug
'area' => $area,
'subStaffFlg' => $subStaffFlg, //debug
'displayWeek' => $displayWeek,
'hidden_bakusoku' => $hidden_bakusoku //爆速商品フラグ
];
}
/**
* カレンダー配列に定休日と今日フラグを設定します
*
* @param array $targetMonthCalendar カレンダー配列
* @param array $holidayListOfTwoMonths 定休日リスト
* @param Carbon $targetDate ターゲット日
*
* @return array カレンダーの配列
*/
private function setHolidayAndTodayFlag($targetMonthCalendar, $holidayListOfTwoMonths, Carbon $targetDate)
{
for ($i = 0; $i < count($targetMonthCalendar); $i++) {
// カレンダー配列の日が空の場合は処理をスキップ
if ($targetMonthCalendar[$i]['day'] == '') {
$targetMonthCalendar[$i]['holiday'] = false;
$targetMonthCalendar[$i]['today'] = false;
continue;
}
$targetYmdDateTime = new \DateTime($targetDate->copy()->format('Y-n') . '-' . $targetMonthCalendar[$i]['day']);
// カレンダーの日付が定休日リストに存在するかを確認
$result = array_search($targetYmdDateTime, $holidayListOfTwoMonths);
// 定休日フラグを設定
if ($result !== false) {
$targetMonthCalendar[$i]['holiday'] = true;
} else {
$targetMonthCalendar[$i]['holiday'] = false;
}
// 今日フラグを設定
if ($targetYmdDateTime == new \DateTime($targetDate->copy()->format('Y-n-j'))) {
$targetMonthCalendar[$i]['today'] = true;
} else {
$targetMonthCalendar[$i]['today'] = false;
}
}
return $targetMonthCalendar;
}
/**
* カレンダーの配列を生成します
*
* @param Carbon $firstDateOfTargetMonth 月初日
*
* @return array カレンダーの配列
*/
private function createCalendar(Carbon $firstDateOfTargetMonth)
{
$year = $firstDateOfTargetMonth->copy()->year;
$month = $firstDateOfTargetMonth->copy()->month;
// 週のうちの何日目か 0 (日曜)から 6 (土曜)を取得
$firstDayOfWeek = $firstDateOfTargetMonth->dayOfWeek;
$targetMonthCalendar = [];
// 1日目の曜日の位置手前まで空文字を追加
for ($i = 0; $i <= $firstDayOfWeek; $i++) {
$targetMonthCalendar[$i]['day'] = '';
$targetMonthCalendar[$i]['dayOfWeek'] = '';
}
// 1日目の曜日の位置+月の日数
$loopCount = $firstDayOfWeek + $firstDateOfTargetMonth->daysInMonth;
// 月の日数に合わせて日と曜日を追加
//年月日を追加
$dayNumber = 1;
$dayOfWeekNumber = $firstDayOfWeek;
for ($i = $firstDayOfWeek; $i < $loopCount; $i++) {
$targetMonthCalendar[$i]['day'] = $dayNumber;
$targetMonthCalendar[$i]['dayOfWeek'] = $this->getDayOfWeekString($dayOfWeekNumber);
$month2digits = sprintf('%02d', $month);
$dayNumber2digits = sprintf('%02d', $dayNumber);
$targetMonthCalendar[$i]['yearMonthDay'] = $year . '-' . $month2digits . '-' . $dayNumber2digits;
$dayNumber++;
$dayOfWeekNumber++;
// 曜日のおりかえし: 0 (日曜)へ
if ($dayOfWeekNumber == 7) {
$dayOfWeekNumber = 0;
}
}
// 1日目の曜日の位置+月の日数に合わせて後に空文字を追加
// 7日*4週=28日(日曜始まりでうるう年じゃない2月)
if ($loopCount === 28) {
// 後に空文字追加はスキップ
return $targetMonthCalendar;
}
// 7日*6週=42日、7日*5週=35日
$paddingLoopCount = 35;
if ($loopCount > 35) {
$paddingLoopCount = 42;
}
for ($i = $loopCount; $i < $paddingLoopCount; $i++) {
$targetMonthCalendar[$i]['day'] = '';
$targetMonthCalendar[$i]['dayOfWeek'] = '';
}
return $targetMonthCalendar;
}
/**
* 曜日を数値から文字列へ変換します
*
* @param int $dayOfWeekNumber 曜日の番号 : 0 (日曜)から 6 (土曜)
*
* @return string 曜日の文字 : Sun(日曜)からSat(土曜)
*/
private function getDayOfWeekString($dayOfWeekNumber)
{
$weekday = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
return $weekday[$dayOfWeekNumber];
}
}