Skip to content

Commit

Permalink
Merge pull request #8 from t1k3/fix/date-time-merge
Browse files Browse the repository at this point in the history
Fix/date time merge
  • Loading branch information
t1k3 authored Jul 18, 2019
2 parents 84e4479 + cb1a8f2 commit a960eb3
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 69 deletions.
141 changes: 77 additions & 64 deletions src/Models/CalendarEvent.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace T1k3\LaravelCalendarEvent\Models;

use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use T1k3\LaravelCalendarEvent\Enums\RecurringFrequenceType;
use T1k3\LaravelCalendarEvent\Exceptions\InvalidMonthException;
Expand Down Expand Up @@ -33,7 +34,7 @@ class CalendarEvent extends AbstractModel implements CalendarEventInterface
*/
protected $casts = [
'start_datetime' => 'datetime',
'end_datetime' => 'datetime',
'end_datetime' => 'datetime',
];

/**
Expand Down Expand Up @@ -108,7 +109,7 @@ public function updateCalendarEvent(array $attributes, UserInterface $user = nul
$this->template->toArray(),
[
'start_datetime' => $this->start_datetime,
'end_datetime' => $this->end_datetime,
'end_datetime' => $this->end_datetime,
],
$attributes
),
Expand Down Expand Up @@ -194,81 +195,32 @@ public function deleteCalendarEvent(bool $isRecurring = null)
*/
public static function showPotentialCalendarEventsOfMonth(\DateTimeInterface $date)
{
$endOfRecurring = $date->lastOfMonth();
$month = str_pad($endOfRecurring->month, 2, '0', STR_PAD_LEFT);

$templateCalendarEvents = TemplateCalendarEvent
::where(function ($q) use ($month) {
$q->where('is_recurring', false)
->whereMonth('start_datetime', $month);
})
->orWhere(function ($q) use ($endOfRecurring) {
$q->where('is_recurring', true)
->whereNull('end_of_recurring')
->where('start_datetime', '<=', $endOfRecurring);
})
->orWhere(function ($q) use ($endOfRecurring) {
$q->where('is_recurring', true)
->where('start_datetime', '<=', $endOfRecurring)
->whereMonth('end_of_recurring', '<=', $endOfRecurring);
})
->with('events')
->get();
$endOfRecurring = $date->lastOfMonth()->hour(23)->minute(59)->second(59);
$month = str_pad($endOfRecurring->month, 2, '0', STR_PAD_LEFT);
$templateCalendarEvents = self::getMonthlyEvents($endOfRecurring);

$calendarEvents = collect();
foreach ($templateCalendarEvents as $templateCalendarEvent) {
$calendarEvents = $calendarEvents->merge($templateCalendarEvent->events()
->whereMonth('start_datetime', $month)
->get());
$dateNext = null;
$calendarEventTmpLast = $templateCalendarEvent->events()->orderBy('start_datetime', 'desc')->first();
$calendarEvents = $calendarEvents->merge(
$templateCalendarEvent->events()->whereMonth('start_datetime', $month)->get()
);

if ($calendarEventTmpLast) {
// TODO Refactor: OCP, Strategy
switch ($templateCalendarEvent->frequence_type_of_recurring) {
case RecurringFrequenceType::DAY:
$diff = $date->firstOfMonth()->diffInDays($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addDays($diff);
break;
case RecurringFrequenceType::WEEK:
$diff = $date->firstOfMonth()->diffInWeeks($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addWeeks($diff);
break;
case RecurringFrequenceType::MONTH:
$diff = $date->firstOfMonth()->diffInMonths($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addMonths($diff);
break;
case RecurringFrequenceType::YEAR:
$diff = $date->firstOfMonth()->diffInYears($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addYears($diff);
break;
case RecurringFrequenceType::NTHWEEKDAY:
$diff = $date->firstOfMonth()->diffInMonths($calendarEventTmpLast->start_datetime);
$nextMonth = $calendarEventTmpLast->start_datetime->addMonths($diff);

$weekdays = getWeekdaysInMonth(
$calendarEventTmpLast->start_datetime->format('l'),
$nextMonth
);
$dateNext = $weekdays[$calendarEventTmpLast->start_datetime->weekOfMonth - 1];
}
}
$calendarEventTmpLast = $templateCalendarEvent->events()->orderBy('start_datetime', 'desc')->first();
$dateNext = self::getNextDateFromTemplate($templateCalendarEvent, $calendarEventTmpLast, $date);

while ($dateNext !== null && $dateNext->month <= (int)$month) {
$diffInDays = $templateCalendarEvent->start_datetime->diffInDays($templateCalendarEvent->end_datetime);
while ($dateNext !== null && $dateNext->year == $date->year && $dateNext->month <= (int)$month) {
$diffInDays = $templateCalendarEvent->start_datetime->diffInDays($templateCalendarEvent->end_datetime);
$dateNextEnd = clone($dateNext);
$dateNextEnd = $dateNextEnd->addDays($diffInDays);

$calendarEventNotExists = (new CalendarEvent())->make([
$calendarEventNotExists = (new CalendarEvent())->make([
'start_datetime' => $dateNext,
'end_datetime' => $dateNextEnd,
'end_datetime' => $dateNextEnd,
]);
$calendarEventNotExists->is_not_exists = true;
$calendarEventNotExists->template()->associate($templateCalendarEvent);

if ($calendarEventNotExists->start_datetime->month === (int)$month
&& !$templateCalendarEvent->events()->where('start_datetime', $dateNext)->first()
) {
if ($calendarEventNotExists->start_datetime->month === (int)$month && !$templateCalendarEvent->events()->where('start_datetime', $dateNext)->first()) {
$calendarEvents = $calendarEvents->merge(collect([$calendarEventNotExists]));
}

Expand All @@ -278,4 +230,65 @@ public static function showPotentialCalendarEventsOfMonth(\DateTimeInterface $da

return $calendarEvents;
}

private static function getNextDateFromTemplate(TemplateCalendarEvent $templateCalendarEvent, CalendarEvent $calendarEventTmpLast, \DateTimeInterface $date)
{
$dateNext = null;
// TODO Refactor: OCP, Strategy
if ($calendarEventTmpLast) {
switch ($templateCalendarEvent->frequence_type_of_recurring) {
case RecurringFrequenceType::DAY:
$diff = $calendarEventTmpLast->template->frequence_number_of_recurring;
$dateNext = $calendarEventTmpLast->start_datetime->addDays($diff);
break;
case RecurringFrequenceType::WEEK:
$diff = $date->firstOfMonth()->diffInWeeks($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addWeeks($diff);
break;
case RecurringFrequenceType::MONTH:
$diff = $date->firstOfMonth()->diffInMonths($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addMonths($diff);
break;
case RecurringFrequenceType::YEAR:
$diff = $date->firstOfMonth()->diffInYears($calendarEventTmpLast->start_datetime);
$dateNext = $calendarEventTmpLast->start_datetime->addYears($diff);
break;
case RecurringFrequenceType::NTHWEEKDAY:
$diff = $date->firstOfMonth()->diffInMonths($calendarEventTmpLast->start_datetime);
$nextMonth = $calendarEventTmpLast->start_datetime->addMonths($diff);

$weekdays = getWeekdaysInMonth(
$calendarEventTmpLast->start_datetime->format('l'),
$nextMonth
);
$dateNext = $weekdays[$calendarEventTmpLast->start_datetime->weekOfMonth - 1];
break;
}
}

return $dateNext;
}

private static function getMonthlyEvents(\DateTimeInterface $endOfRecurring): Collection
{
$month = str_pad($endOfRecurring->month, 2, '0', STR_PAD_LEFT);

return TemplateCalendarEvent
::where(function ($q) use ($month) {
$q->where('is_recurring', false)
->whereMonth('start_datetime', $month);
})
->orWhere(function ($q) use ($endOfRecurring) {
$q->where('is_recurring', true)
->whereNull('end_of_recurring')
->where('start_datetime', '<=', $endOfRecurring);
})
->orWhere(function ($q) use ($endOfRecurring) {
$q->where('is_recurring', true)
->where('start_datetime', '<=', $endOfRecurring)
->whereMonth('end_of_recurring', '<=', $endOfRecurring);
})
->with('events')
->get();
}
}
136 changes: 131 additions & 5 deletions tests/Unit/Models/CalendarEventTest.php
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,132 @@ public function eventsOfMonth()
$this->assertTrue($isExist);
}
}


public function dataProvider_for_eventsOfMonth_after_merge_date_time()
{
for ($i = 1; $i <= 31; $i++) {
$array[] = [$i];
}

return $array;
}

/**
* @test
* @dataProvider dataProvider_for_eventsOfMonth_after_merge_date_time
* @param int $day
*/
public function getEventsOfMonth_after_merge_date_time(int $day)
{
$startDateTime = Carbon::parse('2019-07-' . $day . ' 18:00:00');
$this->calendarEvent->createCalendarEvent([
'title' => str_random(16),
'start_datetime' => $startDateTime,
'end_datetime' => clone($startDateTime)->addHours(2),
'description' => str_random(32),
'is_recurring' => true,
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::DAY,
'is_public' => true,
'end_of_recurring' => null,
]);

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-07'));
$this->assertEquals(32 - $day, $calendarEvents->count());
}

/**
* @test
* @dataProvider dataProvider_for_eventsOfMonth_after_merge_date_time
* @param int $day
*/
public function getEventsOfMonth_after_merge_date_time_nextMonth(int $day)
{
$startDateTime = Carbon::parse('2019-07-' . $day . ' 18:00:00');
$this->calendarEvent->createCalendarEvent([
'title' => str_random(16),
'start_datetime' => $startDateTime,
'end_datetime' => (clone($startDateTime))->addHours(2),
'description' => str_random(32),
'is_recurring' => true,
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::DAY,
'is_public' => true,
'end_of_recurring' => null,
]);

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-08'));
$this->assertEquals(31, $calendarEvents->count());
}

/**
* @test
*/
public function getEventsOfMonth_after_merge_date_time_Type_week()
{
$startDateTime = Carbon::parse('2019-07-03 18:00:00');
$this->calendarEvent->createCalendarEvent([
'title' => str_random(16),
'start_datetime' => $startDateTime,
'end_datetime' => (clone($startDateTime))->addHours(2),
'description' => str_random(32),
'is_recurring' => true,
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::WEEK,
'is_public' => true,
'end_of_recurring' => null,
]);

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-07'));
$this->assertEquals(5, $calendarEvents->count());
}

/**
* @test
*/
public function getEventsOfMonth_after_merge_date_time_Type_month()
{
$startDateTime = Carbon::parse('2019-07-18 20:45:00');
$this->calendarEvent->createCalendarEvent([
'title' => str_random(16),
'start_datetime' => $startDateTime,
'end_datetime' => (clone($startDateTime))->addHours(2),
'description' => str_random(32),
'is_recurring' => true,
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::MONTH,
'is_public' => true,
'end_of_recurring' => null,
]);

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-07'));
$this->assertEquals(1, $calendarEvents->count());
$this->assertEquals('2019-07-18 20:45:00', $calendarEvents->first()->start_datetime->format('Y-m-d H:i:s'));
}

/**
* @test
*/
public function getEventsOfMonth_after_merge_date_time_Type_year()
{
$startDateTime = Carbon::parse('2019-07-18 20:00:00');
$this->calendarEvent->createCalendarEvent([
'title' => str_random(16),
'start_datetime' => $startDateTime,
'end_datetime' => (clone($startDateTime))->addHours(2),
'description' => str_random(32),
'is_recurring' => true,
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::YEAR,
'is_public' => true,
'end_of_recurring' => null,
]);

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-07'));
$this->assertEquals(1, $calendarEvents->count());
$this->assertEquals('2019-07-18 20:00:00', $calendarEvents->first()->start_datetime->format('Y-m-d H:i:s'));
}

/**
* @test
*/
Expand All @@ -475,17 +600,18 @@ public function getEventsOfMonth_for_nthweekRecurring()
'frequence_number_of_recurring' => 1,
'frequence_type_of_recurring' => RecurringFrequenceType::NTHWEEKDAY,
'is_public' => true,
'end_of_recurring' => null,
]);


$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-07'));
$this->assertEquals(1, $calendarEvents->count());
$this->assertEquals('2019-07-17', $calendarEvents->first()->start_datetime->format('Y-m-d'));

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-08'));
$this->assertEquals(1, $calendarEvents->count());
$this->assertEquals('2019-08-21', $calendarEvents->first()->start_datetime->format('Y-m-d'));

$calendarEvents = CalendarEvent::showPotentialCalendarEventsOfMonth(Carbon::parse('2019-09'));
$this->assertEquals(1, $calendarEvents->count());
$this->assertEquals('2019-09-18', $calendarEvents->first()->start_datetime->format('Y-m-d'));
Expand Down

0 comments on commit a960eb3

Please sign in to comment.