Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CB-Admins von Advance Booking Days ausnehmen #1422

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
3 changes: 2 additions & 1 deletion includes/Users.php
Original file line number Diff line number Diff line change
Expand Up @@ -213,14 +213,15 @@ function commonsbooking_isUserCBManager( \WP_User $user ): bool {

// Check if current user has subscriber role
function commonsbooking_isCurrentUserSubscriber() {
if (! is_user_logged_in() ) { return false; }
$user = wp_get_current_user();

return apply_filters( 'commonsbooking_isCurrentUserSubscriber', in_array( 'subscriber', $user->roles ), $user );
}

// check if current user has CBManager role
function commonsbooking_isCurrentUserCBManager() {

if (! is_user_logged_in() ) { return false; }
$user = wp_get_current_user();

$isManager = ! empty( array_intersect( \CommonsBooking\Repository\UserRepository::getManagerRoles(), $user->roles ) );
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public function getWeeks(): array {
}

// set cache expiration to force daily fresh after midnight
Plugin::setCacheItem( $weeks, array( 'misc' ), $customId, 'midnight' );
Plugin::setCacheItem( $weeks, array( 'misc' ), $customId, true, 'midnight' );

return $weeks;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Day.php
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ protected function getTimeframeSlots(): array {

Plugin::setCacheItem(
$slots,
Wordpress::getTags($this->getTimeframes(), $this->items, $this->locations),
Wordpress::getTags( $this->getTimeframes(), $this->items, $this->locations ),
$customCacheKey
);

Expand Down
24 changes: 20 additions & 4 deletions src/Model/Timeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,7 @@ public function isUserPrivileged(\WP_User $user = null): bool {
*/
public function getLatestPossibleBookingDateTimestamp() {
$calculationBase = time();

// if meta-value not set we define a default value far in the future so that we count all possibly relevant timeframes
$advanceBookingDays = $this->getMeta( TimeFrame::META_TIMEFRAME_ADVANCE_BOOKING_DAYS ) ?: 365;
$advanceBookingDays = $this->getAdvanceBookingDays();

// we subtract one day to reflect the current day in calculation
$advanceBookingDays --;
Expand All @@ -199,6 +197,24 @@ public function getLatestPossibleBookingDateTimestamp() {

}

/**
* Gets the maximum number of days that can be booked in advance.
* @return void
*/
public function getAdvanceBookingDays() {
if ( $this->isUserPrivileged()) {
return 365;
}
else {
//the field is usually empty, when it does not apply to this type of timeframe.
//Timeframes that do not have this field need a big enough number to make sure that they are not filtered out
//See #1357
return intval(
empty( $this->getMeta( self::META_TIMEFRAME_ADVANCE_BOOKING_DAYS ) ) ? 365 : $this->getMeta( self::META_TIMEFRAME_ADVANCE_BOOKING_DAYS )
);
}
}

/**
* This function will get the formatted end date of the timeframe.
* This is used to display the end date of the timeframe in the frontend.
Expand Down Expand Up @@ -864,7 +880,7 @@ public function getGrid(): int {
* Checks if timeframes are overlapping in time ranges or daily slots.
*
* Use {@see Timeframe::overlaps()} if you want to compute full-overlap between two timeframes.
*
*
* @param Timeframe $otherTimeframe
*
* @return bool If start-time and end-time overlaps, regardless of overlapping start-date and end-date.
Expand Down
2 changes: 1 addition & 1 deletion src/Model/Week.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public function getDays() {
}

// set cache expiration to force daily fresh after midnight
Plugin::setCacheItem( $days, array( 'misc' ), $customId, 'midnight' );
Plugin::setCacheItem( $days, array( 'misc' ), $customId, true, 'midnight' );

return $days;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Repository/Restriction.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static function get(
}

$posts = $posts ?: [];
Plugin::setCacheItem( $posts, Wordpress::getTags($posts, $items, $locations), $customCacheKey );
Plugin::setCacheItem( $posts, Wordpress::getTags( $posts, $items, $locations ), $customCacheKey );

return $posts;
}
Expand Down Expand Up @@ -93,7 +93,7 @@ private static function queryPosts( $date, $minTimestamp, $postStatus ) {
";

$posts = $wpdb->get_results( $query );
Plugin::setCacheItem( $posts, Wordpress::getTags($posts) );
Plugin::setCacheItem( $posts, Wordpress::getTags( $posts ) );

return $posts;
}
Expand Down
20 changes: 11 additions & 9 deletions src/Repository/Timeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public static function get(

Plugin::setCacheItem(
$posts,
Wordpress::getTags($posts, $items, $locations),
Wordpress::getTags( $posts, $items, $locations ),
$customId
);
return $posts;
Expand Down Expand Up @@ -191,7 +191,7 @@ public static function getPostIdsByType( array $types = [], array $items = [], a
}

$customId = md5( serialize( $types ) );
$cacheItem = Plugin::getCacheItem( $customId );
$cacheItem = Plugin::getCacheItem( $customId, false );
if ( $cacheItem ) {
return $cacheItem;
} else {
Expand Down Expand Up @@ -255,8 +255,9 @@ public static function getPostIdsByType( array $types = [], array $items = [], a

Plugin::setCacheItem(
$postIds,
Wordpress::getTags($posts, $items, $locations),
$customId
Wordpress::getTags( $posts, $items, $locations ),
$customId,
false
);

return $postIds;
Expand Down Expand Up @@ -309,7 +310,7 @@ private static function getEntityQuery( string $joinAlias, string $table_postmet
* @return array
*/
private static function getPostsByBaseParams( ?string $date, ?int $minTimestamp, ?int $maxTimestamp, array $postIds, array $postStatus ): array {
$cacheItem = Plugin::getCacheItem();
$cacheItem = Plugin::getCacheItem('', false);
if ( $cacheItem ) {
return $cacheItem;
} else {
Expand Down Expand Up @@ -348,7 +349,9 @@ private static function getPostsByBaseParams( ?string $date, ?int $minTimestamp,

Plugin::setCacheItem(
$posts,
Wordpress::getTags($posts, $postIds)
Wordpress::getTags( $posts, $postIds ),
'',
false
);

return $posts;
Expand Down Expand Up @@ -513,7 +516,6 @@ private static function filterTimeframesByConfiguredDays( array $posts, ?string
}

Plugin::setCacheItem( $posts, Wordpress::getTags( $posts ) );

return $posts;
}
}
Expand Down Expand Up @@ -621,7 +623,7 @@ public static function getByLocationItemTimestamp( int $locationId, int $itemId,
date( $time_format, strtotime( $timeframe->getStartTime() ) ) == $startTimestampTime ||
date( $time_format, strtotime( $timeframe->getEndTime() ) ) == $endTimestampTime
) {
Plugin::setCacheItem( $timeframe, [$timeframe->ID, $itemId, $locationId] );
Plugin::setCacheItem( $timeframe, [ $timeframe->ID, $itemId, $locationId ] );

return $timeframe;
}
Expand Down Expand Up @@ -695,7 +697,7 @@ public static function getInRange(

Plugin::setCacheItem(
$posts,
Wordpress::getTags($posts, $locations, $items),
Wordpress::getTags( $posts, $locations, $items ),
$customId
);

Expand Down
30 changes: 29 additions & 1 deletion src/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,35 @@ public static function getOwners(): array {
}

/**
* Returns an array of all User Roles as roleID => translated role name
* Why? Because we have different kinds of caches for a given role type.
* The different caches right now only differentiate between privileged and unprivileged users and managers.
* Depending on the items the manager have been assigned, they could be privileged to some items and unprivileged to others.
* That's why we need to get the user ID for the managers.
* @param \WP_User|null $user
*
* @return int 0 = unprivileged, 1 = privileged, other = manager
*/
public static function getRoleTypeID( \WP_User $user = null ): int {
if ( $user == null ) {
$user = wp_get_current_user();
if ( ! $user ) {
return 0;
}
}
if ( commonsbooking_isUserAdmin( $user ) ) {
return 1;
}
if ( commonsbooking_isUserCBManager( $user ) ) {
return $user->ID;
}

return 0;
}

/**
* Returns an associative array of all User Roles as
* roleID => translated role name
* so that it can be used in the CMB2 select field.
*
* @return array
*/
Expand Down
20 changes: 14 additions & 6 deletions src/Service/Cache.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace CommonsBooking\Service;

use CommonsBooking\Map\MapShortcode;
use CommonsBooking\Repository\UserRepository;
use CommonsBooking\View\Calendar;
use CommonsBooking\Settings\Settings;
use Exception;
Expand All @@ -20,19 +21,20 @@ trait Cache {
/**
* Returns cache item based on calling class, function and args.
*
* @param null $custom_id
* @param null $custom_id custom id to add to cache id
* @param bool $userRoleSensitive if false, the cache will be shared between all users
*
* @return mixed
* @throws InvalidArgumentException
*/
public static function getCacheItem( $custom_id = null ) {
public static function getCacheItem( $custom_id = null, bool $userRoleSensitive = true ) {
if ( WP_DEBUG ) {
return false;
}

try {
/** @var CacheItem $cacheItem */
$cacheKey = self::getCacheId( $custom_id );
$cacheKey = self::getCacheId( $custom_id, $userRoleSensitive );
$cacheItem = self::getCache()->getItem( $cacheKey );
if ( $cacheItem->isHit() ) {
return $cacheItem->get();
Expand All @@ -48,17 +50,22 @@ public static function getCacheItem( $custom_id = null ) {
* @since 2.7.2 added Plugin_Dir to Namespace to avoid conflicts on multiple instances on same server
*
* @param null $custom_id
* @param bool $userRoleSensitive if false, the cache will be shared between all users
*
* @return string
*/
public static function getCacheId( $custom_id = null ): string {
public static function getCacheId( $custom_id = null, bool $userRoleSensitive = true ): string {
$backtrace = debug_backtrace()[2];
$backtrace = self::sanitizeArgsArray( $backtrace );
$namespace = COMMONSBOOKING_PLUGIN_DIR;
$namespace .= '_' . str_replace( '\\', '_', strtolower( $backtrace['class'] ) );
$namespace .= '_' . $backtrace['function'];
$backtraceArgs = $backtrace['args'];
$namespace .= '_' . serialize( $backtraceArgs );
if ( $userRoleSensitive ) {
$userGroupID = UserRepository::getRoleTypeID();
$namespace .= '_' . $userGroupID;
}
if ( $custom_id ) {
$namespace .= $custom_id;
}
Expand Down Expand Up @@ -139,13 +146,14 @@ public static function getCache( string $namespace = '', int $defaultLifetime =
* @param $value
* @param array $tags
* @param null $custom_id
* @param bool $userRoleSensitive if false, the cache will be shared between all users
* @param string|null $expirationString set expiration as timestamp or string 'midnight' to set expiration to 00:00 next day
*
* @return bool
* @throws InvalidArgumentException
* @throws \Psr\Cache\CacheException
*/
public static function setCacheItem( $value, array $tags, $custom_id = null, ?string $expirationString = null ): bool {
public static function setCacheItem( $value, array $tags, $custom_id = null, bool $userRoleSensitive = true, ?string $expirationString = null ): bool {
// Set a default expiration to make sure, that we get rid of stale items, if there are some
// too much space
$expiration = 604800;
Expand All @@ -165,7 +173,7 @@ public static function setCacheItem( $value, array $tags, $custom_id = null, ?st

$cache = self::getCache( '', intval( $expiration ) );
/** @var CacheItem $cacheItem */
$cacheKey = self::getCacheId( $custom_id );
$cacheKey = self::getCacheId( $custom_id, $userRoleSensitive );
$cacheItem = $cache->getItem( $cacheKey );
$cacheItem->tag($tags);
$cacheItem->set( $value );
Expand Down
4 changes: 2 additions & 2 deletions src/View/Calendar.php
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,7 @@ public static function getCalendarDataArray( $item, $location, string $startDate

if ( count( $bookableTimeframes ) ) {
$closestBookableTimeframe = self::getClosestBookableTimeFrameForToday( $bookableTimeframes );
$advanceBookingDays = intval( $closestBookableTimeframe->getFieldValue( 'timeframe-advance-booking-days' ) );
$advanceBookingDays = $closestBookableTimeframe->getAdvanceBookingDays();
$firstBookableDay = $closestBookableTimeframe->getFirstBookableDay();

// Only if passed daterange must not be kept
Expand Down Expand Up @@ -544,7 +544,7 @@ public static function prepareJsonResponse(
}

// set transient expiration time to midnight to force cache refresh by daily basis to allow dynamic advanced booking day feature
Plugin::setCacheItem( $jsonResponse, [ 'misc' ], $customCacheKey, 'midnight' );
Plugin::setCacheItem( $jsonResponse, [ 'misc' ], $customCacheKey, true, 'midnight' );
}

return $jsonResponse;
Expand Down
4 changes: 4 additions & 0 deletions tests/php/Model/TimeframeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,10 @@ public function testGetLatestPossibleBookingDateTimestamp() {
)
);

//do this as a regular user so that we are not unlimited like privileged users
$this->createSubscriber();
wp_set_current_user($this->subscriberId);

$this->assertEquals(
strtotime( '+29 days', strtotime( self::CURRENT_DATE )),
$lateTimeframe->getLatestPossibleBookingDateTimestamp()
Expand Down
8 changes: 8 additions & 0 deletions tests/php/View/CalendarTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ public function testKeepDateRangeParam() {
}

public function testAdvancedBookingDays() {
//set our user to a normal subscriber so that the booking is not privileged
wp_set_current_user( $this->subscriberId);
$startDate = date( 'Y-m-d', strtotime( 'midnight' ) );
$endDate = date( 'Y-m-d', strtotime( '+60 days midnight' ) );
$jsonresponse = Calendar::getCalendarDataArray(
Expand Down Expand Up @@ -71,6 +73,8 @@ public function testAdvancedBookingDays() {
$maxBookableDays = date_diff( $latestPossibleBookingDate, $timeframeStart )->days;

$this->assertTrue( $maxBookableDays == (self::bookingDaysInAdvance - self::timeframeStart - 1) );

wp_logout();
}

public function testClosestBookableTimeFrameFuntion() {
Expand Down Expand Up @@ -146,6 +150,8 @@ public function testBookingOffset() {
30,
2
);
//this has to be done as a regular user
wp_set_current_user( $this->subscriberId );
$jsonresponse = Calendar::getCalendarDataArray(
$otherItemId,
$otherLocationId,
Expand Down Expand Up @@ -189,6 +195,8 @@ protected function setUp() : void {
// set booking days in advance
update_post_meta( $this->timeframeId, Timeframe::META_TIMEFRAME_ADVANCE_BOOKING_DAYS, self::bookingDaysInAdvance );

$this->createSubscriber();

$this->closestTimeframe = $this->createTimeframe(
$this->locationId,
$this->itemId,
Expand Down
5 changes: 5 additions & 0 deletions tests/php/View/ViewTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ protected function setUp() : void {
$now = time();
$this->now = $now;

//set our user to the subscriber so that it is not showing the views for admins ( which don't have to oblige to some booking restrictions )
$this->createSubscriber();
wp_set_current_user( $this->subscriberId );

$this->item = new Item( $this->itemId );
$this->location = new Location( $this->locationId );

Expand Down Expand Up @@ -152,6 +156,7 @@ protected function setUp() : void {
}

protected function tearDown() : void {
wp_logout();
parent::tearDown();
}

Expand Down