diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php index c5418ef4..904ee8a7 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php @@ -509,4 +509,58 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController } } + /** + * @param int $summit_id + * @param int $attendee_id + * @return mixed + */ + public function updateAttendee($summit_id, $attendee_id){ + try { + if(!Request::isJson()) return $this->error403(); + $data = Input::json(); + + $summit = SummitFinderStrategyFactory::build($this->repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $attendee = $this->attendee_repository->getById($attendee_id); + if(is_null($attendee)) return $this->error404(); + + $rules = [ + 'member_id' => 'required|integer', + 'share_contact_info' => 'sometimes|boolean', + 'summit_hall_checked_in' => 'sometimes|boolean', + 'summit_hall_checked_in_date' => 'sometimes|date_format:U', + ]; + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $attendee = $this->attendee_service->updateAttendee($summit, $attendee_id, $data->all()); + + return $this->updated(SerializerRegistry::getInstance()->getSerializer($attendee)->serialize()); + } + 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 23244b62..cdb41896 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -159,6 +159,7 @@ Route::group([ Route::group(array('prefix' => '{attendee_id}'), function () { Route::get('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@getAttendee']); + Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@updateAttendee']); Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitAttendeesApiController@deleteAttendee']); Route::group(array('prefix' => 'schedule'), function () { diff --git a/app/Models/Foundation/Summit/Attendees/SummitAttendeeTicket.php b/app/Models/Foundation/Summit/Attendees/SummitAttendeeTicket.php index 98b55ceb..65122b38 100644 --- a/app/Models/Foundation/Summit/Attendees/SummitAttendeeTicket.php +++ b/app/Models/Foundation/Summit/Attendees/SummitAttendeeTicket.php @@ -13,7 +13,6 @@ **/ use models\utils\SilverstripeBaseModel; use Doctrine\ORM\Mapping AS ORM; - /** * @ORM\Entity * @ORM\Table(name="SummitAttendeeTicket") @@ -23,6 +22,44 @@ use Doctrine\ORM\Mapping AS ORM; */ class SummitAttendeeTicket extends SilverstripeBaseModel { + /** + * @ORM\Column(name="ExternalOrderId", type="string") + * @var string + */ + private $external_order_id; + + /** + * @ORM\Column(name="ExternalAttendeeId", type="string") + * @var + */ + private $external_attendee_id; + + /** + * @ORM\Column(name="TicketBoughtDate", type="datetime") + * @var \DateTime + */ + private $bought_date; + + /** + * @ORM\Column(name="TicketChangedDate", type="datetime") + * @var \DateTime + */ + private $changed_date; + + /** + * @ORM\ManyToOne(targetEntity="SummitTicketType", fetch="EAGER") + * @ORM\JoinColumn(name="TicketTypeID", referencedColumnName="ID") + * @var SummitTicketType + */ + private $ticket_type; + + /** + * @ORM\ManyToOne(targetEntity="SummitAttendee", inversedBy="tickets") + * @ORM\JoinColumn(name="OwnerID", referencedColumnName="ID") + * @var SummitAttendee + */ + private $owner; + /** * @return mixed */ @@ -136,44 +173,4 @@ class SummitAttendeeTicket extends SilverstripeBaseModel { $this->owner = $owner; } - - /** - * @ORM\Column(name="ExternalOrderId", type="string") - * @var string - */ - private $external_order_id; - - /** - * @ORM\Column(name="ExternalAttendeeId", type="string") - * @var - */ - private $external_attendee_id; - - /** - * @ORM\Column(name="TicketBoughtDate", type="datetime") - * @var \DateTime - */ - private $bought_date; - - /** - * @ORM\Column(name="TicketChangedDate", type="datetime") - * @var \DateTime - */ - private $changed_date; - - - /** - * @ORM\ManyToOne(targetEntity="SummitTicketType", fetch="EAGER") - * @ORM\JoinColumn(name="TicketTypeID", referencedColumnName="ID") - * @var SummitTicketType - */ - private $ticket_type; - - /** - * @ORM\ManyToOne(targetEntity="SummitAttendee", inversedBy="tickets") - * @ORM\JoinColumn(name="OwnerID", referencedColumnName="ID") - * @var SummitAttendee - */ - private $owner; - } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php b/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php index 44b79bc4..1ea8b72d 100644 --- a/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php +++ b/app/Models/Foundation/Summit/Factories/SummitAttendeeFactory.php @@ -27,8 +27,17 @@ final class SummitAttendeeFactory * @return SummitAttendee */ public static function build(Summit $summit, Member $member, array $data){ - $attendee = new SummitAttendee(); + return self::updateMainData($summit, new SummitAttendee, $member, $data); + } + /** + * @param Summit $summit + * @param SummitAttendee $attendee + * @param Member $member + * @param array $data + * @return SummitAttendee + */ + public static function updateMainData(Summit $summit, SummitAttendee $attendee, Member $member, array $data){ $attendee->setMember($member); $attendee->setSummit($summit); diff --git a/app/Services/Model/AttendeeService.php b/app/Services/Model/AttendeeService.php index c7f1f606..76b6d4a2 100644 --- a/app/Services/Model/AttendeeService.php +++ b/app/Services/Model/AttendeeService.php @@ -96,13 +96,46 @@ final class AttendeeService implements IAttendeeService { return $this->tx_service->transaction(function() use($summit, $attendee_id){ - $attendee = $summit->getAttendeeById($attendee_id); if(is_null($attendee)) throw new EntityNotFoundException(); $this->attendee_repository->delete($attendee); + }); + } + /** + * @param Summit $summit + * @param int $attendee_id + * @param array $data + * @return SummitAttendee + * @throws ValidationException + * @throws EntityNotFoundException + */ + public function updateAttendee(Summit $summit, $attendee_id, array $data) + { + return $this->tx_service->transaction(function() use($summit, $attendee_id, $data){ + + $attendee = $summit->getAttendeeById($attendee_id); + if(is_null($attendee)) + throw new EntityNotFoundException(sprintf("attendee does not belongs to summit id %s", $summit->getId())); + + if(!isset($data['member_id'])) + throw new ValidationException("member_id is required"); + + $member_id = intval($data['member_id']); + $member = $this->member_repository->getById($member_id); + + if(is_null($member)) + throw new EntityNotFoundException("member not found"); + + // check if attendee already exist for this summit + + $old_attendee = $this->attendee_repository->getBySummitAndMember($summit, $member); + if(!is_null($old_attendee) && $old_attendee->getId() != $attendee->getId()) + throw new ValidationException(sprintf("another attendee (%s) already exist for summit id %s and member id %s", $old_attendee->getId(), $summit->getId(), $member->getIdentifier())); + + return SummitAttendeeFactory::updateMainData($summit, $attendee, $member , $data); }); } diff --git a/app/Services/Model/IAttendeeService.php b/app/Services/Model/IAttendeeService.php index 527a04b2..bbd9a174 100644 --- a/app/Services/Model/IAttendeeService.php +++ b/app/Services/Model/IAttendeeService.php @@ -25,6 +25,8 @@ interface IAttendeeService * @param Summit $summit * @param array $data * @return SummitAttendee + * @throws ValidationException + * @throws EntityNotFoundException */ public function addAttendee(Summit $summit, array $data); @@ -36,4 +38,14 @@ interface IAttendeeService * @throws EntityNotFoundException */ public function deleteAttendee(Summit $summit, $attendee_id); + + /** + * @param Summit $summit + * @param int $attendee_id + * @param array $data + * @return SummitAttendee + * @throws ValidationException + * @throws EntityNotFoundException + */ + public function updateAttendee(Summit $summit, $attendee_id, array $data); } \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 9a8c97f4..584329ea 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -137,6 +137,14 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::WriteAttendeesData, $current_realm), ], ), + array( + 'name' => 'update-attendee', + 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteAttendeesData, $current_realm), + ], + ), array( 'name' => 'get-attendee-schedule', 'route' => '/api/v1/summits/{id}/attendees/{attendee_id}/schedule', diff --git a/tests/OAuth2AttendeesApiTest.php b/tests/OAuth2AttendeesApiTest.php index 96e35825..c129c0fd 100644 --- a/tests/OAuth2AttendeesApiTest.php +++ b/tests/OAuth2AttendeesApiTest.php @@ -74,11 +74,11 @@ class OAuth2AttendeesApiTest extends ProtectedApiTest $this->assertTrue(!is_null($attendee)); } - public function testGetAttendeeByID(){ + public function testGetAttendeeByID($attendee_id = 12641){ $params = [ 'id' => 23, - 'attendee_id' => 12641, + 'attendee_id' => $attendee_id, 'expand' => 'member,schedule,tickets,affiliations,groups' ]; @@ -101,6 +101,8 @@ class OAuth2AttendeesApiTest extends ProtectedApiTest $this->assertResponseStatus(200); $attendee = json_decode($content); $this->assertTrue(!is_null($attendee)); + + return $attendee; } public function testGetAttendeeByOrderID(){ @@ -194,4 +196,40 @@ class OAuth2AttendeesApiTest extends ProtectedApiTest $content = $response->getContent(); $this->assertResponseStatus(204); } + + public function testUpdateAttendee(){ + $attendee = $this->testGetAttendeeByID(12642); + + $params = [ + 'id' => 23, + 'attendee_id' => $attendee->id + ]; + + $data = [ + 'member_id' => $attendee->member->id, + 'share_contact_info' => true + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2SummitAttendeesApiController@updateAttendee", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(204); + $attendee = json_decode($content); + $this->assertTrue(!is_null($attendee)); + return $attendee; + } } \ No newline at end of file