From ff8a664d959017613a10fd62af3949dd13504a89 Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Mon, 13 Aug 2018 18:39:15 -0300 Subject: [PATCH] Added endpoints to add/remove speakers from my presentations DELETE /api/v1/speakers/me/presentations/{presentation_id}/speakers/{speaker_id} PUT /api/v1/speakers/me/presentations/{presentation_id}/speakers/{speaker_id} Required Scopes * /summits/write * /speakers/write * /speakers/write/me Change-Id: I1a262445b3b4342a983b169add63f3c9731e960b --- .../OAuth2SummitSpeakersApiController.php | 64 ++++++++++++++- app/Http/routes.php | 10 +++ .../Events/Presentations/Presentation.php | 20 +++++ app/Services/Model/ISummitService.php | 20 +++++ app/Services/Model/SummitService.php | 81 +++++++++++++++++++ database/seeds/ApiEndpointsSeeder.php | 20 +++++ 6 files changed, 214 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php index 0c5f386e..b40d7914 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSpeakersApiController.php @@ -13,7 +13,6 @@ * limitations under the License. **/ use App\Models\Foundation\Summit\Repositories\ISelectionPlanRepository; -use App\Services\Model\ISummitSelectionPlanService; use Exception; use Illuminate\Support\Facades\Input; use Illuminate\Support\Facades\Log; @@ -32,6 +31,7 @@ use models\summit\PresentationSpeaker; use ModelSerializers\ISerializerTypeSelector; use ModelSerializers\SerializerRegistry; use services\model\ISpeakerService; +use services\model\ISummitService; use utils\FilterParser; use utils\OrderParser; use utils\PagingInfo; @@ -80,6 +80,12 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController */ private $selection_plan_repository; + + /** + * @var ISummitService + */ + private $summit_service; + /** * OAuth2SummitSpeakersApiController constructor. * @param ISummitRepository $summit_repository @@ -89,6 +95,7 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController * @param IMemberRepository $member_repository * @param ISelectionPlanRepository $selection_plan_repository * @param ISpeakerService $service + * @param ISummitService $summit_service * @param ISerializerTypeSelector $serializer_type_selector * @param IResourceServerContext $resource_server_context */ @@ -101,6 +108,7 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController IMemberRepository $member_repository, ISelectionPlanRepository $selection_plan_repository, ISpeakerService $service, + ISummitService $summit_service, ISerializerTypeSelector $serializer_type_selector, IResourceServerContext $resource_server_context ) @@ -113,6 +121,7 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController $this->event_feedback_repository = $event_feedback_repository; $this->selection_plan_repository = $selection_plan_repository; $this->service = $service; + $this->summit_service = $summit_service; $this->serializer_type_selector = $serializer_type_selector; } @@ -829,4 +838,57 @@ final class OAuth2SummitSpeakersApiController extends OAuth2ProtectedController } } + /** + * @param $presentation_id + * @param $speaker_id + * @return mixed + */ + public function addSpeakerToMyPresentation($presentation_id, $speaker_id){ + try { + $current_member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($current_member_id)) + return $this->error403(); + + $this->summit_service->addSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id); + + return $this->updated(); + + } catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } catch (EntityNotFoundException $ex2) { + Log::warning($ex2); + return $this->error404(array('message' => $ex2->getMessage())); + } catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $presentation_id + * @param $speaker_id + * @return mixed + */ + public function removeSpeakerToMyPresentation($presentation_id, $speaker_id){ + try { + $current_member_id = $this->resource_server_context->getCurrentUserExternalId(); + if (is_null($current_member_id)) + return $this->error403(); + + $this->summit_service->removeSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id); + + return $this->deleted(); + + } catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } 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 6e9c9faf..24c1b372 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -533,6 +533,16 @@ Route::group([ Route::get('', 'OAuth2SummitSpeakersApiController@getMySpeaker'); Route::post('', 'OAuth2SummitSpeakersApiController@createMySpeaker'); Route::group(['prefix' => 'presentations'], function(){ + + Route::group(['prefix' => '{presentation_id}'], function(){ + Route::group(['prefix' => 'speakers'], function(){ + Route::put('{speaker_id}', 'OAuth2SummitSpeakersApiController@addSpeakerToMyPresentation'); + Route::delete('{speaker_id}', 'OAuth2SummitSpeakersApiController@removeSpeakerToMyPresentation'); + }); + Route::group(['prefix' => 'moderators'], function(){ + + }); + }); Route::group(['prefix' => '{role}'], function(){ Route::group(['prefix' => 'selection-plans'], function(){ Route::group(['prefix' => '{selection_plan_id}'], function(){ diff --git a/app/Models/Foundation/Summit/Events/Presentations/Presentation.php b/app/Models/Foundation/Summit/Events/Presentations/Presentation.php index fcfb554b..84efefe6 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/Presentation.php +++ b/app/Models/Foundation/Summit/Events/Presentations/Presentation.php @@ -345,9 +345,18 @@ class Presentation extends SummitEvent * @param PresentationSpeaker $speaker */ public function removeSpeaker(PresentationSpeaker $speaker){ + if(!$this->speakers->contains($speaker)) return; $this->speakers->removeElement($speaker); } + /** + * @param PresentationSpeaker $speaker + * @return bool + */ + public function isSpeaker(PresentationSpeaker $speaker){ + return $this->speakers->contains($speaker); + } + /** * @return PresentationSlide[] */ @@ -677,4 +686,15 @@ class Presentation extends SummitEvent } } + /** + * @param PresentationSpeaker $speaker + * @return bool + */ + public function canEdit(PresentationSpeaker $speaker){ + if($this->getCreatorId() == $speaker->getId()) return true; + if($this->getModeratorId() == $speaker->getId()) return true; + if($this->isSpeaker($speaker)) return true; + return false; + } + } diff --git a/app/Services/Model/ISummitService.php b/app/Services/Model/ISummitService.php index 66b8a3f5..fab17033 100644 --- a/app/Services/Model/ISummitService.php +++ b/app/Services/Model/ISummitService.php @@ -222,4 +222,24 @@ interface ISummitService * @return void */ public function deleteSummit($summit_id); + + /** + * @param int $current_member_id + * @param int $speaker_id + * @param int $presentation_id + * @throws ValidationException + * @throws EntityNotFoundException + * @return void + */ + public function addSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id); + + /** + * @param int $current_member_id + * @param int $speaker_id + * @param int $presentation_id + * @throws ValidationException + * @throws EntityNotFoundException + * @return void + */ + public function removeSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id); } \ No newline at end of file diff --git a/app/Services/Model/SummitService.php b/app/Services/Model/SummitService.php index b0435096..060ad8e6 100644 --- a/app/Services/Model/SummitService.php +++ b/app/Services/Model/SummitService.php @@ -1653,4 +1653,85 @@ final class SummitService extends AbstractService implements ISummitService }); } + + /** + * @param int $current_member_id + * @param int $speaker_id + * @param int $presentation_id + * @throws ValidationException + * @throws EntityNotFoundException + * @return void + */ + public function addSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id) + { + return $this->tx_service->transaction(function () use ($current_member_id, $speaker_id, $presentation_id) { + $current_member = $this->member_repository->getById($current_member_id); + if(is_null($current_member)) + throw new EntityNotFoundException(sprintf("member %s not found", $current_member_id)); + + $current_speaker = $this->speaker_repository->getByMember($current_member); + if(is_null($current_speaker)) + throw new EntityNotFoundException(sprintf("member %s does not has a speaker profile", $current_member_id)); + + $presentation = $this->event_repository->getById($presentation_id); + if(is_null($presentation)) + throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id)); + + if(!$presentation instanceof Presentation) + throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id)); + + if(!$presentation->canEdit($current_speaker)) + throw new ValidationException(sprintf("member %s can not edit presentation %s", + $current_member_id, + $presentation_id + )); + + $speaker = $this->speaker_repository->getById(intval($speaker_id)); + if (is_null($speaker)) + throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id)); + + $presentation->addSpeaker($speaker); + }); + } + + /** + * @param int $current_member_id + * @param int $speaker_id + * @param int $presentation_id + * @throws ValidationException + * @throws EntityNotFoundException + * @return void + */ + public function removeSpeaker2Presentation($current_member_id, $speaker_id, $presentation_id) + { + return $this->tx_service->transaction(function () use ($current_member_id, $speaker_id, $presentation_id) { + + $current_member = $this->member_repository->getById($current_member_id); + if(is_null($current_member)) + throw new EntityNotFoundException(sprintf("member %s not found", $current_member_id)); + + $current_speaker = $this->speaker_repository->getByMember($current_member); + if(is_null($current_speaker)) + throw new EntityNotFoundException(sprintf("member %s does not has a speaker profile", $current_member_id)); + + $presentation = $this->event_repository->getById($presentation_id); + if(is_null($presentation)) + throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id)); + + if(!$presentation instanceof Presentation) + throw new EntityNotFoundException(sprintf("presentation %s not found", $presentation_id)); + + if(!$presentation->canEdit($current_speaker)) + throw new ValidationException(sprintf("member %s can not edit presentation %s", + $current_member_id, + $presentation_id + )); + + $speaker = $this->speaker_repository->getById(intval($speaker_id)); + if (is_null($speaker)) + throw new EntityNotFoundException(sprintf('speaker %s not found', $speaker_id)); + + $presentation->removeSpeaker($speaker); + }); + } } \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 3382ebf2..52cec733 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -329,6 +329,26 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::ReadAllSummitData, $current_realm) ], ), + [ + 'name' => 'add-speaker-2-my-presentation', + 'route' => '/api/v1/speakers/me/presentations/{presentation_id}/speakers/{speaker_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteSpeakersData, $current_realm), + sprintf(SummitScopes::WriteMySpeakersData, $current_realm) + ], + ], + [ + 'name' => 'remove-speaker-2-my-presentation', + 'route' => '/api/v1/speakers/me/presentations/{presentation_id}/speakers/{speaker_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteSpeakersData, $current_realm), + sprintf(SummitScopes::WriteMySpeakersData, $current_realm) + ], + ], array( 'name' => 'create-my-speaker', 'route' => '/api/v1/speakers/me',