From 51b5ab7b6340ceb110a38d963576837fe9c93e0d Mon Sep 17 00:00:00 2001 From: Sebastian Marcet Date: Tue, 20 Feb 2018 13:05:34 -0300 Subject: [PATCH] Added endpoint delete summit event type DELETE /api/v1/summits/{id}/event-types/{event_type_id} Change-Id: Id835571fc2e7b8644fbecb060cc1f890c92038d7 --- .../OAuth2SummitsEventTypesApiController.php | 28 ++++ app/Http/routes.php | 1 + app/Models/Foundation/Summit/Summit.php | 26 ++-- .../DoctrineSummitEventTypeRepository.php | 1 + .../Model/ISummitEventTypeService.php | 9 ++ app/Services/Model/SummitEventTypeService.php | 42 +++++- database/seeds/ApiEndpointsSeeder.php | 9 ++ tests/OAuth2EventTypesApiTest.php | 122 ++++++++++++++++++ 8 files changed, 224 insertions(+), 14 deletions(-) diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitsEventTypesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitsEventTypesApiController.php index e27359d3..9d28fdf3 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitsEventTypesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitsEventTypesApiController.php @@ -112,6 +112,7 @@ final class OAuth2SummitsEventTypesApiController extends OAuth2ProtectedControll $filter = FilterParser::parse(Input::get('filter'), [ 'name' => ['=@', '=='], 'class_name' => ['=='], + 'is_default' => ['=='], 'black_out_times' => ['=='], 'use_sponsors' => ['=='], 'are_sponsors_mandatory' => ['=='], @@ -267,4 +268,31 @@ final class OAuth2SummitsEventTypesApiController extends OAuth2ProtectedControll return $this->error500($ex); } } + + /** + * @param $summit_id + * @param $event_type_id + * @return mixed + */ + public function deleteEventTypeBySummit($summit_id, $event_type_id) + { + try { + + $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $this->event_type_service->deleteEventType($summit, $event_type_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 781fc700..6873967a 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -298,6 +298,7 @@ Route::group([ Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitsEventTypesApiController@addEventTypeBySummit']); Route::group(['prefix' => '{event_type_id}'], function () { Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitsEventTypesApiController@updateEventTypeBySummit']); + Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitsEventTypesApiController@deleteEventTypeBySummit']); }); }); diff --git a/app/Models/Foundation/Summit/Summit.php b/app/Models/Foundation/Summit/Summit.php index 8bda8b56..f9de2064 100644 --- a/app/Models/Foundation/Summit/Summit.php +++ b/app/Models/Foundation/Summit/Summit.php @@ -147,12 +147,12 @@ class Summit extends SilverstripeBaseModel private $time_zone_id; /** - * @ORM\OneToMany(targetEntity="SummitAbstractLocation", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="SummitAbstractLocation", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) */ private $locations; /** - * @ORM\OneToMany(targetEntity="SummitEvent", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="SummitEvent", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) */ private $events; @@ -182,30 +182,30 @@ class Summit extends SilverstripeBaseModel private $logo; /** - * @ORM\OneToMany(targetEntity="models\summit\SummitEventType", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\SummitEventType", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) */ private $event_types; /** - * @ORM\OneToMany(targetEntity="models\summit\PresentationCategory", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\PresentationCategory", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) * @var PresentationCategory[] */ private $presentation_categories; /** - * @ORM\OneToMany(targetEntity="models\summit\SummitAttendee", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\SummitAttendee", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) * @var SummitAttendee[] */ private $attendees; /** - * @ORM\OneToMany(targetEntity="models\summit\PresentationCategoryGroup", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\PresentationCategoryGroup", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) * @var PresentationCategoryGroup[] */ private $category_groups; /** - * @ORM\OneToMany(targetEntity="models\summit\SummitTicketType", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\SummitTicketType", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) */ private $ticket_types; @@ -908,7 +908,7 @@ class Summit extends SilverstripeBaseModel } /** - * @ORM\OneToMany(targetEntity="models\summit\SummitEntityEvent", mappedBy="summit", cascade={"persist"}) + * @ORM\OneToMany(targetEntity="models\summit\SummitEntityEvent", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) * @var SummitEntityEvent[] */ private $entity_events; @@ -1478,6 +1478,16 @@ SQL; return $this; } + /** + * @param SummitEventType $event_type + * @return $this + */ + public function removeEventType(SummitEventType $event_type){ + $this->event_types->removeElement($event_type); + $event_type->setSummit(null); + return $this; + } + /** * @return PresentationCategory[] */ diff --git a/app/Repositories/Summit/DoctrineSummitEventTypeRepository.php b/app/Repositories/Summit/DoctrineSummitEventTypeRepository.php index 77d7c148..06cdf190 100644 --- a/app/Repositories/Summit/DoctrineSummitEventTypeRepository.php +++ b/app/Repositories/Summit/DoctrineSummitEventTypeRepository.php @@ -45,6 +45,7 @@ final class DoctrineSummitEventTypeRepository return [ 'name' => 'et.type:json_string', 'black_out_times' => 'et.black_out_times:json_boolean', + 'is_default' => 'et.is_default:json_boolean', 'use_sponsors' => 'et.use_sponsors:json_boolean', 'are_sponsors_mandatory' => 'et.are_sponsors_mandatory:json_boolean', 'allows_attachment' => 'et.allows_attachment:json_boolean', diff --git a/app/Services/Model/ISummitEventTypeService.php b/app/Services/Model/ISummitEventTypeService.php index 1c5cd99c..401f4c57 100644 --- a/app/Services/Model/ISummitEventTypeService.php +++ b/app/Services/Model/ISummitEventTypeService.php @@ -40,4 +40,13 @@ interface ISummitEventTypeService */ public function updateEventType(Summit $summit, $event_type_id, array $data); + /** + * @param Summit $summit + * @param int $event_type_id + * @return void + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function deleteEventType(Summit $summit, $event_type_id); + } \ No newline at end of file diff --git a/app/Services/Model/SummitEventTypeService.php b/app/Services/Model/SummitEventTypeService.php index af73355a..b1f2cfb1 100644 --- a/app/Services/Model/SummitEventTypeService.php +++ b/app/Services/Model/SummitEventTypeService.php @@ -29,7 +29,7 @@ final class SummitEventTypeService implements ISummitEventTypeService /** * @var ITransactionService */ - private $tx_manager; + private $tx_service; /** * @var ISummitEventTypeRepository @@ -39,15 +39,15 @@ final class SummitEventTypeService implements ISummitEventTypeService /** * SummitEventTypeService constructor. * @param ISummitEventTypeRepository $repository - * @param ITransactionService $tx_manager + * @param ITransactionService $tx_service */ public function __construct ( ISummitEventTypeRepository $repository, - ITransactionService $tx_manager + ITransactionService $tx_service ) { - $this->tx_manager = $tx_manager; + $this->tx_service = $tx_service; $this->repository = $repository; } @@ -60,7 +60,7 @@ final class SummitEventTypeService implements ISummitEventTypeService */ public function addEventType(Summit $summit, array $data) { - return $this->tx_manager->transaction(function() use($summit, $data){ + return $this->tx_service->transaction(function() use($summit, $data){ $type = trim($data['name']); @@ -88,7 +88,7 @@ final class SummitEventTypeService implements ISummitEventTypeService */ public function updateEventType(Summit $summit, $event_type_id, array $data) { - return $this->tx_manager->transaction(function() use($summit, $event_type_id, $data){ + return $this->tx_service->transaction(function() use($summit, $event_type_id, $data){ $type = isset($data['name']) ? trim($data['name']) : null; @@ -110,4 +110,34 @@ final class SummitEventTypeService implements ISummitEventTypeService }); } + + /** + * @param Summit $summit + * @param int $event_type_id + * @return void + * @throws EntityNotFoundException + * @throws ValidationException + */ + public function deleteEventType(Summit $summit, $event_type_id) + { + return $this->tx_service->transaction(function() use($event_type_id, $summit){ + + $event_type = $summit->getEventType($event_type_id); + + if(is_null($event_type)) + throw new EntityNotFoundException + ( + sprintf("event type id %s does not belongs to summit id %s", $event_type_id, $summit->getId()) + ); + + if ($event_type->isDefault()) + throw new ValidationException + ( + sprintf("event type id %s is a default one and is not allowed to be deleted", $event_type_id) + ); + + $summit->removeEventType($event_type); + + }); + } } \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index d0ae3081..9efc1c07 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -564,6 +564,15 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::WriteSummitData, $current_realm) ], ], + [ + 'name' => 'delete-event-type', + 'route' => '/api/v1/summits/{id}/event-types/{event_type_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SummitScopes::WriteEventTypeData, $current_realm), + sprintf(SummitScopes::WriteSummitData, $current_realm) + ], + ], //tracks array( 'name' => 'get-tracks', diff --git a/tests/OAuth2EventTypesApiTest.php b/tests/OAuth2EventTypesApiTest.php index 1e2a612d..0b0f29ef 100644 --- a/tests/OAuth2EventTypesApiTest.php +++ b/tests/OAuth2EventTypesApiTest.php @@ -46,6 +46,71 @@ final class OAuth2EventTypesApiTest extends ProtectedApiTest $this->assertResponseStatus(200); $event_types = json_decode($content); $this->assertTrue(!is_null($event_types)); + return $event_types; + } + + public function testGetEventTypesDefaultOnes(){ + $params = [ + + 'id' => 23, + 'page' => 1, + 'per_page' => 10, + 'filter' => 'is_default==1', + 'order' => '+name' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitsEventTypesApiController@getAllBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $event_types = json_decode($content); + $this->assertTrue(!is_null($event_types)); + return $event_types; + } + + public function testGetEventTypesNonDefaultOnes(){ + $params = [ + + 'id' => 23, + 'page' => 1, + 'per_page' => 10, + 'filter' => 'is_default==0', + 'order' => '+name' + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "GET", + "OAuth2SummitsEventTypesApiController@getAllBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $event_types = json_decode($content); + $this->assertTrue(!is_null($event_types)); + return $event_types; } public function testGetEventTypesByClassNamePresentationType(){ @@ -151,5 +216,62 @@ final class OAuth2EventTypesApiTest extends ProtectedApiTest return $event_type; } + public function testDeleteDefaultOne($summit_id = 23){ + + $event_types = $this->testGetEventTypesDefaultOnes($summit_id); + + $params = [ + 'id' => $summit_id, + 'event_type_id' => $event_types->data[0]->id, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "DELETE", + "OAuth2SummitsEventTypesApiController@deleteEventTypeBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(!empty($content)); + $this->assertResponseStatus(412); + } + + public function testDeleteNonDefaultOne($summit_id = 23){ + + $event_types = $this->testGetEventTypesNonDefaultOnes($summit_id); + + $params = [ + 'id' => $summit_id, + 'event_type_id' => $event_types->data[0]->id, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "DELETE", + "OAuth2SummitsEventTypesApiController@deleteEventTypeBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(empty($content)); + $this->assertResponseStatus(204); + } } \ No newline at end of file