Skip to content

Commit

Permalink
Merge pull request #1585 from wielebenwir/experiment/calendar-optimiz…
Browse files Browse the repository at this point in the history
…ation

Performanceverbesserungen Kalenderaufbau
  • Loading branch information
hansmorb authored Jun 22, 2024
2 parents c60046f + 48710fe commit 4647db8
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 52 deletions.
41 changes: 34 additions & 7 deletions src/Model/Calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ class Calendar {
protected Day $endDate;

/**
* @var array
* @var int[]
*/
protected $items;
protected array $items;

/**
* @var array
* @var int[]
*/
protected $locations;
protected array $locations;

/**
* @var array
Expand All @@ -43,13 +43,19 @@ class Calendar {
*/
protected $weeks;

/**
* The timeframes that are relevant for this calendar.
* @var Timeframe[]
*/
protected array $timeframes;

/**
* Calendar constructor.
*
* @param Day $startDate
* @param Day $endDate
* @param array $locations
* @param array $items
* @param int[] $locations
* @param int[] $items
* @param array $types
*/
public function __construct( Day $startDate, Day $endDate, array $locations = [], array $items = [], array $types = [] ) {
Expand All @@ -63,6 +69,8 @@ public function __construct( Day $startDate, Day $endDate, array $locations = []
$this->items = $items;
$this->locations = $locations;
$this->types = $types;

$this->timeframes = $this->getTimeframes();
}

/**
Expand Down Expand Up @@ -96,7 +104,8 @@ public function getWeeks(): array {
$dayOfYear,
$this->locations,
$this->items,
$this->types
$this->types,
$this->timeframes
);
$startDate = strtotime( 'next monday', $startDate );
}
Expand Down Expand Up @@ -171,5 +180,23 @@ public function getAvailabilitySlots(): array {
}
return $slots;
}

private function getTimeframes(): array {
if ( ! isset( $this->timeframes ) ) {
$this->timeframes = [];
$timeframes = \CommonsBooking\Repository\Timeframe::getInRange(
$this->startDate->getStartTimestamp(),
$this->endDate->getEndTimestamp(),
$this->locations,
$this->items,
$this->types,
true,
[ 'confirmed', 'publish' ]
);
$this->timeframes = $timeframes;
}

return $this->timeframes;
}

}
39 changes: 30 additions & 9 deletions src/Model/Day.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class Day {
protected $types;

/**
* @var array
* @var Timeframe[]|null
*/
protected $timeframes;
protected ?array $timeframes = null;

/**
* Day constructor.
Expand All @@ -49,8 +49,9 @@ class Day {
* @param array $locations
* @param array $items
* @param array $types
* @param array $possibleTimeframes
*/
public function __construct( string $date, array $locations = [], array $items = [], array $types = [] ) {
public function __construct( string $date, array $locations = [], array $items = [], array $types = [], array $possibleTimeframes = [] ) {
$this->date = $date;
$this->locations = array_map( function ( $location ) {
return $location instanceof WP_Post ? $location->ID : $location;
Expand All @@ -60,6 +61,11 @@ public function __construct( string $date, array $locations = [], array $items =
}, $items );

$this->types = $types;

if ( ! empty ( $possibleTimeframes ) ) {
$this->timeframes = \CommonsBooking\Repository\Timeframe::filterTimeframesForTimerange( $possibleTimeframes, $this->getStartTimestamp(), $this->getEndTimestamp() );
$this->timeframes = array_filter( $this->timeframes, fn( $timeframe ) => $this->filterTimeframe( $timeframe ) );
}
}

/**
Expand Down Expand Up @@ -124,12 +130,7 @@ public function getTimeframes(): array {

// check if user is allowed to book this timeframe and remove unallowed timeframes from array
// OR: Check for repetition timeframe selected days
foreach ( $timeFrames as $key => $timeframe ) {
if ( ! commonsbooking_isCurrentUserAllowedToBook( $timeframe->ID ) ||
! $this->isInTimeframe( $timeframe )) {
unset( $timeFrames[ $key ] );
}
}
$timeFrames = array_filter( $timeFrames, fn( $timeframe ) => $this->filterTimeframe( $timeframe ) );

$this->timeframes = $timeFrames;
}
Expand Down Expand Up @@ -374,6 +375,26 @@ public function isInTimeframe( \CommonsBooking\Model\Timeframe $timeframe ): boo
return true;
}

/**
* Can be used as a callback to filter timeframes if they belong
* to the day and are bookable for the current user
*
* @param Timeframe $timeframe
*
* @return bool
* @throws Exception
*/
public function filterTimeframe( \CommonsBooking\Model\Timeframe $timeframe ): bool {
if ( ! $this->isInTimeframe( $timeframe ) ) {
return false;
}
if ( ! commonsbooking_isCurrentUserAllowedToBook( $timeframe->ID ) ) {
return false;
}

return true;
}

/**
* Maps timeframes to timeslots.
*
Expand Down
64 changes: 48 additions & 16 deletions src/Model/Timeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,17 @@ class Timeframe extends CustomPost {
*/
public const META_MANUAL_SELECTION = 'timeframe_manual_date';

/**
* null means the data is not fetched yet
* @var int|null
*/
private ?int $repetitionStart = null;
/**
* null means the data is not fetched yet, 0 means there is no end date
* @var int|null
*/
private ?int $repetitionEnd = null;

/**
* Return the span of a timeframe in human-readable format
*
Expand All @@ -92,37 +103,58 @@ public function formattedBookableDate(): string {
*
* @return int
*/
public function getStartDate() : int {
public function getStartDate(): int {
if ( $this->repetitionStart !== null ) {
return $this->repetitionStart;
}

$startDate = $this->getMeta( self::REPETITION_START );

if ( (string) intval( $startDate ) !== $startDate ) {
$startDate = strtotime( $startDate );
} else {
$startDate = intval( $startDate );
}
else {
$startDate = intval ($startDate);
}

$this->repetitionStart = $startDate;

return $startDate;
}

/**
* Return defined end (repetition) date of timeframe.
*
* The timestamps are stored in local time (not in UTC).
* This means that we do not have to do timezone conversion in order to get the corresponding local time.
*
* @return false|int Timestamp of end date, false if no end date is set
*/
public function getTimeframeEndDate() {
$endDate = $this->getMeta( self::REPETITION_END );
/**
* Return defined end (repetition) date of timeframe.
*
* The timestamps are stored in local time (not in UTC).
* This means that we do not have to do timezone conversion in order to get the corresponding local time.
*
* @return false|int Timestamp of end date, false if no end date is set
*/
public function getTimeframeEndDate() {
if ( $this->repetitionEnd !== null ) {
if ( $this->repetitionEnd === 0 ) {
return false;
}
return $this->repetitionEnd;
}

$endDate = $this->getMeta( self::REPETITION_END );

if ( (string) intval( $endDate ) != $endDate ) {
$endDate = strtotime( $endDate );
} else {
$endDate = intval( $endDate );
}

return $endDate;
}
if ( ! $endDate ) {
$this->repetitionEnd = 0;
}
else {
$this->repetitionEnd = $endDate;
}

return $endDate;
}

/**
* Return End (repetition) date and respects advance booking days setting.
* We need this function in order to display the correct end of the booking period for the user.
Expand Down
48 changes: 44 additions & 4 deletions src/Model/Week.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Week {
protected $year;

/**
* Week of year.
* Day in the year to start the week from (0-365)
* @var integer
*/
protected $dayOfYear;
Expand All @@ -40,6 +40,11 @@ class Week {
*/
protected $types;

/**
* @var Timeframe[]
*/
private array $timeframes = [];

/**
* Week constructor.
*
Expand All @@ -48,8 +53,9 @@ class Week {
* @param array $locations
* @param array $items
* @param array $types
* @param Timeframe[] $possibleTimeframes Timeframes that might be relevant for this week, need to be filtered.
*/
public function __construct( $year, $dayOfYear, array $locations = [], array $items = [], array $types = [] ) {
public function __construct( $year, $dayOfYear, array $locations = [], array $items = [], array $types = [], array $possibleTimeframes = [] ) {
if ( $year === null ) {
$year = date( 'Y' );
}
Expand All @@ -58,6 +64,10 @@ public function __construct( $year, $dayOfYear, array $locations = [], array $it
$this->locations = $locations;
$this->items = $items;
$this->types = $types;

if ( ! empty( $possibleTimeframes ) ) {
$this->timeframes = \CommonsBooking\Repository\Timeframe::filterTimeframesForTimerange( $possibleTimeframes, $this->getStartTimestamp(), $this->getEndTimestamp() );
}
}

/**
Expand All @@ -77,15 +87,15 @@ public function getDays() {
if ( $cacheItem ) {
return $cacheItem;
} else {
$yearTimestamp = mktime( 0, 0, 0, 1, 1, $this->year );
$yearTimestamp = $this->getYearTimestamp();
$dayOfYear = $this->dayOfYear;
$timestamp = strtotime( "+ $dayOfYear days", $yearTimestamp );
$dto = Wordpress::getUTCDateTimeByTimestamp( $timestamp );

$days = array();
for ( $i = 0; $i < 7; $i ++ ) {
$dayDate = $dto->format( 'Y-m-d' );
$days[] = new Day( $dayDate, $this->locations, $this->items, $this->types );
$days[] = new Day( $dayDate, $this->locations, $this->items, $this->types, $this->timeframes ?: [] );
$dayOfWeek = $dto->format( 'w' );
if ( $dayOfWeek === '0' ) {
break;
Expand All @@ -101,4 +111,34 @@ public function getDays() {
}
}

/**
* Will return the timestamp of the first second of the given week.
* @return int
*/
public function getStartTimestamp(): int {
$yearTimestamp = $this->getYearTimestamp();
$timestamp = strtotime( "+ $this->dayOfYear days", $yearTimestamp );

return $timestamp;
}

/**
* Will return the timestamp of the last second of the given week.
* @return int
*/
public function getEndTimestamp(): int {
$yearTimestamp = $this->getYearTimestamp();
$timestamp = strtotime( "+ $this->dayOfYear days", $yearTimestamp );
$timestamp = strtotime( '+6 days 23:59:59', $timestamp );

return $timestamp;
}

/**
* @return false|int
*/
private function getYearTimestamp() {
return mktime( 0, 0, 0, 1, 1, $this->year );
}

}
Loading

0 comments on commit 4647db8

Please sign in to comment.