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

WIP: Create index for #1575 #1769

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
</testsuites>
<php>
<ini name="xdebug.mode" value="coverage" />
<const name="PHPUNIT_COMMONSBOOKING_TESTING" value="true"/>
</php>
<logging>
<testdoxXml outputFile="build/logs/xml.log" />
Expand Down
4 changes: 4 additions & 0 deletions src/Plugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use CommonsBooking\Map\SearchShortcode;
use CommonsBooking\Model\Booking;
use CommonsBooking\Model\BookingCode;
use CommonsBooking\Repository\TimeframeRelations;
use CommonsBooking\Service\BookingRuleApplied;
use CommonsBooking\Service\Cache;
use CommonsBooking\Service\Scheduler;
Expand Down Expand Up @@ -57,6 +58,9 @@ public static function activation() {
// Init booking codes table
BookingCodes::initBookingCodesTable();

//Init Relations Table
TimeframeRelations::initTable();

self::clearCache();
}

Expand Down
29 changes: 24 additions & 5 deletions src/Repository/Timeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public static function get(
$posts = [];

// Get Post-IDs considering types, items and locations
$postIds = self::getPostIdsByType( $types, $items, $locations );
$postIds = self::getPostIdsByType( $types, $items, $locations, $minTimestamp );

if ( $postIds && count( $postIds ) ) {
$posts = self::getPostsByBaseParams(
Expand Down Expand Up @@ -332,7 +332,7 @@ function ( $post ) use ( $args ) {
* @return mixed
* @throws \Psr\Cache\InvalidArgumentException
*/
public static function getPostIdsByType( array $types = [], array $items = [], array $locations = [] ) {
public static function getPostIdsByType( array $types = [], array $items = [], array $locations = [], int $dateTS = null ) {

if ( ! count( $types ) ) {
$types = [
Expand All @@ -349,8 +349,6 @@ public static function getPostIdsByType( array $types = [], array $items = [], a
if ( $cacheItem ) {
return $cacheItem;
} else {
global $wpdb;
$table_postmeta = $wpdb->prefix . 'postmeta';

$items = array_filter( $items );
$locations = array_filter( $locations );
Expand All @@ -360,6 +358,27 @@ public static function getPostIdsByType( array $types = [], array $items = [], a
$locations = commonsbooking_sanitizeArrayorString( $locations, 'intval' );
$types = commonsbooking_sanitizeArrayorString( $types, 'intval' );

//Dirty hooking ourselves our new function
if ( $dateTS != null ) {
$postIds = TimeframeRelations::getRelevantPosts( $locations, $items, $dateTS, $types );


//SAME AS BELOW, TODO DRY YOURSELF
// Get Posts
$posts = array_map(function($post) {
return get_post($post);
}, $postIds);

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

global $wpdb;
$table_postmeta = $wpdb->prefix . 'postmeta';
$itemQuery = '';
if ( count( $items ) > 0 ) {
$itemQuery = self::getEntityQuery(
Expand Down Expand Up @@ -444,7 +463,7 @@ private static function getEntityQuery( string $joinAlias, string $table_postmet
}
$multiLocationQuery = "(
$joinAlias.meta_key = '" . $multiEntityKey . "' AND
(" . implode( ' OR ', $multiLocationQueries ) . ')
(" . implode( ' OR ', $multiLocationQueries ) . ')
)';
$locationQueryParts[] = $multiLocationQuery;

Expand Down
143 changes: 143 additions & 0 deletions src/Repository/TimeframeRelations.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

namespace CommonsBooking\Repository;

class TimeframeRelations
{

public static string $tableName = 'cb_tfrelations';

public static function initTable(): void {
global $wpdb;
//TODO: Add DB versioning

$tableName = $wpdb->prefix . self::$tableName;
$charsetCollate = $wpdb->get_charset_collate();

$sql = "CREATE TABLE IF NOT EXISTS $tableName (
timeframe bigint(20) unsigned NOT NULL,
location bigint(20) unsigned NOT NULL,
item bigint(20) unsigned NOT NULL,
StartDateTime DATETIME NOT NULL,
EndDateTime DATETIME,
tftype tinyint(1) unsigned NOT NULL,
PRIMARY KEY (timeframe, location, item, tftype)
) $charsetCollate;";

$sql .= "CREATE INDEX idx_{$tableName}_daterange ON $tableName (startdatetime, enddatetime);";

// TODO If we choose to use 9999-01-01 as our "infinity"-date instead of null, we can use the datetime columns in the primary key.

require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
dbDelta($sql);
}

public static function insertTimeframe ( \CommonsBooking\Model\Timeframe $timeframe ) {
global $wpdb;

$endTimestamp = $timeframe->getEndDate();

$dateConversionFails = false === date( 'Y-m-d H:i:s', $endTimestamp );
if ( $endTimestamp == 0 || empty( $endTimestamp ) || $dateConversionFails ) {
//$EndDateTime = date('Y-m-d H:i:s', strtotime("+90 days"));
$EndDateTime = 'NULL'; // TODO as 9999-01-01... in case of non-null enddatetime column change
} else {
$EndDateTime = date( 'Y-m-d H:i:s', $endTimestamp );
}


if (self::hasTimeframe($timeframe)) {
return self::updateTimeframe($timeframe);
}
$tableName = $wpdb->prefix . self::$tableName;
$locationIDs = $timeframe->getLocationIDs();
$itemIDs = $timeframe->getItemIDs();
$StartDateTime = date('Y-m-d H:i:s', $timeframe->getStartDate());
$type = $timeframe->getType();

foreach ($locationIDs as $locationID) {
foreach ($itemIDs as $itemID) {
$sql = $wpdb->prepare("INSERT INTO $tableName (timeframe, location, item, StartDateTime, EndDateTime, tftype) VALUES (%d, %d, %d, %s, %s, %d)", $timeframe->ID, $locationID, $itemID, $StartDateTime, $EndDateTime, $type);
$wpdb->query($sql);
//TODO: Mega dirty aber geht
$sql = "UPDATE $tableName SET EndDateTime = NULL WHERE EndDateTime = '0000-00-00 00:00:00'";
$wpdb->query($sql);
}
}
}

public static function updateTimeframe( \CommonsBooking\Model\Timeframe $timeframe ) {
global $wpdb;
$tableName = $wpdb->prefix . self::$tableName;
//This is incredibly dirty and fast, TODO FIX!
$sql = $wpdb->prepare("DELETE FROM $tableName WHERE timeframe = %d", $timeframe->ID);
$wpdb->query($sql);
self::insertTimeframe($timeframe);
}

/**
* To replace the
*
* @see Timeframe::getPostIdsByType()
* @param int[] $locations
* @param int[] $items
* @param int $dateTS
* @param int[] $types
*
* @return int[] Timeframe IDS
*/
public static function getRelevantPosts( array $locations, array $items, int $dateTS, array $types ): array {
global $wpdb;

$DateTime = date( 'Y-m-d H:i:s', $dateTS );

$tableName = $wpdb->prefix . self::$tableName;
$querystring = '';
if ( ! empty ( $locations ) ) {
$locationString = implode( ',', $locations );
if ( strpos( $locationString, '39082') ) {
$hallo = 1;
}
$querystring .= "location IN ($locationString)";
}
if ( ! empty ( $items ) ) {
$itemString = implode( ',', $items );
if ( ! empty ( $querystring ) ) {
$querystring .= ' AND ';
}
$querystring .= "item IN ($itemString)";
}
if ( ! empty ( $types ) ) {
$typeString = implode( ',', $types );
if ( ! empty ( $querystring ) ) {
$querystring .= ' AND ';
}
$querystring .= "tftype IN ($typeString)";
}
if ( $dateTS ) {
if ( ! empty ( $querystring ) ) {
$querystring .= ' AND ';
}
$querystring .= "StartDateTime <= '$DateTime' AND (EndDateTime >= '$DateTime' OR EndDateTime IS NULL)";
}
$sql = "SELECT DISTINCT timeframe FROM $tableName WHERE $querystring";


$sql = $wpdb->prepare( $sql );
$result = $wpdb->get_results($sql);
$ids = [];
foreach ($result as $row) {
$ids[] = $row->timeframe;
}
return $ids;
}

public static function hasTimeframe ( \CommonsBooking\Model\Timeframe $timeframe ): bool {
global $wpdb;
$tableName = $wpdb->prefix . self::$tableName;
$sql = $wpdb->prepare("SELECT * FROM $tableName WHERE timeframe = %d", $timeframe->ID);
$result = $wpdb->get_results($sql);
return count($result) > 0;
}

}
52 changes: 49 additions & 3 deletions src/Service/Upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
use CommonsBooking\Messages\AdminMessage;
use CommonsBooking\Model\Timeframe;
use CommonsBooking\Plugin;
use CommonsBooking\Repository\TimeframeRelations;
use CommonsBooking\Settings\Settings;
use CommonsBooking\Wordpress\CustomPostType\Map;
use CommonsBooking\Wordpress\CustomPostType\CustomPostType;
use CommonsBooking\Wordpress\Options\AdminOptions;
use Psr\Cache\InvalidArgumentException;

Expand All @@ -25,7 +27,8 @@ class Upgrade {
/**
* The number of posts that will be processed in each iteration of the AJAX upgrade tasks.
*/
const POSTS_PER_ITERATION = 10;
//TODO: TEMPORARILY RAISED FOR TESTING PURPOSES
const POSTS_PER_ITERATION = 100;
private string $previousVersion;
private string $currentVersion;

Expand Down Expand Up @@ -75,8 +78,11 @@ class Upgrade {
[ self::class, 'removeBreakingPostmeta' ],
],
'2.9.0' => [
[ self::class, 'setMultiSelectTimeFrameDefault' ],
[ self::class, 'setMultiSelectTimeFrameDefault' ]
],
'2.10.3' => [
[ self::class, 'migrateTimeframeRelations' ]
]
];

/**
Expand All @@ -98,7 +104,13 @@ private function runEveryUpgrade(): void {
Plugin::addCPTRoleCaps();

// update version number in options
update_option( self::VERSION_OPTION, $this->currentVersion );
//TODO: We removed this for testing purpose, READD
//update_option( self::VERSION_OPTION, $this->currentVersion );
//only do in PHPUNIT
if ( defined( 'PHPUNIT_COMMONSBOOKING_TESTING' ) ) {
update_option( self::VERSION_OPTION, $this->currentVersion );
}


// Clear cache
try {
Expand Down Expand Up @@ -561,4 +573,38 @@ function ( $result, $option ) {
}
}
}

public static function migrateTimeframeRelations( int $page = 1 ) {
if ($page == 1 ) {
TimeframeRelations::initTable();
}
$allBookings = \CommonsBooking\Repository\Timeframe::getPostIdsByType( [
\CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_ID,
\CommonsBooking\Wordpress\CustomPostType\Timeframe::HOLIDAYS_ID,
\CommonsBooking\Wordpress\CustomPostType\Timeframe::OFF_HOLIDAYS_ID,
\CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKING_CANCELED_ID,
\CommonsBooking\Wordpress\CustomPostType\Timeframe::BOOKABLE_ID,
\CommonsBooking\Wordpress\CustomPostType\Timeframe::REPAIR_ID]
);
asort( $allBookings );
$currentPage = array_slice( $allBookings, ( $page - 1 ) * self::POSTS_PER_ITERATION, self::POSTS_PER_ITERATION );
if ( empty($currentPage) ) {
//We are done
return true;
}
foreach ( $currentPage as $bookingId ) {
$post = get_post( $bookingId );
if ( $post->post_type == \CommonsBooking\Wordpress\CustomPostType\Timeframe::getPostType() ) {
$model = new Timeframe( $post );
}
elseif ( $post->post_type == \CommonsBooking\Wordpress\CustomPostType\Booking::getPostType() ) {
$model = new \CommonsBooking\Model\Booking( $post );
}
else {
continue;
}
\CommonsBooking\Repository\TimeframeRelations::insertTimeframe( $model );
}
return $page + 1;
}
}
7 changes: 6 additions & 1 deletion src/Wordpress/CustomPostType/Booking.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use CommonsBooking\Exception\TimeframeInvalidException;
use CommonsBooking\Helper\Helper;
use CommonsBooking\Messages\BookingMessage;
use CommonsBooking\Repository\TimeframeRelations;
use CommonsBooking\Service\BookingRuleApplied;
use CommonsBooking\Service\iCalendar;
use Exception;
Expand Down Expand Up @@ -81,7 +82,11 @@ public function initHooks() {
public function savePost( $post_id, $post = null, $update = null ) {
global $pagenow;

$post = $post ?? get_post( $post_id );
//Save relations
$model = new \CommonsBooking\Model\Booking( $post_id );
TimeframeRelations::insertTimeframe( $model );

$post = $post ?? get_post( $post_id );
$is_trash_action = str_contains( ( $_REQUEST ?? array() )['action'] ?? '', 'trash' );

// we check if it's a new created post - TODO: This is not the case
Expand Down
4 changes: 4 additions & 0 deletions src/Wordpress/CustomPostType/Timeframe.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use CommonsBooking\Exception\BookingCodeException;
use CommonsBooking\Exception\TimeframeInvalidException;
use CommonsBooking\Model\BookingCode;
use CommonsBooking\Repository\TimeframeRelations;
use WP_Post;
use Exception;
use CommonsBooking\View\Calendar;
Expand Down Expand Up @@ -907,6 +908,9 @@ public function savePost( $post_id, WP_Post $post ) {
// Validate timeframe
$isValid = self::validateTimeFrame( $timeframe );

// Save to Relations Table
TimeframeRelations::insertTimeframe( $timeframe );

if ( $isValid ) {
self::sanitizeRepetitionEndDate( $post_id );

Expand Down
6 changes: 4 additions & 2 deletions tests/php/Wordpress/CustomPostTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use CommonsBooking\Plugin;
use CommonsBooking\Repository\BookingCodes;
use CommonsBooking\Repository\TimeframeRelations;
use CommonsBooking\Tests\BaseTestCase;
use CommonsBooking\Wordpress\CustomPostType\Booking;
use CommonsBooking\Wordpress\CustomPostType\Item;
Expand Down Expand Up @@ -550,7 +551,8 @@ protected function setUp(): void {

$this->dateFormatted = date( 'Y-m-d', strtotime( self::CURRENT_DATE ) );

$this->setUpBookingCodesTable();
$this->setUpBookingCodesTable();
TimeframeRelations::initTable();

// Create location
$this->locationId = self::createLocation( 'Testlocation', 'publish' );
Expand All @@ -569,7 +571,7 @@ protected function setUpBookingCodesTable() {
location bigint(20) unsigned NOT NULL,
item bigint(20) unsigned NOT NULL,
code varchar(100) NOT NULL,
PRIMARY KEY (date, timeframe, location, item, code)
PRIMARY KEY (date, timeframe, location, item, code)
) $charset_collate;";

$wpdb->query( $sql );
Expand Down
Loading