diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitPromoCodesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitPromoCodesApiController.php index 0f23faaa..98a30386 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitPromoCodesApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitPromoCodesApiController.php @@ -13,6 +13,7 @@ **/ use App\Http\Utils\BooleanCellFormatter; use App\Http\Utils\EpochCellFormatter; +use App\Http\Utils\PagingConstants; use App\Models\Foundation\Summit\PromoCodes\PromoCodesConstants; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request; @@ -81,36 +82,6 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle $this->member_repository = $member_repository; } - /** - * @param $filter_element - * @return bool - */ - private function validateClassName($filter_element){ - if($filter_element instanceof FilterElement){ - return in_array($filter_element->getValue(), PromoCodesConstants::$valid_class_names); - } - $valid = true; - foreach($filter_element[0] as $elem){ - $valid = $valid && in_array($elem->getValue(), PromoCodesConstants::$valid_class_names); - } - return $valid; - } - - /** - * @param $filter_element - * @return bool - */ - private function validateTypes($filter_element){ - if($filter_element instanceof FilterElement){ - return in_array($filter_element->getValue(), PromoCodesConstants::getValidTypes()); - } - $valid = true; - foreach($filter_element[0] as $elem){ - $valid = $valid && in_array($elem->getValue(), PromoCodesConstants::getValidTypes()); - } - return $valid; - } - /** * @param $summit_id * @return mixed @@ -120,7 +91,7 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle $rules = [ 'page' => 'integer|min:1', - 'per_page' => 'required_with:page|integer|min:5|max:100', + 'per_page' => sprintf('required_with:page|integer|min:%s|max:%s', PagingConstants::MinPageSize, PagingConstants::MaxPageSize), ]; try { @@ -137,7 +108,7 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle // default values $page = 1; - $per_page = 5; + $per_page = PagingConstants::DefaultPageSize;; if (Input::has('page')) { $page = intval(Input::get('page')); @@ -162,6 +133,32 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle ]); } + if(is_null($filter)) $filter = new Filter(); + + $filter->validate([ + 'class_name' => sprintf('sometimes|in:%s',implode(',', PromoCodesConstants::$valid_class_names)), + 'code' => 'sometimes|string', + 'creator' => 'sometimes|string', + 'creator_email' => 'sometimes|string', + 'owner' => 'sometimes|string', + 'owner_email' => 'sometimes|string', + 'speaker' => 'sometimes|string', + 'speaker_email' => 'sometimes|string', + 'sponsor' => 'sometimes|string', + 'type' => sprintf('sometimes|in:%s',implode(',', PromoCodesConstants::getValidTypes())), + ], [ + 'class_name.in' => sprintf + ( + ":attribute has an invalid value ( valid values are %s )", + implode(", ", PromoCodesConstants::$valid_class_names) + ), + 'type.in' => sprintf + ( + ":attribute has an invalid value ( valid values are %s )", + implode(", ", PromoCodesConstants::getValidTypes()) + ) + ]); + $order = null; if (Input::has('order')) @@ -173,28 +170,6 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle ]); } - if(is_null($filter)) $filter = new Filter(); - - if($filter->hasFilter("class_name") && !$this->validateClassName($filter->getFilter("class_name"))){ - throw new ValidationException( - sprintf - ( - "class_name filter has an invalid value ( valid values are %s", - implode(", ", PromoCodesConstants::$valid_class_names) - ) - ); - } - - if($filter->hasFilter("type") && !$this->validateTypes($filter->getFilter("type"))){ - throw new ValidationException( - sprintf - ( - "type filter has an invalid value ( valid values are %s", - implode(", ", PromoCodesConstants::getValidTypes()) - ) - ); - } - $data = $this->promo_code_repository->getBySummit($summit, new PagingInfo($page, $per_page), $filter, $order); return $this->ok @@ -257,7 +232,6 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle if (Input::has('filter')) { $filter = FilterParser::parse(Input::get('filter'), [ - 'code' => ['=@', '=='], 'creator' => ['=@', '=='], 'creator_email' => ['=@', '=='], @@ -271,6 +245,32 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle ]); } + if(is_null($filter)) $filter = new Filter(); + + $filter->validate([ + 'class_name' => sprintf('sometimes|in:%s',implode(',', PromoCodesConstants::$valid_class_names)), + 'code' => 'sometimes|string', + 'creator' => 'sometimes|string', + 'creator_email' => 'sometimes|string', + 'owner' => 'sometimes|string', + 'owner_email' => 'sometimes|string', + 'speaker' => 'sometimes|string', + 'speaker_email' => 'sometimes|string', + 'sponsor' => 'sometimes|string', + 'type' => sprintf('sometimes|in:%s',implode(',', PromoCodesConstants::getValidTypes())), + ], [ + 'class_name.in' => sprintf + ( + ":attribute has an invalid value ( valid values are %s )", + implode(", ", PromoCodesConstants::$valid_class_names) + ), + 'type.in' => sprintf + ( + ":attribute has an invalid value ( valid values are %s )", + implode(", ", PromoCodesConstants::getValidTypes()) + ) + ]); + $order = null; if (Input::has('order')) @@ -282,28 +282,6 @@ final class OAuth2SummitPromoCodesApiController extends OAuth2ProtectedControlle ]); } - if(is_null($filter)) $filter = new Filter(); - - if($filter->hasFilter("class_name") && !$this->validateClassName($filter->getFilter("class_name"))){ - throw new ValidationException( - sprintf - ( - "class_name filter has an invalid value ( valid values are %s", - implode(", ", PromoCodesConstants::$valid_class_names) - ) - ); - } - - if($filter->hasFilter("type") && !$this->validateTypes($filter->getFilter("type"))){ - throw new ValidationException( - sprintf - ( - "type filter has an invalid value ( valid values are %s", - implode(", ", PromoCodesConstants::getValidTypes()) - ) - ); - } - $data = $this->promo_code_repository->getBySummit($summit, new PagingInfo($page, $per_page), $filter, $order); $filename = "promocodes-" . date('Ymd'); $list = $data->toArray(); diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitRSVPTemplatesApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitRSVPTemplatesApiController.php new file mode 100644 index 00000000..ae8bbb49 --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitRSVPTemplatesApiController.php @@ -0,0 +1,159 @@ +summit_repository = $summit_repository; + $this->rsvp_template_repository = $rsvp_template_repository; + } + + /** + * @param $summit_id + * @return mixed + */ + public function getAllBySummit($summit_id){ + + $values = Input::all(); + $rules = [ + + 'page' => 'integer|min:1', + 'per_page' => sprintf('required_with:page|integer|min:%s|max:%s', PagingConstants::MinPageSize, PagingConstants::MaxPageSize), + ]; + + try { + + $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) + return $this->error404(); + + $validation = Validator::make($values, $rules); + + if ($validation->fails()) { + $ex = new ValidationException(); + throw $ex->setMessages($validation->messages()->toArray()); + } + + // default values + $page = 1; + $per_page = PagingConstants::DefaultPageSize;; + + if (Input::has('page')) { + $page = intval(Input::get('page')); + $per_page = intval(Input::get('per_page')); + } + + $filter = null; + + if (Input::has('filter')) { + $filter = FilterParser::parse(Input::get('filter'), [ + 'title' => ['=@', '=='], + 'is_enabled' => [ '=='], + ]); + } + + if(is_null($filter)) $filter = new Filter(); + + $filter->validate([ + 'title' => 'sometimes|string', + 'is_enabled' => 'sometimes|boolean', + ]); + + $order = null; + + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), [ + 'id', + 'title', + ]); + } + + $data = $this->rsvp_template_repository->getBySummit($summit, new PagingInfo($page, $per_page), $filter, $order); + + return $this->ok + ( + $data->toArray + ( + Request::input('expand', ''), + [], + [], + [] + ) + ); + } + catch (ValidationException $ex1) + { + Log::warning($ex1); + return $this->error412([ $ex1->getMessage()]); + } + catch (EntityNotFoundException $ex2) + { + Log::warning($ex2); + return $this->error404(['message' => $ex2->getMessage()]); + } + catch(\HTTP401UnauthorizedException $ex3) + { + Log::warning($ex3); + return $this->error401(); + } + catch (\Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } +} \ No newline at end of file diff --git a/app/Http/Utils/Filters/Filter.php b/app/Http/Utils/Filters/Filter.php index c72404ab..8eaae31c 100644 --- a/app/Http/Utils/Filters/Filter.php +++ b/app/Http/Utils/Filters/Filter.php @@ -147,7 +147,7 @@ final class Filter * @param array $messages * @throws ValidationException */ - public function validate(array $rules, array $messages){ + public function validate(array $rules, array $messages = []){ $filter_key_values = $this->getFiltersKeyValues(); foreach($rules as $field => $rule) { if(!isset($filter_key_values[$field])) continue; diff --git a/app/Http/routes.php b/app/Http/routes.php index 9f79d148..ff0f68a1 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -164,6 +164,11 @@ Route::group([ Route::group(array('prefix' => '{id}'), function () { + // rsvp templates + Route::group(array('prefix' => 'rsvp-templates'), function () { + Route::get('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitRSVPTemplatesApiController@getAllBySummit']); + }); + Route::get('', [ 'middleware' => 'cache:'.Config::get('cache_api_response.get_summit_response_lifetime', 1200), 'uses' => 'OAuth2SummitApiController@getSummit'])->where('id', 'current|[0-9]+'); Route::get('entity-events', 'OAuth2SummitApiController@getSummitEntityEvents'); @@ -295,6 +300,7 @@ Route::group([ Route::group(['prefix' => 'rooms'], function () { Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitLocationsApiController@addVenueRoom']); Route::group(['prefix' => '{room_id}'], function () { + Route::get('', 'OAuth2SummitLocationsApiController@getVenueRoom'); Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitLocationsApiController@updateVenueRoom']); Route::delete('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitLocationsApiController@deleteVenueRoom']); }); diff --git a/app/ModelSerializers/Locations/SummitVenueRoomSerializer.php b/app/ModelSerializers/Locations/SummitVenueRoomSerializer.php index e562ac11..f75ac7f7 100644 --- a/app/ModelSerializers/Locations/SummitVenueRoomSerializer.php +++ b/app/ModelSerializers/Locations/SummitVenueRoomSerializer.php @@ -19,12 +19,12 @@ use ModelSerializers\SerializerRegistry; */ final class SummitVenueRoomSerializer extends SummitAbstractLocationSerializer { - protected static $array_mappings = array - ( - 'VenueId' => 'venue_id:json_int', - 'FloorId' => 'floor_id:json_int', - 'Capacity' => 'capacity:json_int', - ); + protected static $array_mappings = [ + 'VenueId' => 'venue_id:json_int', + 'FloorId' => 'floor_id:json_int', + 'Capacity' => 'capacity:json_int', + 'OverrideBlackouts' => 'override_blackouts:json_boolean', + ]; public function serialize($expand = null, array $fields = array(), array $relations = array(), array $params = array() ) { diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index a61200bf..25e18d21 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -36,6 +36,10 @@ use App\ModelSerializers\Marketplace\SpokenLanguageSerializer; use App\ModelSerializers\Marketplace\SupportChannelTypeSerializer; use App\ModelSerializers\Software\OpenStackComponentSerializer; use App\ModelSerializers\Software\OpenStackReleaseSerializer; +use App\ModelSerializers\Summit\RSVP\Templates\RSVPMultiValueQuestionTemplateSerializer; +use App\ModelSerializers\Summit\RSVP\Templates\RSVPQuestionValueTemplateSerializer; +use App\ModelSerializers\Summit\RSVP\Templates\RSVPSingleValueTemplateQuestionSerializer; +use App\ModelSerializers\Summit\RSVPTemplateSerializer; use App\ModelSerializers\Summit\ScheduledSummitLocationBannerSerializer; use App\ModelSerializers\Summit\SummitLocationBannerSerializer; use Libs\ModelSerializers\IModelSerializer; @@ -107,7 +111,22 @@ final class SerializerRegistry self::SerializerType_Private => AdminPresentationSpeakerSerializer::class ]; + // RSVP $this->registry['RSVP'] = RSVPSerializer::class; + $this->registry['RSVPTemplate'] = RSVPTemplateSerializer::class; + $this->registry['RSVPQuestionValueTemplate'] = RSVPQuestionValueTemplateSerializer::class; + + $this->registry['RSVPSingleValueTemplateQuestion'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPTextBoxQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPTextAreaQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPMemberEmailQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPMemberFirstNameQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPMemberLastNameQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + $this->registry['RSVPMemberLastNameQuestionTemplate'] = RSVPSingleValueTemplateQuestionSerializer::class; + + $this->registry['RSVPCheckBoxListQuestionTemplate'] = RSVPMultiValueQuestionTemplateSerializer::class; + $this->registry['RSVPRadioButtonListQuestionTemplate'] = RSVPMultiValueQuestionTemplateSerializer::class; + $this->registry['SpeakerExpertise'] = SpeakerExpertiseSerializer::class; $this->registry['SpeakerLanguage'] = SpeakerLanguageSerializer::class; $this->registry['SpeakerTravelPreference'] = SpeakerTravelPreferenceSerializer::class; diff --git a/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php b/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php index f2ee3f0b..1a83cea4 100644 --- a/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php +++ b/app/ModelSerializers/Summit/Presentation/PresentationSpeakerSummitAssistanceConfirmationRequestSerializer.php @@ -11,9 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use models\summit\PresentationSpeakerSummitAssistanceConfirmationRequest; - /** * Class PresentationSpeakerSummitAssistanceConfirmationRequestSerializer * @package ModelSerializers diff --git a/app/ModelSerializers/Summit/RSVPSerializer.php b/app/ModelSerializers/Summit/RSVP/RSVPSerializer.php similarity index 94% rename from app/ModelSerializers/Summit/RSVPSerializer.php rename to app/ModelSerializers/Summit/RSVP/RSVPSerializer.php index 1291d720..b55ce4bc 100644 --- a/app/ModelSerializers/Summit/RSVPSerializer.php +++ b/app/ModelSerializers/Summit/RSVP/RSVPSerializer.php @@ -17,11 +17,11 @@ */ final class RSVPSerializer extends SilverStripeSerializer { - protected static $array_mappings = array - ( + protected static $array_mappings = [ + 'OwnerId' => '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/RSVP/Templates/RSVPLiteralContentQuestionTemplateSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPLiteralContentQuestionTemplateSerializer.php new file mode 100644 index 00000000..b66e0462 --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPLiteralContentQuestionTemplateSerializer.php @@ -0,0 +1,25 @@ + 'content:json_string', + ]; + +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/RSVP/Templates/RSVPMultiValueQuestionTemplateSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPMultiValueQuestionTemplateSerializer.php new file mode 100644 index 00000000..6564d64a --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPMultiValueQuestionTemplateSerializer.php @@ -0,0 +1,52 @@ + 'empty_string:json_string', + ]; + + /** + * @param null $expand + * @param array $fields + * @param array $relations + * @param array $params + * @return array + */ + public function serialize($expand = null, array $fields = [], array $relations = [], array $params = []) + { + $question = $this->object; + if(! $question instanceof RSVPMultiValueQuestionTemplate) return []; + $values = parent::serialize($expand, $fields, $relations, $params); + + $question_values = []; + foreach ($question->getValues() as $value){ + $question_values[] = SerializerRegistry::getInstance()->getSerializer($value)->serialize($expand, [], ['none']); + } + + $values['values'] = $question_values; + if($question->hasDefaultValue()) + $values['default_value'] = SerializerRegistry::getInstance()->getSerializer($question->getDefaultValue())->serialize($expand, [], ['none']);; + + return $values; + } +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionTemplateSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionTemplateSerializer.php new file mode 100644 index 00000000..f9ef5b52 --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionTemplateSerializer.php @@ -0,0 +1,29 @@ + 'name:json_string', + 'Label' => 'label:json_string', + 'Order' => 'order:json_int', + 'Mandatory' => 'is_mandatory:json_boolean', + 'ReadOnly' => 'is_read_only:json_boolean', + 'ClassName' => 'class_name:json_string', + ]; +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionValueTemplateSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionValueTemplateSerializer.php new file mode 100644 index 00000000..3c80fb61 --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPQuestionValueTemplateSerializer.php @@ -0,0 +1,27 @@ + 'value:json_string', + 'Label' => 'label:json_string', + 'Order' => 'order:json_int', + 'OwnerId' => 'owner_id:json_int', + ]; +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/RSVP/Templates/RSVPSingleValueTemplateQuestionSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPSingleValueTemplateQuestionSerializer.php new file mode 100644 index 00000000..b2ce3d6e --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPSingleValueTemplateQuestionSerializer.php @@ -0,0 +1,24 @@ + 'initial_value:json_string', + ]; +} \ No newline at end of file diff --git a/app/ModelSerializers/Summit/RSVP/Templates/RSVPTemplateSerializer.php b/app/ModelSerializers/Summit/RSVP/Templates/RSVPTemplateSerializer.php new file mode 100644 index 00000000..0e0bd9af --- /dev/null +++ b/app/ModelSerializers/Summit/RSVP/Templates/RSVPTemplateSerializer.php @@ -0,0 +1,71 @@ + 'title:json_string', + 'Enabled' => 'is_enable:json_boolean', + 'CreatedById' => 'created_by_id:json_int', + 'SummitId' => 'summit_id:json_int', + ]; + + /** + * @param null $expand + * @param array $fields + * @param array $relations + * @param array $params + * @return array + */ + public function serialize($expand = null, array $fields = [], array $relations = [], array $params = []) + { + $template = $this->object; + if(! $template instanceof RSVPTemplate) return []; + $values = parent::serialize($expand, $fields, $relations, $params); + + $questions = []; + foreach ($template->getQuestions() as $question){ + $questions[] = SerializerRegistry::getInstance()->getSerializer($question)->serialize($expand, [], ['none']); + } + + $values['questions'] = $questions; + + if (!empty($expand)) { + $exp_expand = explode(',', $expand); + foreach ($exp_expand as $relation) { + switch (trim($relation)) { + + case 'created_by': + { + if($template->hasCreatedBy()) { + unset($values['created_by_id']); + $values['created_by'] = SerializerRegistry::getInstance()->getSerializer($template)->serialize($expand, [], ['none']); + } + } + break; + } + } + } + + return $values; + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Group.php b/app/Models/Foundation/Main/Group.php index 1214ea30..3fcc5a3c 100644 --- a/app/Models/Foundation/Main/Group.php +++ b/app/Models/Foundation/Main/Group.php @@ -15,7 +15,6 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Mapping AS ORM; use models\utils\SilverstripeBaseModel; - /** * @ORM\Entity(repositoryClass="repositories\main\DoctrineGroupRepository") * @ORM\Table(name="`Group`") diff --git a/app/Models/Foundation/Summit/Events/Presentations/PrivatePresentationCategoryGroup.php b/app/Models/Foundation/Summit/Events/Presentations/PrivatePresentationCategoryGroup.php index 9f8a6260..f95a9aa3 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/PrivatePresentationCategoryGroup.php +++ b/app/Models/Foundation/Summit/Events/Presentations/PrivatePresentationCategoryGroup.php @@ -44,7 +44,7 @@ class PrivatePresentationCategoryGroup extends PresentationCategoryGroup protected $max_submission_allowed_per_user; /** - * @ORM\ManyToMany(targetEntity="models\main\Group", inversedBy="groups") + * @ORM\ManyToMany(targetEntity="models\main\Group") * @ORM\JoinTable(name="PrivatePresentationCategoryGroup_AllowedGroups", * joinColumns={@ORM\JoinColumn(name="PrivatePresentationCategoryGroupID", referencedColumnName="ID")}, * inverseJoinColumns={@ORM\JoinColumn(name="GroupID", referencedColumnName="ID")} diff --git a/app/Models/Foundation/Summit/Events/Presentations/SummitSelectedPresentation.php b/app/Models/Foundation/Summit/Events/Presentations/SummitSelectedPresentation.php index 21a3c975..dd8945cc 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/SummitSelectedPresentation.php +++ b/app/Models/Foundation/Summit/Events/Presentations/SummitSelectedPresentation.php @@ -42,14 +42,14 @@ class SummitSelectedPresentation extends SilverstripeBaseModel private $order; /** - * @ORM\ManyToOne(targetEntity="SummitSelectedPresentationList") + * @ORM\ManyToOne(targetEntity="SummitSelectedPresentationList", inversedBy="selected_presentations") * @ORM\JoinColumn(name="SummitSelectedPresentationListID", referencedColumnName="ID") * @var SummitSelectedPresentationList */ private $list; /** - * @ORM\ManyToOne(targetEntity="Presentation") + * @ORM\ManyToOne(targetEntity="Presentation", inversedBy="selected_presentations") * @ORM\JoinColumn(name="PresentationID", referencedColumnName="ID") * @var Presentation */ diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPCheckBoxListQuestionTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPCheckBoxListQuestionTemplate.php new file mode 100644 index 00000000..1db9330f --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPCheckBoxListQuestionTemplate.php @@ -0,0 +1,29 @@ +content; + } + + /** + * @param string $content + */ + public function setContent($content) + { + $this->content = $content; + } + + +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPMemberEmailQuestionTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPMemberEmailQuestionTemplate.php new file mode 100644 index 00000000..884842d4 --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPMemberEmailQuestionTemplate.php @@ -0,0 +1,29 @@ +empty_string; + } + + /** + * @param string $empty_string + */ + public function setEmptyString($empty_string) + { + $this->empty_string = $empty_string; + } + + /** + * @return RSVPQuestionValueTemplate[] + */ + public function getValues() + { + $criteria = Criteria::create(); + $criteria->orderBy(['order'=> 'ASC']); + return $this->values->matching($criteria); + } + + /** + * @param mixed $values + */ + public function setValues($values) + { + $this->values = $values; + } + + /** + * @return RSVPQuestionValueTemplate + */ + public function getDefaultValue() + { + return $this->default_value; + } + + /** + * @param RSVPQuestionValueTemplate $default_value + */ + public function setDefaultValue(RSVPQuestionValueTemplate $default_value) + { + $this->default_value = $default_value; + } + + public function __construct() + { + parent::__construct(); + $this->values = new ArrayCollection; + } + + /** + * @return string + */ + public function getClassName(){ + return 'RSVPMultiValueQuestionTemplate'; + } + + /** + * @return bool + */ + public function hasDefaultValue(){ + return $this->getDefaultValueId() > 0; + } + + /** + * @return int + */ + public function getDefaultValueId(){ + try{ + return is_null($this->default_value) ? 0 : $this->default_value->getId(); + } + catch (\Exception $ex){ + return 0; + } + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionDependsOn.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionDependsOn.php new file mode 100644 index 00000000..a963faef --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionDependsOn.php @@ -0,0 +1,153 @@ +parent; + } + + /** + * @param RSVPQuestionTemplate $parent + */ + public function setParent($parent) + { + $this->parent = $parent; + } + + /** + * @return RSVPQuestionTemplate + */ + public function getChild() + { + return $this->child; + } + + /** + * @param RSVPQuestionTemplate $child + */ + public function setChild($child) + { + $this->child = $child; + } + + /** + * @return string + */ + public function getOperator() + { + return $this->operator; + } + + /** + * @param string $operator + */ + public function setOperator($operator) + { + $this->operator = $operator; + } + + /** + * @return string + */ + public function getVisibility() + { + return $this->visibility; + } + + /** + * @param string $visibility + */ + public function setVisibility($visibility) + { + $this->visibility = $visibility; + } + + /** + * @return string + */ + public function getDefaultValue() + { + return $this->default_value; + } + + /** + * @param string $default_value + */ + public function setDefaultValue($default_value) + { + $this->default_value = $default_value; + } + + /** + * @return string + */ + public function getBooleanOp() + { + return $this->boolean_op; + } + + /** + * @param string $boolean_op + */ + public function setBooleanOp($boolean_op) + { + $this->boolean_op = $boolean_op; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionTemplate.php new file mode 100644 index 00000000..b508c3cd --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionTemplate.php @@ -0,0 +1,186 @@ +name; + } + + /** + * @param string $name + */ + public function setName($name) + { + $this->name = $name; + } + + /** + * @return string + */ + public function getLabel() + { + return $this->label; + } + + /** + * @param string $label + */ + public function setLabel($label) + { + $this->label = $label; + } + + /** + * @return bool + */ + public function isMandatory() + { + return $this->is_mandatory; + } + + /** + * @param bool $is_mandatory + */ + public function setIsMandatory($is_mandatory) + { + $this->is_mandatory = $is_mandatory; + } + + /** + * @return string + */ + public function getOrder() + { + return $this->order; + } + + /** + * @param string $order + */ + public function setOrder($order) + { + $this->order = $order; + } + + /** + * @return bool + */ + public function isReadOnly() + { + return $this->is_read_only; + } + + /** + * @param bool $is_read_only + */ + public function setIsReadOnly($is_read_only) + { + $this->is_read_only = $is_read_only; + } + + /** + * @return RSVPTemplate + */ + public function getTemplate() + { + return $this->template; + } + + /** + * @param RSVPTemplate $template + */ + public function setTemplate(RSVPTemplate $template) + { + $this->template = $template; + } + + /** + * @return string + */ + public function getClassName(){ + return 'RSVPQuestionTemplate'; + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionValueTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionValueTemplate.php new file mode 100644 index 00000000..800c958e --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPQuestionValueTemplate.php @@ -0,0 +1,124 @@ +value; + } + + /** + * @param string $value + */ + public function setValue($value) + { + $this->value = $value; + } + + /** + * @return string + */ + public function getLabel() + { + return $this->label; + } + + /** + * @param string $label + */ + public function setLabel($label) + { + $this->label = $label; + } + + /** + * @return int + */ + public function getOrder() + { + return $this->order; + } + + /** + * @param int $order + */ + public function setOrder($order) + { + $this->order = $order; + } + + /** + * @return RSVPMultiValueQuestionTemplate + */ + public function getOwner() + { + return $this->owner; + } + + /** + * @param RSVPMultiValueQuestionTemplate $owner + */ + public function setOwner(RSVPMultiValueQuestionTemplate $owner) + { + $this->owner = $owner; + } + + /** + * @return int + */ + public function getOwnerId(){ + try{ + return is_null($this->owner) ? 0 : $this->owner->getId(); + } + catch (\Exception $ex){ + return 0; + } + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPRadioButtonListQuestionTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPRadioButtonListQuestionTemplate.php new file mode 100644 index 00000000..d2bdc048 --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPRadioButtonListQuestionTemplate.php @@ -0,0 +1,29 @@ +initial_value; + } + + /** + * @param string $initial_value + */ + public function setInitialValue($initial_value) + { + $this->initial_value = $initial_value; + } + + /** + * @return string + */ + public function getClassName(){ + return 'RSVPSingleValueTemplateQuestion'; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/RSVPTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTemplate.php similarity index 65% rename from app/Models/Foundation/Summit/Events/RSVP/RSVPTemplate.php rename to app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTemplate.php index c9b651e3..fb802813 100644 --- a/app/Models/Foundation/Summit/Events/RSVP/RSVPTemplate.php +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTemplate.php @@ -11,6 +11,8 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Criteria; use models\main\Member; use models\summit\SummitOwned; use models\utils\SilverstripeBaseModel; @@ -44,6 +46,12 @@ class RSVPTemplate extends SilverstripeBaseModel */ private $created_by; + /** + * @ORM\OneToMany(targetEntity="RSVPQuestionTemplate", mappedBy="template", cascade={"persist"}, orphanRemoval=true) + * @var RSVPQuestionTemplate[] + */ + private $questions; + /** * @return string */ @@ -91,4 +99,48 @@ class RSVPTemplate extends SilverstripeBaseModel { $this->created_by = $created_by; } + + /** + * @return int + */ + public function getCreatedById(){ + try{ + return is_null($this->created_by) ? 0 : $this->created_by->getId(); + } + catch (\Exception $ex){ + return 0; + } + } + + /** + * @return bool + */ + public function hasCreatedBy(){ + return $this->getCreatedById() > 0; + } + + public function __construct() + { + parent::__construct(); + $this->questions = new ArrayCollection; + } + + /** + * @return RSVPQuestionTemplate[] + */ + public function getQuestions() + { + $criteria = Criteria::create(); + $criteria->orderBy(['order'=> 'ASC']); + return $this->questions->matching($criteria); + } + + /** + * @param mixed $questions + */ + public function setQuestions($questions) + { + $this->questions = $questions; + } + } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTextAreaQuestionTemplate.php b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTextAreaQuestionTemplate.php new file mode 100644 index 00000000..a28f33bf --- /dev/null +++ b/app/Models/Foundation/Summit/Events/RSVP/Templates/RSVPTextAreaQuestionTemplate.php @@ -0,0 +1,29 @@ +getLocalEndDate(); foreach ($this->banners as $old_banner){ - if($old_banner instanceof ScheduledSummitLocationBanner && $old_banner->isEnabled() && $old_banner->getId() != $banner->getId()){ + if($old_banner instanceof ScheduledSummitLocationBanner + && $old_banner->isEnabled() + && $old_banner->getId() != $banner->getId() + && $old_banner->getType() == $banner->getType()){ $old_start = $old_banner->getLocalStartDate(); $old_end = $old_banner->getLocalEndDate(); // (StartA <= EndB) and (EndA >= StartB) diff --git a/app/Models/Foundation/Summit/Locations/SummitVenueFloor.php b/app/Models/Foundation/Summit/Locations/SummitVenueFloor.php index ac5c48ba..430a877d 100644 --- a/app/Models/Foundation/Summit/Locations/SummitVenueFloor.php +++ b/app/Models/Foundation/Summit/Locations/SummitVenueFloor.php @@ -166,7 +166,7 @@ class SummitVenueFloor extends SilverstripeBaseModel public function __construct() { parent::__construct(); - $this->rooms = new ArrayCollection(); + $this->rooms = new ArrayCollection; } /** diff --git a/app/Models/Foundation/Summit/PromoCodes/SpeakerSummitRegistrationPromoCode.php b/app/Models/Foundation/Summit/PromoCodes/SpeakerSummitRegistrationPromoCode.php index f7fbf675..75b7cba2 100644 --- a/app/Models/Foundation/Summit/PromoCodes/SpeakerSummitRegistrationPromoCode.php +++ b/app/Models/Foundation/Summit/PromoCodes/SpeakerSummitRegistrationPromoCode.php @@ -30,7 +30,7 @@ class SpeakerSummitRegistrationPromoCode extends SummitRegistrationPromoCode protected $type; /** - * @ORM\ManyToOne(targetEntity="PresentationSpeaker") + * @ORM\ManyToOne(targetEntity="PresentationSpeaker", inversedBy="promo_codes") * @ORM\JoinColumn(name="SpeakerID", referencedColumnName="ID") * @var PresentationSpeaker */ diff --git a/app/Models/Foundation/Summit/Repositories/IRSVPTemplateRepository.php b/app/Models/Foundation/Summit/Repositories/IRSVPTemplateRepository.php index aa713398..9bdcb4eb 100644 --- a/app/Models/Foundation/Summit/Repositories/IRSVPTemplateRepository.php +++ b/app/Models/Foundation/Summit/Repositories/IRSVPTemplateRepository.php @@ -11,12 +11,31 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ +use models\summit\Summit; use models\utils\IBaseRepository; +use utils\Filter; +use utils\Order; +use utils\PagingInfo; +use utils\PagingResponse; /** * Interface IRSVPTemplateRepository * @package App\Models\Foundation\Summit\Repositories */ interface IRSVPTemplateRepository extends IBaseRepository { + /** + * @param Summit $summit + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return PagingResponse + */ + public function getBySummit + ( + Summit $summit, + PagingInfo $paging_info, + Filter $filter = null, + Order $order = null + ); } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Speakers/PresentationSpeakerSummitAssistanceConfirmationRequest.php b/app/Models/Foundation/Summit/Speakers/PresentationSpeakerSummitAssistanceConfirmationRequest.php index 15194052..86ba9301 100644 --- a/app/Models/Foundation/Summit/Speakers/PresentationSpeakerSummitAssistanceConfirmationRequest.php +++ b/app/Models/Foundation/Summit/Speakers/PresentationSpeakerSummitAssistanceConfirmationRequest.php @@ -53,7 +53,7 @@ class PresentationSpeakerSummitAssistanceConfirmationRequest extends Silverstrip private $confirmation_date; /** - * @ORM\ManyToOne(targetEntity="PresentationSpeaker") + * @ORM\ManyToOne(targetEntity="PresentationSpeaker", inversedBy="summit_assistances") * @ORM\JoinColumn(name="SpeakerID", referencedColumnName="ID") * @var PresentationSpeaker */ diff --git a/app/Models/Foundation/Summit/Speakers/SpeakerAnnouncementSummitEmail.php b/app/Models/Foundation/Summit/Speakers/SpeakerAnnouncementSummitEmail.php index a2d12960..7102680f 100644 --- a/app/Models/Foundation/Summit/Speakers/SpeakerAnnouncementSummitEmail.php +++ b/app/Models/Foundation/Summit/Speakers/SpeakerAnnouncementSummitEmail.php @@ -51,7 +51,7 @@ class SpeakerAnnouncementSummitEmail extends SilverstripeBaseModel Use SummitOwned; /** - * @ORM\ManyToOne(targetEntity="models\summit\PresentationSpeaker") + * @ORM\ManyToOne(targetEntity="models\summit\PresentationSpeaker", inversedBy="announcement_summit_emails") * @ORM\JoinColumn(name="SpeakerID", referencedColumnName="ID") * @var PresentationSpeaker */ @@ -105,6 +105,4 @@ class SpeakerAnnouncementSummitEmail extends SilverstripeBaseModel $this->speaker = $speaker; } - - } \ No newline at end of file diff --git a/app/Repositories/Main/DoctrineFolderRepository.php b/app/Repositories/Main/DoctrineFolderRepository.php index 0a45e02e..382279b8 100644 --- a/app/Repositories/Main/DoctrineFolderRepository.php +++ b/app/Repositories/Main/DoctrineFolderRepository.php @@ -35,7 +35,6 @@ final class DoctrineFolderRepository select * from File where ClassName = 'Folder' AND Name = :folder_name SQL; - // build rsm here $rsm = new ResultSetMappingBuilder($this->_em); $rsm->addRootEntityFromClassMetadata(\models\main\File::class, 'f'); @@ -43,7 +42,7 @@ SQL; $native_query->setParameter("folder_name", $folder_name); - return $native_query->getSingleResult(); + return $native_query->getOneOrNullResult(); } /** diff --git a/app/Repositories/Summit/DoctrineRSVPTemplateRepository.php b/app/Repositories/Summit/DoctrineRSVPTemplateRepository.php index 10449ea9..292c5cc5 100644 --- a/app/Repositories/Summit/DoctrineRSVPTemplateRepository.php +++ b/app/Repositories/Summit/DoctrineRSVPTemplateRepository.php @@ -14,6 +14,12 @@ use App\Models\Foundation\Summit\Events\RSVP\RSVPTemplate; use App\Models\Foundation\Summit\Repositories\IRSVPTemplateRepository; use App\Repositories\SilverStripeDoctrineRepository; +use Doctrine\ORM\Tools\Pagination\Paginator; +use models\summit\Summit; +use utils\Filter; +use utils\Order; +use utils\PagingInfo; +use utils\PagingResponse; /** * Class DoctrineRSVPTemplateRepository * @package App\Repositories\Summit @@ -30,4 +36,80 @@ final class DoctrineRSVPTemplateRepository { return RSVPTemplate::class; } + + protected function getFilterMappings() + { + return [ + 'title' => 't.title:json_string', + 'is_enabled' => 't.is_enabled:json_boolean', + ]; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'id' => 't.id', + 'title' => 't.title', + ]; + } + + /** + * @param Summit $summit + * @param PagingInfo $paging_info + * @param Filter|null $filter + * @param Order|null $order + * @return mixed + */ + public function getBySummit + ( + Summit $summit, + PagingInfo $paging_info, + Filter $filter = null, + Order $order = null + ) + { + $query = $this->getEntityManager() + ->createQueryBuilder() + ->select("t") + ->from(RSVPTemplate::class, "t") + ->leftJoin('t.summit', 's') + ->leftJoin('t.created_by', 'o') + ->where("s.id = :summit_id"); + + $query->setParameter("summit_id", $summit->getId()); + + if(!is_null($filter)){ + $filter->apply2Query($query, $this->getFilterMappings()); + } + + if (!is_null($order)) { + $order->apply2Query($query, $this->getOrderMappings()); + } else { + //default order + $query = $query->addOrderBy("t.id",'ASC'); + } + + $query = $query + ->setFirstResult($paging_info->getOffset()) + ->setMaxResults($paging_info->getPerPage()); + + $paginator = new Paginator($query, $fetchJoinCollection = true); + $total = $paginator->count(); + $data = []; + + foreach($paginator as $entity) + $data[] = $entity; + + return new PagingResponse + ( + $total, + $paging_info->getPerPage(), + $paging_info->getCurrentPage(), + $paging_info->getLastPage($total), + $data + ); + } } \ No newline at end of file diff --git a/app/Services/Model/LocationService.php b/app/Services/Model/LocationService.php index 52349db2..cb1758ec 100644 --- a/app/Services/Model/LocationService.php +++ b/app/Services/Model/LocationService.php @@ -756,7 +756,7 @@ final class LocationService implements ILocationService if (isset($data['name'])) { $old_location = $summit->getLocationByName(trim($data['name'])); - if (!is_null($old_location)) { + if (!is_null($old_location) && $old_location->getId() != $room_id) { throw new ValidationException ( trans @@ -1057,7 +1057,7 @@ final class LocationService implements ILocationService ); } - $banner = SummitLocationBannerFactory::populate($summit, $location, $data, $banner); + $banner = SummitLocationBannerFactory::populate($summit, $location, $banner, $data); $location->validateBanner($banner); return $banner; }); diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 33827eff..1a51a88f 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -546,6 +546,43 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::WriteLocationsData, $current_realm) ], ], + // images + [ + 'name' => 'add-location-image', + 'route' => '/api/v1/summits/{id}/locations/{location_id}/images', + 'http_method' => 'POST', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteLocationsData, $current_realm) + ], + ], + [ + 'name' => 'update-location-image', + 'route' => '/api/v1/summits/{id}/locations/{location_id}/images/{image_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteLocationsData, $current_realm) + ], + ], + [ + 'name' => 'get-location-image', + 'route' => '/api/v1/summits/{id}/locations/{location_id}/images/{image_id}', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SummitScopes::ReadSummitData, $current_realm), + sprintf(SummitScopes::ReadAllSummitData, $current_realm) + ], + ], + [ + 'name' => 'delete-location-image', + 'route' => '/api/v1/summits/{id}/locations/{location_id}/images/{image_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SummitScopes::WriteSummitData, $current_realm), + sprintf(SummitScopes::WriteLocationsData, $current_realm) + ], + ], // banners [ 'name' => 'get-location-banners', @@ -651,6 +688,15 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::WriteLocationsData, $current_realm) ], ], + // rsvp templates + [ + 'name' => 'get-rsvp-templates', + 'route' => '/api/v1/summits/{id}/rsvp-templates', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SummitScopes::ReadAllSummitData, $current_realm) + ], + ], // rooms [ 'name' => 'get-venue-room', diff --git a/tests/OAuth2SummitRSVPTemplateApiTest.php b/tests/OAuth2SummitRSVPTemplateApiTest.php new file mode 100644 index 00000000..e19ef898 --- /dev/null +++ b/tests/OAuth2SummitRSVPTemplateApiTest.php @@ -0,0 +1,49 @@ + $summit_id, + 'page' => 1, + 'per_page' => 5, + 'order' => '-id' + ]; + + $headers = + [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action + ( + "GET", + "OAuth2SummitRSVPTemplatesApiController@getAllBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + + $rsvp_templates = json_decode($content); + $this->assertTrue(!is_null($rsvp_templates)); + } +} \ No newline at end of file