diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2MembersApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2MembersApiController.php index 297026e9..cd5f2228 100644 --- a/app/Http/Controllers/Apis/Protected/Main/OAuth2MembersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2MembersApiController.php @@ -254,5 +254,34 @@ final class OAuth2MembersApiController extends OAuth2ProtectedController } } + /** + * @param $member_id + * @param $rsvp_id + * @return mixed + */ + public function deleteRSVP($member_id, $rsvp_id){ + try{ + + $member = $this->repository->getById($member_id); + if(is_null($member)) return $this->error404(); + + $this->member_service->deleteRSVP($member, $rsvp_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/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php index 04a9c4d6..4cf0dcab 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitAttendeesApiController.php @@ -153,7 +153,13 @@ final class OAuth2SummitAttendeesApiController extends OAuth2ProtectedController ( $attendee, SerializerRegistry::SerializerType_Private - )->serialize($expand)); + )->serialize + ( + $expand, + [], + [], + [ 'serializer_type' => SerializerRegistry::SerializerType_Private ] + )); } catch (\HTTP401UnauthorizedException $ex1) { Log::warning($ex1); diff --git a/app/Http/routes.php b/app/Http/routes.php index df0643a6..71c9e077 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -108,6 +108,12 @@ Route::group([ Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@deleteAffiliation']); }); }); + + Route::group(array('prefix' => 'rsvp'), function () { + Route::group(['prefix' => '{rsvp_id}'], function () { + Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2MembersApiController@deleteRSVP']); + }); + }); }); }); diff --git a/app/ModelSerializers/OwnMemberSerializer.php b/app/ModelSerializers/OwnMemberSerializer.php index 4a8c4d67..edabf704 100644 --- a/app/ModelSerializers/OwnMemberSerializer.php +++ b/app/ModelSerializers/OwnMemberSerializer.php @@ -43,6 +43,7 @@ final class OwnMemberSerializer extends AbstractMemberSerializer 'favorite_summit_events', 'feedback', 'schedule_summit_events', + 'rsvp', ]; private static $expand_group_events = [ @@ -172,6 +173,18 @@ final class OwnMemberSerializer extends AbstractMemberSerializer $values['schedule_summit_events'] = $schedule; } break; + case 'rsvp':{ + if(!in_array('rsvp', $relations)) break; + if(is_null($summit)) break; + $rsvps = []; + foreach ($member->getRsvpBySummit($summit) as $rsvp){ + $rsvps[] = SerializerRegistry::getInstance() + ->getSerializer($rsvp) + ->serialize($expand); + } + $values['rsvp'] = $rsvps; + } + break; } } } diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index d225336b..c55e212c 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -106,6 +106,7 @@ final class SerializerRegistry self::SerializerType_Private => AdminPresentationSpeakerSerializer::class ]; + $this->registry['RSVP'] = RSVPSerializer::class; $this->registry['SpeakerExpertise'] = SpeakerExpertiseSerializer::class; $this->registry['SpeakerLanguage'] = SpeakerLanguageSerializer::class; $this->registry['SpeakerTravelPreference'] = SpeakerTravelPreferenceSerializer::class; diff --git a/app/ModelSerializers/Summit/RSVPSerializer.php b/app/ModelSerializers/Summit/RSVPSerializer.php new file mode 100644 index 00000000..1291d720 --- /dev/null +++ b/app/ModelSerializers/Summit/RSVPSerializer.php @@ -0,0 +1,27 @@ + 'owner_id:json_int', + 'EventId' => 'event_id:json_int', + 'SeatType' => 'seat_type:json_string', + 'Created' => 'created:datetime_epoch', + ); +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/SummitAttendeeSerializer.php b/app/ModelSerializers/Summit/SummitAttendeeSerializer.php index 76812d0d..506b1778 100644 --- a/app/ModelSerializers/Summit/SummitAttendeeSerializer.php +++ b/app/ModelSerializers/Summit/SummitAttendeeSerializer.php @@ -112,7 +112,13 @@ final class SummitAttendeeSerializer extends SilverStripeSerializer if($attendee->hasMember()) { unset($values['member_id']); - $values['member'] = SerializerRegistry::getInstance()->getSerializer($attendee->getMember(), $serializer_type)->serialize($expand); + $values['member'] = SerializerRegistry::getInstance() + ->getSerializer($attendee->getMember(), $serializer_type) + ->serialize( + $expand, + [], + [], + ['summit' => $attendee->getSummit()]); } } break; diff --git a/app/Models/Foundation/Main/Member.php b/app/Models/Foundation/Main/Member.php index 0f52ded2..196e7494 100644 --- a/app/Models/Foundation/Main/Member.php +++ b/app/Models/Foundation/Main/Member.php @@ -924,6 +924,26 @@ SQL; return count($rsvp) > 0 ? $rsvp[0] : null; } + /** + * @param Summit $summit + * @return null|RSVP[] + */ + public function getRsvpBySummit(Summit $summit){ + $builder = $this->createQueryBuilder(); + $res = $builder + ->select('r') + ->from('models\summit\RSVP','r') + ->join('r.owner','o') + ->join('r.event','e') + ->join('e.summit','s') + ->where('o.id = :owner_id and s.id = :summit_id') + ->setParameter('owner_id', $this->getId()) + ->setParameter('summit_id', $summit->getId()) + ->getQuery()->getResult(); + + return $res; + } + /** * @param Summit $summit * @return SummitMemberSchedule[] @@ -1016,4 +1036,26 @@ SQL; $this->affiliations->removeElement($affiliation); return $this; } + + /** + * @param int $rsvp_id + * @return RSVP|null + */ + public function getRsvpById($rsvp_id){ + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('id', $rsvp_id)); + + $rsvp = $this->rsvp->matching($criteria)->first(); + + return $rsvp ? $rsvp : null; + } + + /** + * @param RSVP $rsvp + * @return $this + */ + public function removeRsvp(RSVP $rsvp){ + $this->rsvp->removeElement($rsvp); + return $this; + } } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP.php b/app/Models/Foundation/Summit/Events/RSVP.php index 4ad3112a..dc6a25e3 100644 --- a/app/Models/Foundation/Summit/Events/RSVP.php +++ b/app/Models/Foundation/Summit/Events/RSVP.php @@ -40,6 +40,25 @@ class RSVP extends SilverstripeBaseModel */ private $owner; + /** + * @ORM\ManyToOne(targetEntity="models\summit\SummitEvent", inversedBy="rsvp", fetch="LAZY") + * @ORM\JoinColumn(name="EventID", referencedColumnName="ID") + * @var SummitEvent + */ + private $event; + + + /** + * @ORM\Column(name="SeatType", type="string") + */ + protected $seat_type; + + /** + * @ORM\OneToMany(targetEntity="models\summit\RSVPAnswer", mappedBy="rsvp", cascade={"persist", "remove"}) + * @var RSVPAnswer[] + */ + protected $answers; + /** * @return ArrayCollection */ @@ -71,12 +90,6 @@ class RSVP extends SilverstripeBaseModel $this->owner = $owner; } - /** - * @ORM\ManyToOne(targetEntity="models\summit\SummitEvent", inversedBy="rsvp", fetch="LAZY") - * @ORM\JoinColumn(name="EventID", referencedColumnName="ID") - * @var SummitEvent - */ - private $event; /** * @return SummitEvent @@ -125,9 +138,19 @@ class RSVP extends SilverstripeBaseModel } /** - * @ORM\OneToMany(targetEntity="models\summit\RSVPAnswer", mappedBy="rsvp", cascade={"persist", "remove"}) - * @var RSVPAnswer[] + * @return mixed */ - protected $answers; + public function getSeatType() + { + return $this->seat_type; + } + + /** + * @param mixed $seat_type + */ + public function setSeatType($seat_type) + { + $this->seat_type = $seat_type; + } } \ No newline at end of file diff --git a/app/Services/Model/IMemberService.php b/app/Services/Model/IMemberService.php index 925351a8..a2117acd 100644 --- a/app/Services/Model/IMemberService.php +++ b/app/Services/Model/IMemberService.php @@ -29,8 +29,15 @@ interface IMemberService /** * @param Member $member - * @param $affiliation_id + * @param int $affiliation_id * @return void */ public function deleteAffiliation(Member $member, $affiliation_id); + + /** + * @param Member $member + * @param int $rsvp_id + * @return void + */ + public function deleteRSVP(Member $member, $rsvp_id); } \ No newline at end of file diff --git a/app/Services/Model/MemberService.php b/app/Services/Model/MemberService.php index 2fbbf8c8..df02e83b 100644 --- a/app/Services/Model/MemberService.php +++ b/app/Services/Model/MemberService.php @@ -111,4 +111,20 @@ final class MemberService implements IMemberService $member->removeAffiliation($affiliation); }); } + + /** + * @param Member $member + * @param int $rsvp_id + * @return void + */ + public function deleteRSVP(Member $member, $rsvp_id) + { + return $this->tx_service->transaction(function() use($member, $rsvp_id){ + $affiliation = $member->getRsvpById($rsvp_id); + if(is_null($affiliation)) + throw new EntityNotFoundException(sprintf("rsvp id %s does not belongs to member id %s", $rsvp_id, $member->getId())); + + $member->removeAffiliation($affiliation); + }); + } } \ No newline at end of file diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 0bba9446..98b18158 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -693,7 +693,15 @@ class ApiEndpointsSeeder extends Seeder 'scopes' => [ sprintf(SummitScopes::WriteMemberData, $current_realm) ], - ] + ], + [ + 'name' => 'delete-member-rsvp', + 'route' => '/api/v1/members/{member_id}/rsvp/{rsvp_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SummitScopes::WriteMemberData, $current_realm) + ], + ] ] ); } diff --git a/tests/OAuth2AttendeesApiTest.php b/tests/OAuth2AttendeesApiTest.php index a6ee2968..facac495 100644 --- a/tests/OAuth2AttendeesApiTest.php +++ b/tests/OAuth2AttendeesApiTest.php @@ -23,7 +23,7 @@ class OAuth2AttendeesApiTest extends ProtectedApiTest 'per_page' => 10, 'order' => '+id', 'filter' => 'email=@jimmy', - 'expand' => 'member,schedule' + 'expand' => 'member,schedule,rsvp' ]; $headers = [ @@ -74,12 +74,12 @@ class OAuth2AttendeesApiTest extends ProtectedApiTest $this->assertTrue(!is_null($attendee)); } - public function testGetAttendeeByID($attendee_id = 12642){ + public function testGetAttendeeByID($attendee_id = 12923){ $params = [ 'id' => 23, 'attendee_id' => $attendee_id, - 'expand' => 'member,schedule,tickets,affiliations,groups' + 'expand' => 'member,schedule,tickets,affiliations,groups,rsvp' ]; $headers = [