diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersAssistanceApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersAssistanceApiController.php new file mode 100644 index 00000000..3e891f0f --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersAssistanceApiController.php @@ -0,0 +1,157 @@ +summit_repository = $summit_repository; + $this->speakers_assistance_repository = $speakers_assistance_repository; + } + + /** + * @param $summit_id + * @return mixed + */ + public function getBySummit($summit_id){ + try { + $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $values = Input::all(); + + $rules = array + ( + 'page' => 'integer|min:1', + 'per_page' => 'required_with:page|integer|min:10|max:100', + ); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) + { + $messages = $validation->messages()->toArray(); + + return $this->error412($messages); + } + + // default values + $page = 1; + $per_page = 10; + + if (Input::has('page')) + { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + + if (Input::has('filter')) + { + $filter = FilterParser::parse(Input::get('filter'), [ + 'id' => ['=='], + 'on_site_phone' => ['==', '=@'], + 'speaker_email' => ['==', '=@'], + 'speaker' => ['==', '=@'], + 'is_confirmed' => ['=='], + 'registered' => ['=='], + 'confirmation_date' => ['>', '<', '>=', '<='] + ]); + } + + $order = null; + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), [ + 'id', + 'is_confirmed', + 'confirmation_date', + 'created', + 'registered', + ]); + } + + $serializer_type = SerializerRegistry::SerializerType_Private; + $result = $this->speakers_assistance_repository->getBySummit($summit, new PagingInfo($page, $per_page), $filter, $order); + + return $this->ok + ( + $result->toArray + ( + Request::input('expand', ''), + [], + [], + [ + 'summit' => $summit, + 'serializer_type' => $serializer_type + ], + $serializer_type + ) + ); + } + catch(ValidationException $ex1){ + Log::warning($ex1); + return $this->error412($ex1->getMessages()); + } + catch(EntityNotFoundException $ex2) + { + Log::warning($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + catch (\Exception $ex) + { + Log::error($ex); + return $this->error500($ex); + } + } +} \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index 77a8c235..dfeed573 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -214,6 +214,12 @@ Route::group([ }); }); + // speakers assistance + Route::group(['prefix' => 'speakers-assistances'], function () { + Route::get('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitSpeakersAssistanceApiController@getBySummit']); + }); + + // events Route::group(array('prefix' => 'events'), function () { diff --git a/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php b/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php index 3e9dddda..f2ee3f0b 100644 --- a/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php +++ b/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php @@ -11,18 +11,61 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ + +use models\summit\PresentationSpeakerSummitAssistanceConfirmationRequest; + /** * Class PresentationSpeakerSummitAssistanceConfirmationRequestSerializer * @package ModelSerializers */ -final class PresentationSpeakerSummitAssistanceConfirmationRequestSerializer extends SilverStripeSerializer +final class PresentationSpeakerSummitAssistanceConfirmationRequestSerializer + extends SilverStripeSerializer { protected static $array_mappings = [ - 'OnSitePhone' => 'on_site_phone:json_string', - 'Registered' => 'registered:json_boolean', - 'Confirmed' => 'is_confirmed:json_boolean', - 'CheckedIn' => 'checked_in:json_boolean', - 'SummitId' => 'summit_id:json_int', - 'SpeakerId' => 'speaker_id:json_int', + 'OnSitePhone' => 'on_site_phone:json_string', + 'Registered' => 'registered:json_boolean', + 'Confirmed' => 'is_confirmed:json_boolean', + 'CheckedIn' => 'checked_in:json_boolean', + 'SummitId' => 'summit_id:json_int', + 'SpeakerId' => 'speaker_id:json_int', + 'ConfirmationDate' => 'confirmation_date:datetime_epoch', ]; + + /** + * @param null $expand + * @param array $fields + * @param array $relations + * @param array $params + * @return array + */ + public function serialize($expand = null, array $fields = array(), array $relations = array(), array $params = array() ) + { + if(!count($relations)) $relations = $this->getAllowedRelations(); + + $request = $this->object; + + if(!$request instanceof PresentationSpeakerSummitAssistanceConfirmationRequest) return []; + + $serializer_type = SerializerRegistry::SerializerType_Public; + + if(isset($params['serializer_type'])) + $serializer_type = $params['serializer_type']; + + $values = parent::serialize($expand, $fields, $relations, $params); + + if (!empty($expand)) { + foreach (explode(',', $expand) as $relation) { + switch (trim($relation)) { + case 'speaker': { + if(isset($values['speaker_id']) && intval($values['speaker_id']) > 0 ){ + unset($values['speaker_id']); + $values['speaker'] = SerializerRegistry::getInstance()->getSerializer($request->getSpeaker(), $serializer_type)->serialize(); + } + } + break; + } + } + } + return $values; + } } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/Presentations/PresentationSpeakerSummitAssistanceConfirmationRequest.php b/app/Models/Foundation/Summit/Events/Presentations/PresentationSpeakerSummitAssistanceConfirmationRequest.php index 01c7e94a..373f7f00 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/PresentationSpeakerSummitAssistanceConfirmationRequest.php +++ b/app/Models/Foundation/Summit/Events/Presentations/PresentationSpeakerSummitAssistanceConfirmationRequest.php @@ -15,7 +15,7 @@ use models\utils\SilverstripeBaseModel; use Doctrine\ORM\Mapping AS ORM; /** * Class PresentationSpeakerSummitAssistanceConfirmationRequest - * @ORM\Entity + * @ORM\Entity(repositoryClass="App\Repositories\Summit\DoctrinePresentationSpeakerSummitAssistanceConfirmationRequestRepository") * @ORM\Table(name="PresentationSpeakerSummitAssistanceConfirmationRequest") * @package models\summit */ @@ -45,6 +45,12 @@ class PresentationSpeakerSummitAssistanceConfirmationRequest extends Silverstrip */ private $checked_in; + /** + * @ORM\Column(name="ConfirmationDate", type="datetime") + * @var \DateTime + */ + private $confirmation_date; + /** * @ORM\ManyToOne(targetEntity="PresentationSpeaker") * @ORM\JoinColumn(name="SpeakerID", referencedColumnName="ID") @@ -145,4 +151,20 @@ class PresentationSpeakerSummitAssistanceConfirmationRequest extends Silverstrip return 0; } } + + /** + * @return \DateTime + */ + public function getConfirmationDate() + { + return $this->confirmation_date; + } + + /** + * @param \DateTime $confirmation_date + */ + public function setConfirmationDate(\DateTime $confirmation_date) + { + $this->confirmation_date = $confirmation_date; + } } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Repositories/IPresentationSpeakerSummitAssistanceConfirmationRequestRepository.php b/app/Models/Foundation/Summit/Repositories/IPresentationSpeakerSummitAssistanceConfirmationRequestRepository.php new file mode 100644 index 00000000..792092e1 --- /dev/null +++ b/app/Models/Foundation/Summit/Repositories/IPresentationSpeakerSummitAssistanceConfirmationRequestRepository.php @@ -0,0 +1,35 @@ + 'r.id:json_int', + 'on_site_phone' => 'r.on_site_phone:json_string', + 'is_confirmed' => 'r.is_confirmed', + 'registered' => 'r.registered', + 'confirmation_date' => 'r.confirmation_date:datetime_epoch', + 'speaker' => new DoctrineFilterMapping + ( + "( concat(spkr.first_name, ' ', spkr.last_name) :operator ':value' ". + "OR concat(spmm.first_name, ' ', spmm.last_name) :operator ':value' ". + "OR spkr.first_name :operator ':value' ". + "OR spkr.last_name :operator ':value' ". + "OR spmm.first_name :operator ':value' ". + "OR spmm.last_name :operator ':value' )" + ), + 'speaker_email' => new DoctrineFilterMapping + ( + "(sprr.email :operator ':value' OR spmm.email :operator ':value')" + ), + ]; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'created' => 'r.created', + 'confirmation_date' => 'r.confirmation_date', + 'id' => 'r.id', + 'is_confirmed' => 'r.is_confirmed', + 'registered' => 'r.registered' + ]; + } + + /** + * @param Summit $summit + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return PagingResponse + */ + public function getBySummit(Summit $summit, PagingInfo $paging_info, Filter $filter = null, Order $order = null) + { + $query = $this->getEntityManager() + ->createQueryBuilder() + ->select("r") + ->from(PresentationSpeakerSummitAssistanceConfirmationRequest::class, "r") + ->leftJoin('r.summit', 's') + ->leftJoin('r.speaker', 'spkr') + ->leftJoin('spkr.member', "spmm", Join::LEFT_JOIN) + ->leftJoin('spkr.registration_request', "sprr", Join::LEFT_JOIN) + ->where("s.id = :summit_id"); + + $query->setParameter("summit_id", $summit->getId()); + + if(!is_null($filter)){ + $filter->apply2Query($query, $this->getFilterMappings()); + } + + if (!is_null($order)) { + $order->apply2Query($query, $this->getOrderMappings()); + } else { + //default order + $query = $query->addOrderBy("r.id",'ASC'); + } + + $query = $query + ->setFirstResult($paging_info->getOffset()) + ->setMaxResults($paging_info->getPerPage()); + + $paginator = new Paginator($query, $fetchJoinCollection = true); + $total = $paginator->count(); + $data = []; + + foreach($paginator as $entity) + $data[] = $entity; + + return new PagingResponse + ( + $total, + $paging_info->getPerPage(), + $paging_info->getCurrentPage(), + $paging_info->getLastPage($total), + $data + ); + } +} \ No newline at end of file diff --git a/app/Repositories/Summit/DoctrineSummitRegistrationPromoCodeRepository.php b/app/Repositories/Summit/DoctrineSummitRegistrationPromoCodeRepository.php index f9119eaf..16ba7d0f 100644 --- a/app/Repositories/Summit/DoctrineSummitRegistrationPromoCodeRepository.php +++ b/app/Repositories/Summit/DoctrineSummitRegistrationPromoCodeRepository.php @@ -13,7 +13,6 @@ **/ use App\Repositories\SilverStripeDoctrineRepository; use Doctrine\ORM\Query\Expr\Join; -use Doctrine\ORM\QueryBuilder; use models\summit\ISummitRegistrationPromoCodeRepository; use models\summit\MemberSummitRegistrationPromoCode; use models\summit\SpeakerSummitRegistrationPromoCode; @@ -22,8 +21,6 @@ use models\summit\Summit; use models\summit\SummitRegistrationPromoCode; use utils\DoctrineFilterMapping; use utils\DoctrineInstanceOfFilterMapping; -use utils\DoctrineJoinFilterMapping; -use utils\DoctrineLeftJoinFilterMapping; use utils\Filter; use utils\Order; use utils\PagingInfo; diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 657b84b2..62551102 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -687,7 +687,6 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/promo-codes', 'http_method' => 'GET', 'scopes' => [ - sprintf(SummitScopes::ReadSummitData, $current_realm), sprintf(SummitScopes::ReadAllSummitData, $current_realm) ], ], @@ -696,7 +695,6 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/promo-codes/{promo_code_id}', 'http_method' => 'GET', 'scopes' => [ - sprintf(SummitScopes::ReadSummitData, $current_realm), sprintf(SummitScopes::ReadAllSummitData, $current_realm) ], ], @@ -741,10 +739,17 @@ class ApiEndpointsSeeder extends Seeder 'route' => '/api/v1/summits/{id}/promo-codes/metadata', 'http_method' => 'GET', 'scopes' => [ - sprintf(SummitScopes::ReadSummitData, $current_realm), sprintf(SummitScopes::ReadAllSummitData, $current_realm) ], - ] + ], + array( + 'name' => 'get-speaker-assistances-by-summit', + 'route' => '/api/v1/summits/{id}/speakers-assistances', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SummitScopes::ReadAllSummitData, $current_realm) + ], + ), ]); } diff --git a/tests/OAuth2SpeakersAssistancesApiTest.php b/tests/OAuth2SpeakersAssistancesApiTest.php new file mode 100644 index 00000000..04d7ed63 --- /dev/null +++ b/tests/OAuth2SpeakersAssistancesApiTest.php @@ -0,0 +1,85 @@ + $summit_id, + 'page' => 1, + 'per_page' => 10, + 'order' => '+id', + 'expand' => 'speaker,summit' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitSpeakersAssistanceApiController@getBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $assistances = json_decode($content); + $this->assertTrue(!is_null($assistances)); + } + + public function testGetAllBySummitAndConfirmed($summit_id = 23){ + + $params = [ + + 'id' => $summit_id, + 'page' => 1, + 'per_page' => 10, + 'filter' => 'is_confirmed==1', + 'order' => '+id', + 'expand' => 'speaker' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitSpeakersAssistanceApiController@getBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $assistances = json_decode($content); + $this->assertTrue(!is_null($assistances)); + } + +} \ No newline at end of file