Endpoint get summit schedule empty spots

Added endpoint

GET /api/v1/summit/{:summit_id}/events/schedule/empty-spots

params

filter

* location_id [==] ( supports OR)
* start_date [>=] (epoch)
* end_date [<=] ( epoch)
* gap [==,<,>,>=,<=] ( in minutes)

Change-Id: I6b4147205c96b32f6f6afc3a771300e588bc7740
This commit is contained in:
Sebastian Marcet 2017-12-08 19:26:18 -03:00
parent dd78b729b6
commit ec1b904092
16 changed files with 631 additions and 40 deletions

View File

@ -32,6 +32,7 @@ use utils\FilterParser;
use utils\FilterParserException;
use utils\OrderParser;
use utils\PagingInfo;
use utils\PagingResponse;
/**
* Class OAuth2SummitEventsApiController
@ -851,7 +852,6 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
}
catch (Exception $ex) {
Log::error($ex);
return $this->error500($ex);
}
}
@ -881,4 +881,60 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
}
}
public function getScheduleEmptySpots($summit_id){
try
{
$summit = SummitFinderStrategyFactory::build($this->repository, $this->resource_server_context)->find($summit_id);
if (is_null($summit)) return $this->error404();
$filter = null;
if (Input::has('filter')) {
$filter = FilterParser::parse(Input::get('filter'), [
'location_id' => ['=='],
'start_date' => ['>='],
'end_date' => ['<='],
'gap' => ['>', '<', '<=', '>=', '=='],
]);
}
if(empty($filter))
throw new ValidationException("filter param is mandatory!");
$gaps = [];
foreach ($this->service->getSummitScheduleEmptySpots($summit, $filter) as $gap)
{
$gaps[] = SerializerRegistry::getInstance()->getSerializer($gap)->serialize();
}
$response = new PagingResponse
(
count($gaps),
count($gaps),
1,
1,
$gaps
);
return $this->ok($response->toArray());
}
catch (EntityNotFoundException $ex1)
{
Log::warning($ex1);
return $this->error404();
}
catch (ValidationException $ex2)
{
Log::warning($ex2);
return $this->error412($ex2->getMessages());
}
catch(FilterParserException $ex3){
Log::warning($ex3);
return $this->error412($ex3->getMessages());
}
catch (Exception $ex)
{
Log::error($ex);
return $this->error500($ex);
}
}
}

View File

@ -356,4 +356,24 @@ final class Filter
}
return $sql;
}
/**
* @param string $field
* @return array
*/
public function getFilterCollectionByField($field){
$list = [];
$filter = $this->getFilter($field);
if(is_array($filter)){
if(is_array($filter[0])){
foreach ($filter[0] as $filter_element)
$list[] = intval($filter_element->getValue());
}
else{
$list[] = intval($filter[0]->getValue());
}
}
return $list;
}
}

View File

@ -23,8 +23,9 @@ final class FilterParser
*/
public static function parse($filters, $allowed_fields = array())
{
$res = [];
$matches = [];
$res = [];
$matches = [];
$and_fields = [];
if (!is_array($filters))
$filters = array($filters);
@ -81,6 +82,10 @@ final class FilterParser
throw new FilterParserException(sprintf("%s op is not allowed for filter by field %s",$op, $field));
}
if(in_array($field, $and_fields))
throw new FilterParserException(sprintf("filter by field %s is already on an and expression", $field));
$and_fields[] = $field;
$f = self::buildFilter($field, $op, $value);
}

View File

@ -26,7 +26,7 @@ final class Order
*/
private $ordering;
public function __construct($ordering = array())
public function __construct($ordering = [])
{
$this->ordering = $ordering;
}

View File

@ -198,7 +198,11 @@ Route::group([
Route::get('', 'OAuth2SummitEventsApiController@getUnpublishedEvents');
//Route::get('{event_id}', 'OAuth2SummitEventsApiController@getUnpublisedEvent');
});
Route::get('/published', 'OAuth2SummitEventsApiController@getScheduledEvents');
Route::group(array('prefix' => 'published'), function () {
Route::get('', 'OAuth2SummitEventsApiController@getScheduledEvents');
Route::get('/empty-spots', 'OAuth2SummitEventsApiController@getScheduleEmptySpots');
});
Route::post('', [ 'middleware' => 'auth.user:administrators', 'uses' => 'OAuth2SummitEventsApiController@addEvent']);
Route::group(array('prefix' => '{event_id}'), function () {

View File

@ -1,4 +1,16 @@
<?php namespace ModelSerializers;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\ModelSerializers\CCLA\TeamSerializer;
use App\ModelSerializers\Marketplace\CloudServiceOfferedSerializer;
use App\ModelSerializers\Marketplace\ConfigurationManagementTypeSerializer;
@ -37,19 +49,11 @@ use ModelSerializers\Locations\SummitVenueFloorSerializer;
use ModelSerializers\Locations\SummitVenueRoomSerializer;
use ModelSerializers\Locations\SummitVenueSerializer;
use App\ModelSerializers\Marketplace\ApplianceSerializer;
use ModelSerializers\SummitScheduleEmptySpotSerializer;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
* Class SerializerRegistry
* @package ModelSerializers
*/
final class SerializerRegistry
{
/**
@ -101,7 +105,7 @@ final class SerializerRegistry
$this->registry['SummitMemberFavorite'] = SummitMemberFavoriteSerializer::class;
$this->registry['SummitEntityEvent'] = SummitEntityEventSerializer::class;
$this->registry['SummitEventWithFile'] = SummitEventWithFileSerializer::class;
$this->registry['SummitScheduleEmptySpot'] = SummitScheduleEmptySpotSerializer::class;
// locations
$this->registry['SummitVenue'] = SummitVenueSerializer::class;
$this->registry['SummitVenueRoom'] = SummitVenueRoomSerializer::class;

View File

@ -0,0 +1,29 @@
<?php namespace ModelSerializers;
/**
* Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Libs\ModelSerializers\AbstractSerializer;
/**
* Class SummitScheduleEmptySpotSerializer
* @package ModelSerializers
*/
final class SummitScheduleEmptySpotSerializer extends AbstractSerializer
{
protected static $array_mappings = [
'LocationId' => 'location_id:json_int',
'StartDateTime' => 'start_date:datetime_epoch',
'EndDateTime' => 'end_date:datetime_epoch',
'TotalMinutes' => 'total_minutes:json_int',
];
}

View File

@ -0,0 +1,83 @@
<?php namespace models\summit;
/**
* Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use DateTime;
/**
* Class SummitScheduleEmptySpot
* @package models\summit
*/
final class SummitScheduleEmptySpot
{
/**
* @var int
*/
private $location_id;
/**
* @var DateTime
*/
private $start_date_time;
/**
* @var DateTime
*/
private $end_date_time;
/**
* SummitScheduleEmptySpot constructor.
* @param int $location_id
* @param DateTime $start_date_time
* @param DateTime $end_date_time
*/
public function __construct($location_id, DateTime $start_date_time, DateTime $end_date_time)
{
$this->location_id = $location_id;
$this->start_date_time = $start_date_time;
$this->end_date_time = $end_date_time;
}
/**
* @return int
*/
public function getLocationId()
{
return $this->location_id;
}
/**
* @return DateTime
*/
public function getStartDateTime()
{
return $this->start_date_time;
}
/**
* @return DateTime
*/
public function getEndDateTime()
{
return $this->end_date_time;
}
/**
* @return int
*/
public function getTotalMinutes(){
$interval = $this->end_date_time->diff($this->start_date_time);
$total_minutes = $interval->days * 24 * 60;
$total_minutes += $interval->h * 60;
$total_minutes += $interval->i;
return intval($total_minutes);
}
}

View File

@ -0,0 +1,51 @@
<?php namespace App\Models\Utils;
/**
* Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
/**
* Class IntervalParser
* @package App\Models\Utils
*/
final class IntervalParser
{
/**
* @param \DateTime $from
* @param \DateTime $to
* @return array
*/
public static function getInterval(\DateTime $from, \DateTime $to){
$intervals = [];
$aux_from = clone $from;
$start_hour = intval($from->format('h'));
$start_min = intval($from->format('i'));
do{
$aux_to = clone $aux_from;
$aux_to->setTime(23, 59, 59);
if($aux_to > $to){
$aux_to = clone $to;
}
$intervals[] = [
$aux_from,
$aux_to
];
$aux_from = clone $aux_from;
$aux_from->add(new \DateInterval('P1D'));
} while($aux_to < $to);
return $intervals;
}
}

View File

@ -1,5 +1,4 @@
<?php namespace App\Repositories\Summit;
/**
* Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
@ -12,7 +11,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Doctrine\ORM\Tools\Pagination\Paginator;
use models\summit\ISummitEventRepository;
use models\summit\SummitEvent;

View File

@ -1,16 +1,4 @@
<?php namespace services\model;
use Illuminate\Http\UploadedFile;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\File;
use models\main\Member;
use models\summit\ConfirmationExternalOrderRequest;
use models\summit\Summit;
use models\summit\SummitAttendee;
use models\summit\SummitEvent;
use models\summit\SummitEventFeedback;
/**
* Copyright 2015 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,6 +11,19 @@ use models\summit\SummitEventFeedback;
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Illuminate\Http\UploadedFile;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\File;
use models\main\Member;
use models\summit\ConfirmationExternalOrderRequest;
use models\summit\Summit;
use models\summit\SummitAttendee;
use models\summit\SummitEvent;
use models\summit\SummitEventFeedback;
use models\summit\SummitScheduleEmptySpot;
use DateTime;
use utils\Filter;
/**
* Interface ISummitService
@ -147,7 +148,7 @@ interface ISummitService
* @param $event_id
* @return bool
*/
public function unRSVPEvent(Summit $summit ,Member $member, $event_id);
public function unRSVPEvent(Summit $summit, Member $member, $event_id);
/**
* @param Summit $summit
@ -159,4 +160,15 @@ interface ISummitService
* @return File
*/
public function addEventAttachment(Summit $summit, $event_id, UploadedFile $file, $max_file_size = 10485760);
/**
* @param Summit $summit
* @param Filter $filter
* @return SummitScheduleEmptySpot[]
*/
public function getSummitScheduleEmptySpots
(
Summit $summit,
Filter $filter
);
}

View File

@ -16,11 +16,11 @@ use App\Events\MyFavoritesRemove;
use App\Events\MyScheduleAdd;
use App\Events\MyScheduleRemove;
use App\Http\Utils\FileUploader;
use App\Models\Utils\IntervalParser;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\Storage;
use models\exceptions\EntityNotFoundException;
use models\exceptions\ValidationException;
use models\main\File;
@ -55,11 +55,19 @@ use models\summit\SummitEventFeedback;
use models\summit\SummitEventType;
use models\summit\SummitEventWithFile;
use models\summit\SummitGroupEvent;
use models\summit\SummitScheduleEmptySpot;
use services\apis\IEventbriteAPI;
use libs\utils\ITransactionService;
use Exception;
use DateTime;
use Illuminate\Support\Facades\Log;
use utils\Filter;
use utils\FilterElement;
use utils\FilterParser;
use utils\Order;
use utils\OrderElement;
use utils\PagingInfo;
use DateInterval;
/**
* Class SummitService
* @package services\model
@ -1158,4 +1166,170 @@ final class SummitService implements ISummitService
return $attachment;
});
}
/**
* @param Summit $summit
* @param Filter $filter
* @return SummitScheduleEmptySpot[]
*/
public function getSummitScheduleEmptySpots
(
Summit $summit,
Filter $filter
)
{
return $this->tx_service->transaction(function () use
(
$summit,
$filter
){
$gaps = [];
$order = new Order([
OrderElement::buildAscFor("location_id"),
OrderElement::buildAscFor("start_date"),
]);
// parse locations ids
if(!$filter->hasFilter('location_id'))
throw new ValidationException("missing required filter location_id");
$location_ids = $filter->getFilterCollectionByField('location_id');
// parse start_date filter
$start_datetime_filter = $filter->getFilter('start_date');
if(is_null($start_datetime_filter))
throw new ValidationException("missing required filter start_date");
$start_datetime_unix = intval($start_datetime_filter[0]->getValue());
$start_datetime = new \DateTime("@$start_datetime_unix");
// parse end_date filter
$end_datetime_filter = $filter->getFilter('end_date');
if(is_null($end_datetime_filter))
throw new ValidationException("missing required filter end_date");
$end_datetime_unix = intval($end_datetime_filter[0]->getValue());
$end_datetime = new \DateTime("@$end_datetime_unix");
// gap size filter
$gap_size_filter = $filter->getFilter('gap');
if(is_null($end_datetime_filter))
throw new ValidationException("missing required filter gap");
$gap_size = $gap_size_filter[0];
$summit_time_zone = $summit->getTimeZone();
$start_datetime->setTimezone($summit_time_zone);
$end_datetime->setTimezone($summit_time_zone);
$intervals = IntervalParser::getInterval($start_datetime, $end_datetime);
foreach($location_ids as $location_id) {
foreach($intervals as $interval) {
$events_filter = new Filter();
$events_filter->addFilterCondition(FilterParser::buildFilter('published', '==', '1'));
$events_filter->addFilterCondition(FilterParser::buildFilter('summit_id', '==', $summit->getId()));
$events_filter->addFilterCondition(FilterParser::buildFilter('location_id', '==', intval($location_id)));
$events_filter->addFilterCondition(FilterParser::buildFilter('start_date', '>=', $interval[0]->getTimestamp()));
$events_filter->addFilterCondition(FilterParser::buildFilter('end_date', '<=', $interval[1]->getTimestamp()));
$paging_response = $this->event_repository->getAllByPage
(
new PagingInfo(1, PHP_INT_MAX),
$events_filter,
$order
);
$gap_start_date = $interval[0];
$gap_end_date = clone $gap_start_date;
// check published items
foreach ($paging_response->getItems() as $event) {
while
(
(
$gap_end_date->getTimestamp() + (self::MIN_EVENT_MINUTES * 60)
)
<= $event->getLocalStartDate()->getTimestamp()
) {
$max_gap_end_date = clone $gap_end_date;
$max_gap_end_date->setTime(23, 59, 59);
if ($gap_end_date->getTimestamp() + (self::MIN_EVENT_MINUTES * 60) > $max_gap_end_date->getTimestamp()) break;
$gap_end_date->add(new DateInterval('PT' . self::MIN_EVENT_MINUTES . 'M'));
}
if ($gap_start_date->getTimestamp() == $gap_end_date->getTimestamp()) {
// no gap!
$gap_start_date = $event->getLocalEndDate();
$gap_end_date = clone $gap_start_date;
continue;
}
// check min gap ...
if(self::checkGapCriteria($gap_size, $gap_end_date->diff($gap_start_date)))
$gaps[] = new SummitScheduleEmptySpot($location_id, $gap_start_date, $gap_end_date);
$gap_start_date = $event->getLocalEndDate();
$gap_end_date = clone $gap_start_date;
}
// check last possible gap ( from last $gap_start_date till $interval[1]
if($gap_start_date < $interval[1]){
// last possible gap
if(self::checkGapCriteria($gap_size, $interval[1]->diff($gap_start_date)))
$gaps[] = new SummitScheduleEmptySpot($location_id, $gap_start_date, $interval[1]);
}
}
}
return $gaps;
});
}
/**
* @param FilterElement $gap_size_criteria
* @param DateInterval $interval
* @return bool
*/
private static function checkGapCriteria
(
FilterElement $gap_size_criteria,
DateInterval $interval
)
{
$total_minutes = $interval->days * 24 * 60;
$total_minutes += $interval->h * 60;
$total_minutes += $interval->i;
switch($gap_size_criteria->getOperator()){
case '=':
{
return intval($gap_size_criteria->getValue()) == $total_minutes;
}
break;
case '<':
{
return $total_minutes < intval($gap_size_criteria->getValue());
}
break;
case '>':
{
return $total_minutes > intval($gap_size_criteria->getValue());
}
break;
case '<=':
{
return $total_minutes <= intval($gap_size_criteria->getValue());
}
break;
case '>=':
{
return $total_minutes >= intval($gap_size_criteria->getValue());
}
break;
}
return false;
}
}

View File

@ -200,6 +200,15 @@ class ApiEndpointsSeeder extends Seeder
sprintf(SummitScopes::ReadAllSummitData, $current_realm)
],
),
array(
'name' => 'get-schedule-empty-spots',
'route' => '/api/v1/summits/{id}/events/published/empty-spots',
'http_method' => 'GET',
'scopes' => [
sprintf(SummitScopes::ReadSummitData, $current_realm),
sprintf(SummitScopes::ReadAllSummitData, $current_realm)
],
),
array(
'name' => 'get-unpublished-events',
'route' => '/api/v1/summits/{id}/events/unpublished',

View File

@ -15,7 +15,6 @@ use models\summit\IAbstractCalendarSyncWorkRequestRepository;
use models\summit\ICalendarSyncInfoRepository;
use models\summit\SummitEvent;
use models\summit\CalendarSync\WorkQueue\AdminSummitEventActionSyncWorkRequest;
use models\summit\CalendarSync\WorkQueue\AdminSummitLocationActionSyncWorkRequest;
use models\summit\CalendarSync\WorkQueue\AbstractCalendarSyncWorkRequest;
/**
* Class AdminActionsCalendarSyncPreProcessorTest

View File

@ -1,5 +1,4 @@
<?php
/**
* Copyright 2015 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
@ -12,6 +11,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use LaravelDoctrine\ORM\Facades\EntityManager;
/**
* Class OAuth2SummitApiTest
*/
final class OAuth2SummitApiTest extends ProtectedApiTest
{
@ -1897,11 +1901,11 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
{
$params = array
(
'id' => $summit_id,
'page' => 1,
'per_page' => 50,
'id' => $summit_id,
'page' => 1,
'per_page' => 50,
'location_id' => 52,
'filter' => array
'filter' => array
(
'tags=@Nova',
'speaker=@Todd'
@ -2460,4 +2464,50 @@ final class OAuth2SummitApiTest extends ProtectedApiTest
}
public function testGetScheduleEmptySpotsBySummit()
{
$summit_repository = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $summit_repository->getById(23);
$summit_time_zone = $summit->getTimeZone();
$start_datetime = new DateTime( "2017-11-04 07:00:00", $summit_time_zone);
$end_datetime = new DateTime("2017-11-05 18:00:00", $summit_time_zone);
$start_datetime_unix = $start_datetime->getTimestamp();
$end_datetime_unix = $end_datetime->getTimestamp();
$params = [
'id' => 23,
'filter' =>
[
'location_id==318,location_id==320',
'start_date>='.$start_datetime_unix,
'end_date<='.$end_datetime_unix,
'gap==10',
],
];
$headers = [
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
];
$response = $this->action
(
"GET",
"OAuth2SummitEventsApiController@getScheduleEmptySpots",
$params,
[],
[],
[],
$headers
);
$content = $response->getContent();
$this->assertResponseStatus(200);
$gaps = json_decode($content);
$this->assertTrue(!is_null($gaps));
}
}

View File

@ -0,0 +1,97 @@
<?php
/**
* Copyright 2017 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use Illuminate\Support\Facades\App;
use LaravelDoctrine\ORM\Facades\EntityManager;
use App\Models\Utils\IntervalParser;
use services\model\ISummitService;
use utils\FilterParser;
/**
* Class SearchEmptySpotsTest
*/
final class SearchEmptySpotsTest extends TestCase
{
public function testIntervalParser2(){
$summit_repository = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $summit_repository->getById(23);
$summit_time_zone = $summit->getTimeZone();
$start_datetime = new DateTime( "2017-11-04 07:00:00", $summit_time_zone);
$end_datetime = new DateTime("2017-11-05 18:00:00", $summit_time_zone);
$intervals = IntervalParser::getInterval($start_datetime, $end_datetime);
$this->assertTrue(count($intervals) == 2);
}
public function testIntervalParse1(){
$summit_repository = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $summit_repository->getById(23);
$summit_time_zone = $summit->getTimeZone();
$start_datetime = new DateTime( "2017-11-04 07:00:00", $summit_time_zone);
$end_datetime = new DateTime("2017-11-04 18:00:00", $summit_time_zone);
$intervals = IntervalParser::getInterval($start_datetime, $end_datetime);
$this->assertTrue(count($intervals) == 1);
}
public function testIntervalParser3(){
$summit_repository = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $summit_repository->getById(23);
$summit_time_zone = $summit->getTimeZone();
$start_datetime = new DateTime( "2017-11-04 07:00:00", $summit_time_zone);
$end_datetime = new DateTime("2017-11-06 18:00:00", $summit_time_zone);
$intervals = IntervalParser::getInterval($start_datetime, $end_datetime);
$this->assertTrue(count($intervals) == 4);
}
public function testFindSpots(){
$summit_repository = EntityManager::getRepository(\models\summit\Summit::class);
$summit = $summit_repository->getById(23);
$summit_time_zone = $summit->getTimeZone();
$start_datetime = new DateTime( "2017-11-04 07:00:00", $summit_time_zone);
$end_datetime = new DateTime("2017-11-05 18:00:00", $summit_time_zone);
$start_datetime_unix = $start_datetime->getTimestamp();
$end_datetime_unix = $end_datetime->getTimestamp();
$service = App::make(\services\model\ISummitService::class);
if(!$service instanceof ISummitService )
return ;
$filter = FilterParser::parse
(
[
'location_id==318,location_id==320',
'start_date>='.$start_datetime_unix,
'end_date<='.$end_datetime_unix,
'gap==10',
],
[
'location_id' => ['=='],
'start_date' => ['>='],
'end_date' => ['<='],
'gap' => ['>', '<', '<=', '>=', '=='],
]
);
$gaps = $service->getSummitScheduleEmptySpots($summit, $filter);
$this->assertTrue(count($gaps) > 0);
}
}