Updated Add/Update event endpoint to accept RSVP template id

now payload accepts as a new field
'rsvp_template_id' (integer)

Change-Id: Ifdfb4e55e8dd818c25c0732c9cbb14f662679c36
This commit is contained in:
Sebastian Marcet 2018-02-27 12:19:59 -03:00
parent 36971f039f
commit d856c7ecc2
12 changed files with 362 additions and 30 deletions

View File

@ -330,8 +330,8 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
if(!Request::isJson()) return $this->error403(); if(!Request::isJson()) return $this->error403();
$data = Input::json(); $data = Input::json();
$rules = array $rules = [
(
'title' => 'required|string|max:100', 'title' => 'required|string|max:100',
'description' => 'required|string', 'description' => 'required|string',
'type_id' => 'required|integer', 'type_id' => 'required|integer',
@ -340,6 +340,7 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
'end_date' => 'sometimes|required_with:start_date|date_format:U|after:start_date', 'end_date' => 'sometimes|required_with:start_date|date_format:U|after:start_date',
'track_id' => 'required|integer', 'track_id' => 'required|integer',
'rsvp_link' => 'sometimes|url', 'rsvp_link' => 'sometimes|url',
'rsvp_template_id' => 'sometimes|integer',
'head_count' => 'sometimes|integer', 'head_count' => 'sometimes|integer',
'social_description' => 'sometimes|string|max:100', 'social_description' => 'sometimes|string|max:100',
'allow_feedback' => 'sometimes|boolean', 'allow_feedback' => 'sometimes|boolean',
@ -353,7 +354,7 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
'moderator_speaker_id' => 'sometimes|integer', 'moderator_speaker_id' => 'sometimes|integer',
// group event // group event
'groups' => 'sometimes|int_array', 'groups' => 'sometimes|int_array',
); ];
// Creates a Validator instance and validates the data. // Creates a Validator instance and validates the data.
$validation = Validator::make($data->all(), $rules); $validation = Validator::make($data->all(), $rules);
@ -412,6 +413,7 @@ final class OAuth2SummitEventsApiController extends OAuth2ProtectedController
'title' => 'sometimes|string|max:100', 'title' => 'sometimes|string|max:100',
'description' => 'sometimes|string', 'description' => 'sometimes|string',
'rsvp_link' => 'sometimes|url', 'rsvp_link' => 'sometimes|url',
'rsvp_template_id' => 'sometimes|integer',
'head_count' => 'sometimes|integer', 'head_count' => 'sometimes|integer',
'social_description' => 'sometimes|string|max:100', 'social_description' => 'sometimes|string|max:100',
'location_id' => 'sometimes|integer', 'location_id' => 'sometimes|integer',

View File

@ -13,7 +13,6 @@
**/ **/
use libs\utils\JsonUtils; use libs\utils\JsonUtils;
use models\summit\SummitEvent; use models\summit\SummitEvent;
/** /**
* Class SummitEventSerializer * Class SummitEventSerializer
* @package ModelSerializers * @package ModelSerializers
@ -36,12 +35,13 @@ class SummitEventSerializer extends SilverStripeSerializer
'Published' => 'is_published:json_boolean', 'Published' => 'is_published:json_boolean',
'HeadCount' => 'head_count:json_int', 'HeadCount' => 'head_count:json_int',
'RSVPLink' => 'rsvp_link:json_string', 'RSVPLink' => 'rsvp_link:json_string',
'IsExternalRSVP' => 'rsvp_external:json_boolean', 'RSVPTemplateId' => 'rsvp_template_id:json_int',
'ExternalRSVP' => 'rsvp_external:json_boolean',
'CategoryId' => 'track_id:json_int', 'CategoryId' => 'track_id:json_int',
); );
protected static $allowed_fields = array protected static $allowed_fields = [
(
'id', 'id',
'title', 'title',
'description', 'description',
@ -59,7 +59,8 @@ class SummitEventSerializer extends SilverStripeSerializer
'rsvp_link', 'rsvp_link',
'rsvp_external', 'rsvp_external',
'track_id', 'track_id',
); 'rsvp_template_id',
];
protected static $allowed_relations = array protected static $allowed_relations = array
( (

View File

@ -1,5 +1,4 @@
<?php namespace models\summit; <?php namespace models\summit;
/** /**
* Copyright 2016 OpenStack Foundation * Copyright 2016 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -12,12 +11,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
use models\main\Member; use models\main\Member;
use models\utils\SilverstripeBaseModel; use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM; use Doctrine\ORM\Mapping AS ORM;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
/** /**
* @ORM\Entity * @ORM\Entity
* @ORM\Table(name="RSVP") * @ORM\Table(name="RSVP")
@ -47,7 +44,6 @@ class RSVP extends SilverstripeBaseModel
*/ */
private $event; private $event;
/** /**
* @ORM\Column(name="SeatType", type="string") * @ORM\Column(name="SeatType", type="string")
*/ */

View File

@ -0,0 +1,94 @@
<?php namespace App\Models\Foundation\Summit\Events\RSVP;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\main\Member;
use models\summit\SummitOwned;
use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM;
/**
* @ORM\Table(name="RSVPTemplate")
* @ORM\Entity(repositoryClass="App\Repositories\Summit\DoctrineRSVPTemplateRepository")
* Class RSVPTemplate
* @package App\Models\Foundation\Summit\Events\RSVP
*/
class RSVPTemplate extends SilverstripeBaseModel
{
use SummitOwned;
/**
* @ORM\Column(name="Title", type="string")
* @var string
*/
private $title;
/**
* @ORM\Column(name="Enabled", type="boolean")
* @var bool
*/
private $is_enabled;
/**
* @ORM\ManyToOne(targetEntity="models\main\Member", fetch="LAZY")
* @ORM\JoinColumn(name="CreatedByID", referencedColumnName="ID")
* @var Member
*/
private $created_by;
/**
* @return string
*/
public function getTitle()
{
return $this->title;
}
/**
* @param string $title
*/
public function setTitle($title)
{
$this->title = $title;
}
/**
* @return bool
*/
public function isEnabled()
{
return $this->is_enabled;
}
/**
* @param bool $is_enabled
*/
public function setIsEnabled($is_enabled)
{
$this->is_enabled = $is_enabled;
}
/**
* @return Member
*/
public function getCreatedBy()
{
return $this->created_by;
}
/**
* @param Member $created_by
*/
public function setCreatedBy(Member $created_by)
{
$this->created_by = $created_by;
}
}

View File

@ -11,6 +11,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
use App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate;
use Doctrine\ORM\Mapping AS ORM; use Doctrine\ORM\Mapping AS ORM;
use App\Events\SummitEventCreated; use App\Events\SummitEventCreated;
use App\Events\SummitEventDeleted; use App\Events\SummitEventDeleted;
@ -106,10 +107,11 @@ class SummitEvent extends SilverstripeBaseModel
protected $head_count; protected $head_count;
/** /**
* @ORM\Column(name="RSVPTemplateID", type="integer") * @ORM\ManyToOne(targetEntity="App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate", fetch="EXTRA_LAZY")
* @var int * @ORM\JoinColumn(name="RSVPTemplateID", referencedColumnName="ID")
* @var RSVPTemplate
*/ */
protected $rsvp_template_id; protected $rsvp_template;
/** /**
* @ORM\OneToMany(targetEntity="models\summit\RSVP", mappedBy="event", cascade={"persist"}) * @ORM\OneToMany(targetEntity="models\summit\RSVP", mappedBy="event", cascade={"persist"})
@ -318,9 +320,9 @@ class SummitEvent extends SilverstripeBaseModel
/** /**
* @return string * @return string
*/ */
public function getRsvpLink() public function getRSVPLink()
{ {
if($this->rsvp_template_id > 0){ if($this->hasRSVPTemplate()){
$summit = $this->getSummit(); $summit = $this->getSummit();
$main_page = $summit->getMainPage(); $main_page = $summit->getMainPage();
@ -338,25 +340,54 @@ class SummitEvent extends SilverstripeBaseModel
return $this->rsvp_link; return $this->rsvp_link;
} }
/**
* @return bool
*/
public function hasRSVPTemplate(){
return $this->getRSVPTemplateId() > 0;
}
/**
* @return int
*/
public function getRSVPTemplateId(){
try{
return !is_null($this->rsvp_template) ? $this->rsvp_template->getId() : 0;
}
catch (\Exception $ex){
return 0;
}
}
/**
* @return RSVPTemplate
*/
public function getRSVPTemplate()
{
return $this->rsvp_template;
}
/**
* @param RSVPTemplate $rsvp_template
*/
public function setRSVPTemplate(RSVPTemplate $rsvp_template)
{
$this->rsvp_template = $rsvp_template;
$this->rsvp_link = '';
}
/** /**
* @return bool * @return bool
*/ */
public function hasRSVP(){ public function hasRSVP(){
return !empty($this->rsvp_link) || $this->rsvp_template_id > 0; return !empty($this->rsvp_link) || $this->hasRSVPTemplate();
} }
/** /**
* @return bool * @return bool
*/ */
public function isExternalRSVP(){ public function isExternalRSVP(){
return !empty($this->rsvp_link) && $this->rsvp_template_id == 0; return !empty($this->rsvp_link) && !$this->hasRSVPTemplate();
}
/**
* @return bool
*/
public function getIsExternalRSVP(){
return $this->isExternalRSVP();
} }
public function getSlug(){ public function getSlug(){
@ -367,9 +398,10 @@ class SummitEvent extends SilverstripeBaseModel
/** /**
* @param string $rsvp_link * @param string $rsvp_link
*/ */
public function setRsvpLink($rsvp_link) public function setRSVPLink($rsvp_link)
{ {
$this->rsvp_link = $rsvp_link; $this->rsvp_link = $rsvp_link;
$this->rsvp_template = null;
} }
/** /**

View File

@ -0,0 +1,22 @@
<?php namespace App\Models\Foundation\Summit\Repositories;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use models\utils\IBaseRepository;
/**
* Interface IRSVPTemplateRepository
* @package App\Models\Foundation\Summit\Repositories
*/
interface IRSVPTemplateRepository extends IBaseRepository
{
}

View File

@ -12,6 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
**/ **/
use App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate;
use DateTime; use DateTime;
use DateTimeZone; use DateTimeZone;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
@ -22,7 +23,7 @@ use models\main\File;
use models\main\Member; use models\main\Member;
use models\main\Tag; use models\main\Tag;
use models\utils\SilverstripeBaseModel; use models\utils\SilverstripeBaseModel;
use Doctrine\ORM\Mapping AS ORM;
/** /**
* @ORM\Entity(repositoryClass="App\Repositories\Summit\DoctrineSummitRepository") * @ORM\Entity(repositoryClass="App\Repositories\Summit\DoctrineSummitRepository")
* @ORM\Table(name="Summit") * @ORM\Table(name="Summit")
@ -156,6 +157,11 @@ class Summit extends SilverstripeBaseModel
*/ */
private $events; private $events;
/**
* @ORM\OneToMany(targetEntity="App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate", mappedBy="summit", cascade={"persist"}, orphanRemoval=true)
*/
private $rsvp_templates;
/** /**
* @ORM\OneToMany(targetEntity="SummitWIFIConnection", mappedBy="summit", cascade={"persist"}, orphanRemoval=true) * @ORM\OneToMany(targetEntity="SummitWIFIConnection", mappedBy="summit", cascade={"persist"}, orphanRemoval=true)
* @var SummitWIFIConnection[] * @var SummitWIFIConnection[]
@ -515,6 +521,7 @@ class Summit extends SilverstripeBaseModel
$this->excluded_categories_for_rejected_presentations = new ArrayCollection; $this->excluded_categories_for_rejected_presentations = new ArrayCollection;
$this->excluded_categories_for_upload_slide_decks = new ArrayCollection; $this->excluded_categories_for_upload_slide_decks = new ArrayCollection;
$this->category_default_tags = new ArrayCollection; $this->category_default_tags = new ArrayCollection;
$this->rsvp_templates = new ArrayCollection;
} }
/** /**
@ -1625,4 +1632,15 @@ SQL;
$event_type->setSummit($this); $event_type->setSummit($this);
return $this; return $this;
} }
/**
* @param int $rsvp_template_id
* @return RSVPTemplate|null
*/
public function getRSVPTemplateById($rsvp_template_id){
$criteria = Criteria::create();
$criteria->where(Criteria::expr()->eq('id', intval($rsvp_template_id)));
$rsvp_template = $this->rsvp_templates->matching($criteria)->first();
return $rsvp_template === false ? null : $rsvp_template;
}
} }

View File

@ -12,8 +12,10 @@
* limitations under the License. * limitations under the License.
**/ **/
use App\Models\Foundation\Summit\Defaults\DefaultSummitEventType; use App\Models\Foundation\Summit\Defaults\DefaultSummitEventType;
use App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate;
use App\Models\Foundation\Summit\Repositories\IDefaultSummitEventTypeRepository; use App\Models\Foundation\Summit\Repositories\IDefaultSummitEventTypeRepository;
use App\Models\Foundation\Summit\Repositories\IPresentationSpeakerSummitAssistanceConfirmationRequestRepository; use App\Models\Foundation\Summit\Repositories\IPresentationSpeakerSummitAssistanceConfirmationRequestRepository;
use App\Models\Foundation\Summit\Repositories\IRSVPTemplateRepository;
use App\Models\Foundation\Summit\Repositories\ISummitEventTypeRepository; use App\Models\Foundation\Summit\Repositories\ISummitEventTypeRepository;
use App\Models\Foundation\Summit\Repositories\ISummitTrackRepository; use App\Models\Foundation\Summit\Repositories\ISummitTrackRepository;
use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\App;
@ -290,5 +292,12 @@ final class RepositoriesProvider extends ServiceProvider
return EntityManager::getRepository(PresentationCategory::class); return EntityManager::getRepository(PresentationCategory::class);
} }
); );
App::singleton(
IRSVPTemplateRepository::class,
function(){
return EntityManager::getRepository(RSVPTemplate::class);
}
);
} }
} }

View File

@ -0,0 +1,33 @@
<?php namespace App\Repositories\Summit;
/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
use App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate;
use App\Models\Foundation\Summit\Repositories\IRSVPTemplateRepository;
use App\Repositories\SilverStripeDoctrineRepository;
/**
* Class DoctrineRSVPTemplateRepository
* @package App\Repositories\Summit
*/
final class DoctrineRSVPTemplateRepository
extends SilverStripeDoctrineRepository
implements IRSVPTemplateRepository
{
/**
* @return string
*/
protected function getBaseEntity()
{
return RSVPTemplate::class;
}
}

View File

@ -673,9 +673,26 @@ final class SummitService implements ISummitService
if (isset($data['description'])) if (isset($data['description']))
$event->setAbstract(html_entity_decode(trim($data['description']))); $event->setAbstract(html_entity_decode(trim($data['description'])));
if(isset($data['rsvp_link']) && isset($data['rsvp_template_id'])){
throw new ValidationException("rsvp_link and rsvp_template_id are both set, you need to especify only one");
}
if (isset($data['rsvp_link'])) if (isset($data['rsvp_link']))
$event->setRsvpLink(html_entity_decode(trim($data['rsvp_link']))); $event->setRsvpLink(html_entity_decode(trim($data['rsvp_link'])));
if (isset($data['rsvp_template_id'])) {
$rsvp_template = $summit->getRSVPTemplateById(intval($data['rsvp_template_id']));
if(is_null($rsvp_template))
throw new EntityNotFoundException(sprintf('rsvp template id %s does not belongs to summit id %s', $data['rsvp_template_id'], $summit->getId()));
if(!$rsvp_template->isEnabled())
throw new ValidationException(sprintf('rsvp template id %s is not enabled', $data['rsvp_template_id']));
$event->setRSVPTemplate($rsvp_template);
}
if (isset($data['head_count'])) if (isset($data['head_count']))
$event->setHeadCount(intval($data['head_count'])); $event->setHeadCount(intval($data['head_count']));

View File

@ -12,7 +12,7 @@
* limitations under the License. * limitations under the License.
**/ **/
class OAuth2SummitEventsApiTest extends ProtectedApiTest final class OAuth2SummitEventsApiTest extends ProtectedApiTest
{ {
public function testPostEvent($summit_id = 23, $location_id = 0, $type_id = 0, $track_id = 0, $start_date = 1477645200, $end_date = 1477647600) public function testPostEvent($summit_id = 23, $location_id = 0, $type_id = 0, $track_id = 0, $start_date = 1477645200, $end_date = 1477647600)
{ {
@ -68,6 +68,114 @@ class OAuth2SummitEventsApiTest extends ProtectedApiTest
return $event; return $event;
} }
public function testPostEventRSVPTemplateUnExistent($summit_id = 23, $location_id = 0, $type_id = 124, $track_id = 208, $start_date = 1477645200, $end_date = 1477647600)
{
$params = array
(
'id' => $summit_id,
);
$headers = array
(
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
);
$data = array
(
'title' => 'Neutron: tbd',
'description' => 'TBD',
'allow_feedback' => true,
'type_id' => $type_id,
'tags' => ['Neutron'],
'track_id' => $track_id,
'rsvp_template_id' => 1,
);
if($start_date > 0){
$data['start_date'] = $start_date;
}
if($end_date > 0){
$data['end_date'] = $end_date;
}
if($location_id > 0){
$data['location_id'] = $location_id;
}
$response = $this->action
(
"POST",
"OAuth2SummitEventsApiController@addEvent",
$params,
array(),
array(),
array(),
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(412);
}
public function testPostEventRSVPTemplate($summit_id = 23, $location_id = 0, $type_id = 124, $track_id = 208, $start_date = 0, $end_date = 0)
{
$params = array
(
'id' => $summit_id,
);
$headers = array
(
"HTTP_Authorization" => " Bearer " . $this->access_token,
"CONTENT_TYPE" => "application/json"
);
$data = array
(
'title' => 'Neutron: tbd',
'description' => 'TBD',
'allow_feedback' => true,
'type_id' => $type_id,
'tags' => ['Neutron'],
'track_id' => $track_id,
'rsvp_template_id' => 12,
);
if($start_date > 0){
$data['start_date'] = $start_date;
}
if($end_date > 0){
$data['end_date'] = $end_date;
}
if($location_id > 0){
$data['location_id'] = $location_id;
}
$response = $this->action
(
"POST",
"OAuth2SummitEventsApiController@addEvent",
$params,
array(),
array(),
array(),
$headers,
json_encode($data)
);
$content = $response->getContent();
$this->assertResponseStatus(201);
$event = json_decode($content);
$this->assertTrue($event->id > 0);
$this->assertTrue(!$event->rsvp_external);
return $event;
}
public function testPostPresentationFail412($start_date = 1461510000, $end_date = 1461513600) public function testPostPresentationFail412($start_date = 1461510000, $end_date = 1461513600)
{ {
$params = array $params = array