diff --git a/backend/components/AdminMenuStructure.php b/backend/components/AdminMenuStructure.php index b847eaa..86bcd13 100644 --- a/backend/components/AdminMenuStructure.php +++ b/backend/components/AdminMenuStructure.php @@ -170,6 +170,8 @@ class AdminMenuStructure{ $items[] = ['label' => 'Termek', 'url' => ['/room' ] ]; $items[] = ['label' => 'Esemény típusok', 'url' => ['/event-type' ] ]; $items[] = ['label' => 'Események', 'url' => ['/event/event/index' ] ]; + $items[] = ['label' => 'Órarend', 'url' => ['/event/event/timetable' ] ]; + $items[] = ['label' => 'Hét másolása', 'url' => ['/event/event/copy-week' ] ]; $this->menuItems[] = ['label' => 'Csoportos edzés', 'url' => $this->emptyUrl, 'items' => $items ]; diff --git a/common/components/DateUtil.php b/common/components/DateUtil.php index eb9437e..cf316ce 100644 --- a/common/components/DateUtil.php +++ b/common/components/DateUtil.php @@ -8,6 +8,12 @@ namespace common\components; +use DateInterval; +use DateTime; +use DateTimeZone; +use Exception; +use Yii; +use yii\base\InvalidConfigException; use yii\i18n\Formatter; class DateUtil @@ -16,12 +22,13 @@ class DateUtil * Get UTC today @00:00:00 . * Helper method to generate date for mysql * - * @return \DateTime + * @return DateTime + * @throws Exception */ public static function todayStart( ){ - $d2 = new \DateTime(); - $d2->setTimezone( new \DateTimeZone( "UTC" ) ); - $d2->setTime(0, 0, 0); + $d2 = new DateTime(); + $d2->setTimezone( new DateTimeZone('UTC') ); + $d2->setTime(0, 0); return $d2; } @@ -29,13 +36,14 @@ class DateUtil * Get UTC t @00:00:00 . * Helper method to generate date for mysql * - * @return \DateTime + * @return DateTime + * @throws Exception */ public static function tomorrowStart( ){ - $d2 = new \DateTime(); - $d2->add(new \DateInterval('P1D')); - $d2->setTimezone( new \DateTimeZone( "UTC" ) ); - $d2->setTime(0, 0, 0); + $d2 = new DateTime(); + $d2->add(new DateInterval('P1D')); + $d2->setTimezone( new DateTimeZone('UTC') ); + $d2->setTime(0, 0); return $d2; } @@ -44,11 +52,11 @@ class DateUtil public static function addMonth($timestamp, $monthCount = 1) { - if ($timestamp instanceof \DateTime) { + if ($timestamp instanceof DateTime) { $d1 = $timestamp; } else { - $d1 = new \DateTime(); + $d1 = new DateTime(); if (isset($timestamp)) { $d1->setTimestamp($timestamp); @@ -63,28 +71,34 @@ class DateUtil $day = $d1->format('d'); $year += floor($monthToAdd / 12); - $monthToAdd = $monthToAdd % 12; + $monthToAdd %= 12; $month += $monthToAdd; if ($month > 12) { $year++; - $month = $month % 12; - if ($month === 0) + $month %= 12; + if ($month === 0) { $month = 12; + } } if (!checkdate($month, $day, $year)) { - $d2 = \DateTime::createFromFormat('Y-n-j', $year . '-' . $month . '-1'); + $d2 = DateTime::createFromFormat('Y-n-j', $year . '-' . $month . '-1'); $d2->modify('last day of'); } else { - $d2 = \DateTime::createFromFormat('Y-n-d', $year . '-' . $month . '-' . $day); + $d2 = DateTime::createFromFormat('Y-n-d', $year . '-' . $month . '-' . $day); } - $d2->setTime(0, 0, 0); + $d2->setTime(0, 0); return $d2; } + /** + * @param $dateTimeObject + * @return string + * @throws InvalidConfigException + */ public static function formatUtc($dateTimeObject) { $formatter = new Formatter; @@ -93,6 +107,11 @@ class DateUtil return $formatter->asDatetime($dateTimeObject); } + /** + * @param $dateTimeObject + * @return string + * @throws InvalidConfigException + */ public static function formatDateUtc($dateTimeObject) { $formatter = new Formatter; @@ -103,9 +122,27 @@ class DateUtil public static function parseDate($dateString){ - $date = \DateTime::createFromFormat("Y.m.d", $dateString, new \DateTimeZone( 'UTC')); - $date->setTime(0, 0, 0); + $date = DateTime::createFromFormat('Y.m.d', $dateString, new DateTimeZone( 'UTC')); + $date->setTime(0, 0); return $date; } -} \ No newline at end of file + /** + * @param integer $weekDay Numeric representation of the day of the week. @See https://www.php.net/manual/en/function.date.php + * @return string + */ + public static function getLocalDayName($weekDay){ + $translations = [ + 0 => Yii::t('common', 'Sunday'), + 1 => Yii::t('common', 'Monday'), + 2 => Yii::t('common', 'Tuesday'), + 3 => Yii::t('common', 'Wednesday'), + 4 => Yii::t('common', 'Thursday'), + 5 => Yii::t('common', 'Friday'), + 6 => Yii::t('common', 'Saturday'), + 7 => Yii::t('common', 'Sunday'), + ]; + return $translations[$weekDay]; + } + +} diff --git a/common/modules/event/controllers/EventController.php b/common/modules/event/controllers/EventController.php index 47f8dc8..838ae51 100644 --- a/common/modules/event/controllers/EventController.php +++ b/common/modules/event/controllers/EventController.php @@ -5,15 +5,24 @@ namespace common\modules\event\controllers; use common\manager\EventRegistrationManager; use common\models\CardEventRegistrationForm; use common\modules\event\EventModule; +use common\modules\event\models\copy\CopyWeekSearch; use common\modules\event\models\EventPermissions; +use common\modules\event\models\timetable\TimeTableSearch; +use DateTime; +use Exception; +use Throwable; use Yii; use common\models\Event; use common\modules\event\models\EventSearch; use yii\data\ActiveDataProvider; +use yii\filters\AccessControl; use yii\web\Controller; use yii\web\HttpException; use yii\web\NotFoundHttpException; use yii\filters\VerbFilter; +use yii\web\Response; + +/** @noinspection PhpUnused */ /** * EventController implements the CRUD actions for Event model. @@ -22,9 +31,9 @@ class EventController extends Controller { public function behaviors() { - $behaviors = [ + $behaviors = [ 'verbs' => [ - 'class' => VerbFilter::className(), + 'class' => VerbFilter::class, 'actions' => [ 'delete' => ['post'], ], @@ -32,24 +41,25 @@ class EventController extends Controller ]; $module = EventModule::getInstance(); - $allowedActions = [ 'index','view', 'reserve-card','cancel-registration','delete-registration' ]; - if ( $module->mode == 'backend' ){ + assert(isset($module), 'event module not set'); + $allowedActions = ['index', 'view', 'reserve-card', 'cancel-registration', 'delete-registration', 'timetable','copy-week']; + if ($module->mode === 'backend') { $allowedActions[] = 'create'; $allowedActions[] = 'update'; $allowedActions[] = 'delete'; } $behaviors['access'] = [ - 'class' => \yii\filters\AccessControl::className(), - 'rules' => [ - // allow authenticated users - [ - 'actions' =>$allowedActions, - 'allow' => true, - 'roles' => ['@'], - ], - // everything else is denied + 'class' => AccessControl::class, + 'rules' => [ + // allow authenticated users + [ + 'actions' => $allowedActions, + 'allow' => true, + 'roles' => ['@'], ], - ]; + // everything else is denied + ], + ]; return $behaviors; } @@ -84,7 +94,7 @@ class EventController extends Controller $dataProvider = new ActiveDataProvider([ - 'query' => $eventRegistrationManager->createFindRegistrationsQuery($id), + 'query' => $eventRegistrationManager->createFindRegistrationsQuery($id), ] ); return $this->render('view', [ @@ -103,13 +113,14 @@ class EventController extends Controller { $model = new Event(); + /** @noinspection NotOptimalIfConditionsInspection */ if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); - } else { - return $this->render('create', [ - 'model' => $model, - ]); } + + return $this->render('create', [ + 'model' => $model, + ]); } /** @@ -123,13 +134,14 @@ class EventController extends Controller { $model = $this->findModel($id); + /** @noinspection NotOptimalIfConditionsInspection */ if ($model->load(Yii::$app->request->post()) && $model->save()) { return $this->redirect(['view', 'id' => $model->id]); - } else { - return $this->render('update', [ - 'model' => $model, - ]); } + + return $this->render('update', [ + 'model' => $model, + ]); } /** @@ -138,65 +150,63 @@ class EventController extends Controller * @param integer $id * @return mixed * @throws NotFoundHttpException - * @throws \yii\db\Exception + * @throws Throwable */ public function actionDelete($id) { $manager = new EventRegistrationManager(); $manager->deleteEvent($this->findModel($id)); return $this->redirect(['index']); - } + }/** @noinspection PhpUnused */ /** * @param $id - * @return \yii\web\Response - * @throws \yii\db\Exception - * @throws \Exception + * @return Response + * @throws Exception */ public function actionCancelRegistration($id) { $eventRegistrationManager = new EventRegistrationManager(); - $db = \Yii::$app->db; + $db = Yii::$app->db; $tx = $db->beginTransaction(); - try{ + try { $registration = $eventRegistrationManager->loadRegistration($id); $eventRegistrationManager->cancelRegistration($registration); $tx->commit(); return $this->redirect(['view', 'id' => $registration->id_event]); - }catch (\Exception $ex){ + } catch (Exception $ex) { $tx->rollBack(); throw $ex; } - } + }/** @noinspection PhpUnused */ /** * @param $id - * @return \yii\web\Response - * @throws \yii\db\Exception - * @throws \Exception + * @return Response + * @throws Exception */ public function actionDeleteRegistration($id) { $eventRegistrationManager = new EventRegistrationManager(); - $db = \Yii::$app->db; + $db = Yii::$app->db; $tx = $db->beginTransaction(); - try{ + try { $registration = $eventRegistrationManager->loadRegistration($id); $eventRegistrationManager->deleteRegistration($registration); $tx->commit(); return $this->redirect(['view', 'id' => $registration->id_event]); - }catch (\Exception $ex){ + } catch (Exception $ex) { $tx->rollBack(); throw $ex; } - } + }/** @noinspection PhpUnused */ /** * @param $id - * @return string|\yii\web\Response + * @return string|Response * @throws NotFoundHttpException - * @throws \yii\db\Exception + * @throws Exception */ public function actionReserveCard($id) { @@ -210,11 +220,11 @@ class EventController extends Controller $manager = new EventRegistrationManager(); try { $manager->registerCard($model); - } catch (HttpException $e) { + } /** @noinspection PhpRedundantCatchClauseInspection */ catch (HttpException $e) { if (array_key_exists($e->getCode(), EventRegistrationManager::$STATES)) { - $model->addError("card_number", Yii::t('event-registration', EventRegistrationManager::$STATES[$e->getCode()])); + $model->addError('card_number', Yii::t('event-registration', EventRegistrationManager::$STATES[$e->getCode()])); } else { - $model->addError("card_number", Yii::t('event-registration', "Unknown Error")); + $model->addError('card_number', Yii::t('event-registration', 'Unknown Error')); } } } @@ -223,9 +233,9 @@ class EventController extends Controller 'model' => $model, 'event' => $event, ]); - } else { - return $this->redirect(['view', 'id' => $id]); } + + return $this->redirect(['view', 'id' => $id]); } return $this->render('register_card', [ 'model' => $model, @@ -233,6 +243,28 @@ class EventController extends Controller ]); } + /** @noinspection PhpUnused */ + /** + * @return string + * @throws Exception + */ + public function actionTimetable() + { + $search = new TimeTableSearch(); + $search->startDateString = (new DateTime())->format('Y.m.d'); + $dataProvider = $search->search(Yii::$app->request->get()); + return $this->render('timetable', array( + 'model' => $search, + 'dataProvider' => $dataProvider + )); + } + + public function actionCopyWeek(){ + $model = new CopyWeekSearch(); + $model->search(\Yii::$app->request->get()); + return $this->render('copy_week',['model' => $model]); + } + /** * Finds the Event model based on its primary key value. * If the model is not found, a 404 HTTP exception will be thrown. @@ -244,8 +276,9 @@ class EventController extends Controller { if (($model = Event::findOne($id)) !== null) { return $model; - } else { - throw new NotFoundHttpException('The requested page does not exist.'); } + + throw new NotFoundHttpException('The requested page does not exist.'); } + } diff --git a/common/modules/event/manager/EventManager.php b/common/modules/event/manager/EventManager.php new file mode 100644 index 0000000..fc95ce1 --- /dev/null +++ b/common/modules/event/manager/EventManager.php @@ -0,0 +1,90 @@ +interval = $interval; + + /** @var DateTime[] $displayDates */ + $displayDates = $interval->getAllDisplayDates(); + + $timeTable->weeks = []; + + /** @var DateTime $displayDate */ + foreach ($displayDates as $displayDate) { + $timeTableMonthDay = new TimeTableMonthDay(); + $timeTableMonthDay->date = $displayDate; + $timeTableMonthDay->active = $interval->isActive($displayDate); + $timeTable->days[] = $timeTableMonthDay; + + $weekNumber = $displayDate->format('W'); + + if (!isset($timeTable->weeks[$weekNumber])) { + $week = new TimeTableMonthWeek(); + $week->weekNumber = $weekNumber; + $timeTable->weeks[$weekNumber] = $week; + } + + $weekDayName = strtolower($displayDate->format('l')); + $timeTable->weeks[$weekNumber]->$weekDayName = $timeTableMonthDay; + } + + // get events between active dates + $query = Event::find(); + $query = $query->select( + [ + '{{event}}.*', +// 'COUNT({{event_registration}}.id) AS reservationCount' + ]); + + $events = $query + ->innerJoinWith('trainer') + ->innerJoinWith('eventType') + ->innerJoinWith('room') + ->joinWith('activeEventRegistrations') + ->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()]) + ->andWhere(['<', 'event.start', (clone $interval->lastActiveDate)->modify('+1 day')->getTimestamp()]) + ->andWhere(['event.active' => '1']) + ->orderBy([ + 'event.start' => SORT_ASC + ]) + ->all(); + + // set events per day + /** @var Event $event */ + foreach ($events as $event) { + $eventDay = new DateTime(); + $eventDay->setTimestamp($event->start); + $eventDay->setTime(0, 0); + + foreach ($timeTable->days as $date) { + if ($date->date == $eventDay) { + $date->events[] = $event; + break; + } + } + } + return $timeTable; + } + +} diff --git a/common/modules/event/models/copy/CopyWeekSearch.php b/common/modules/event/models/copy/CopyWeekSearch.php new file mode 100644 index 0000000..a2299fd --- /dev/null +++ b/common/modules/event/models/copy/CopyWeekSearch.php @@ -0,0 +1,92 @@ + Yii::$app->formatter->dateFormat, 'timestampAttribute' => 'timestampSource', 'timeZone' => 'UTC'], + [['targetDateString',], 'date', 'format' => Yii::$app->formatter->dateFormat, 'timestampAttribute' => 'timestampTarget', 'timeZone' => 'UTC'], + ]; + } + + public function attributeLabels() + { + return [ + 'sourceDateString' => 'Forrás Dátum', + 'targetDateString' => 'Cél Dátum', + ]; + } + + + /** + * Creates data provider instance with search query applied + * + * @param array $params + * + * @throws Exception + */ + public function search($params) + { + + $sourceDate = null; + $targetDate = null; + $this->load($params); + if ($this->validate()) { + + $sourceDate = new DateTime(); + $sourceDate->setTimestamp($this->timestampSource); + + $targetDate = new DateTime(); + $targetDate->setTimestamp($this->timestampTarget); + } + $this->sourceInterval = EventInterval::createInterval($sourceDate,7,7); + $this->targetInterval = EventInterval::createInterval($targetDate,7,7); + + $eventManager = new EventManager(); + $this->sourceTimeTable = $eventManager->loadTimeTable($this->sourceInterval); + $this->targetTimeTable = $eventManager->loadTimeTable($this->targetInterval); + } +} diff --git a/common/modules/event/models/timetable/TimeTableModel.php b/common/modules/event/models/timetable/TimeTableModel.php new file mode 100644 index 0000000..5aeb2a9 --- /dev/null +++ b/common/modules/event/models/timetable/TimeTableModel.php @@ -0,0 +1,13 @@ + $this->weeks + ]); + } + +} diff --git a/common/modules/event/models/timetable/TimeTableMonthDay.php b/common/modules/event/models/timetable/TimeTableMonthDay.php new file mode 100644 index 0000000..e876e8b --- /dev/null +++ b/common/modules/event/models/timetable/TimeTableMonthDay.php @@ -0,0 +1,20 @@ +$objectAttribute; + } + +} diff --git a/common/modules/event/models/timetable/TimeTableSearch.php b/common/modules/event/models/timetable/TimeTableSearch.php new file mode 100644 index 0000000..26a6df2 --- /dev/null +++ b/common/modules/event/models/timetable/TimeTableSearch.php @@ -0,0 +1,86 @@ + Yii::$app->formatter->dateFormat, 'timestampAttribute' => 'timestampStart', 'timeZone' => 'UTC'], + ]; + } + + public function attributeLabels() + { + return [ + 'startDateString' => 'Dátum' + ]; + } + + + /** + * Creates data provider instance with search query applied + * + * @param array $params + * + * @return ArrayDataProvider + * @throws Exception + */ + public function search($params) + { + + $today = null; + $this->load($params); + if ($this->validate()) { + $today = new DateTime( ); + $today->setTimestamp($this->timestampStart); + } + $interval = EventInterval::createInterval($today); + + $em = new EventManager(); + $timeTable = $em->loadTimeTable($interval); + $this->tableModel = new TimeTableModel(); + $this->tableModel->timeTableMonth = $timeTable; + + /** @var DateTime[] $displayDates */ + $displayDates = $interval->getAllDisplayDates(); + + for ($i = 0; $i < 7; $i++) { + $timeTable->weekDayNames[] = DateUtil::getLocalDayName($displayDates[$i]->format('w')); + } + + $this->tableHeaders = ['']; + $this->tableHeaders = array_merge($this->tableHeaders, $timeTable->weekDayNames); + + $dataProvider = new ArrayDataProvider([ + 'allModels' => $timeTable->weeks + ]); + + return $dataProvider; + } +} diff --git a/common/modules/event/views/event/_copy_week_search.php b/common/modules/event/views/event/_copy_week_search.php new file mode 100644 index 0000000..d7a7c02 --- /dev/null +++ b/common/modules/event/views/event/_copy_week_search.php @@ -0,0 +1,57 @@ + + +