From 35fc57473c7929fd557f820eae2c8def733edf90 Mon Sep 17 00:00:00 2001 From: smarcet Date: Mon, 23 Nov 2020 17:26:06 -0300 Subject: [PATCH] Sponsored Projects - Endpoints POST /api/v1/sponsored-projects payload name description is_active scope REALM_URL/sponsored-projects/write GET /api/v1/sponsored-projects scope REALM_URL/sponsored-projects/read PUT /api/v1/sponsored-projects/{id} payload name description is_active scope REALM_URL/sponsored-projects/write GET /api/v1/sponsored-projects/{id} scope REALM_URL/sponsored-projects/read PUBLIC GET /api/public/v1/sponsored-projects/{slug} DELETE /api/v1/sponsored-projects/{id} scope REALM_URL/sponsored-projects/write POST /api/v1/sponsored-projects/{id}/sponsorship-types payload name description is_active order scope REALM_URL/sponsored-projects/write GET /api/v1/sponsored-projects/{id}/sponsorship-types scope REALM_URL/sponsored-projects/read GET /api/v1/sponsored-projects/{id}/sponsorship-types/{id} scope REALM_URL/sponsored-projects/read DELETE /api/v1/sponsored-projects/{id}/sponsorship-types/{id} scope REALM_URL/sponsored-projects/write PUT /api/v1/sponsored-projects/{id}/sponsorship-types/{id} payload name description is_active order scope REALM_URL/sponsored-projects/write PUT /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies/{id} payload order (optional) scope REALM_URL/sponsored-projects/write DELETE /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies/{id} scope REALM_URL/sponsored-projects/write GET /api/v1/sponsored-projects/{id}/sponsorship-types/{id}/supporting-companies scope REALM_URL/sponsored-projects/read Change-Id: I9c0b1bb457a1c583afd284f56f2aced5deceaa02 Signed-off-by: smarcet --- .env.example | 1 - Libs/ModelSerializers/AbstractSerializer.php | 17 +- .../Many2OneExpandSerializer.php | 37 ++ .../One2ManyExpandSerializer.php | 78 ++++ ...tSponsorshipTypeValidationRulesFactory.php | 44 ++ ...SponsoredProjectValidationRulesFactory.php | 41 ++ .../OAuth2SponsoredProjectApiController.php | 378 ++++++++++++++++++ .../OAuth2SponsoredProjectsApiController.php | 23 ++ .../Summit/Traits/ParametrizedAddEntity.php | 90 +++++ .../Traits/ParametrizedDeleteEntity.php | 54 +++ .../Summit/Traits/ParametrizedGetEntity.php | 67 ++++ .../Traits/ParametrizedUpdateEntity.php | 96 +++++ app/Http/Routes/public.php | 6 + app/Http/routes.php | 33 ++ .../{ => Companies}/CompanySerializer.php | 0 .../ProjectSponsorshipTypeSerializer.php | 46 +++ .../Companies/SponsoredProjectSerializer.php | 40 ++ .../Companies/SupportingCompanySerializer.php | 48 +++ app/ModelSerializers/SerializerRegistry.php | 7 +- .../Main/{ => Companies}/Company.php | 2 - .../Main/Companies/ProjectSponsorshipType.php | 242 +++++++++++ .../Main/Companies/SponsoredProject.php | 192 +++++++++ .../Main/Companies/SupportingCompany.php | 114 ++++++ .../ProjectSponsorshipTypeFactory.php | 39 ++ .../Factories/SponsoredProjectFactory.php | 49 +++ .../IProjectSponsorshipTypeRepository.php | 22 + .../ISponsoredProjectRepository.php | 23 ++ .../ISupportingCompanyRepository.php | 22 + ...ctrineProjectSponsorshipTypeRepository.php | 70 ++++ .../DoctrineSponsoredProjectRepository.php | 61 +++ .../DoctrineSupportingCompanyRepository.php | 73 ++++ app/Repositories/RepositoriesProvider.php | 28 +- app/Security/SponsoredProjectScope.php | 23 ++ .../Model/ISponsoredProjectService.php | 94 +++++ .../Model/Imp/SponsoredProjectService.php | 262 ++++++++++++ app/Services/ModelServicesProvider.php | 8 + .../Utils/DoctrineTransactionService.php | 1 - .../model/Version20201119155826.php | 108 +++++ .../model/Version20201120143925.php | 45 +++ database/seeds/ApiEndpointsSeeder.php | 148 +++++++ database/seeds/ApiScopesSeeder.php | 33 ++ database/seeds/ApiSeeder.php | 10 + tests/OAuth2SponsoredProjectsApiTest.php | 221 ++++++++++ tests/ProtectedApiTest.php | 5 + tests/SponsoredProjectModelTest.php | 73 ++++ 45 files changed, 3067 insertions(+), 7 deletions(-) create mode 100644 Libs/ModelSerializers/Many2OneExpandSerializer.php create mode 100644 Libs/ModelSerializers/One2ManyExpandSerializer.php create mode 100644 app/Http/Controllers/Apis/Protected/Main/Factories/ProjectSponsorshipTypeValidationRulesFactory.php create mode 100644 app/Http/Controllers/Apis/Protected/Main/Factories/SponsoredProjectValidationRulesFactory.php create mode 100644 app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectApiController.php create mode 100644 app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectsApiController.php create mode 100644 app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedAddEntity.php create mode 100644 app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedDeleteEntity.php create mode 100644 app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedGetEntity.php create mode 100644 app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedUpdateEntity.php rename app/ModelSerializers/{ => Companies}/CompanySerializer.php (100%) create mode 100644 app/ModelSerializers/Companies/ProjectSponsorshipTypeSerializer.php create mode 100644 app/ModelSerializers/Companies/SponsoredProjectSerializer.php create mode 100644 app/ModelSerializers/Companies/SupportingCompanySerializer.php rename app/Models/Foundation/Main/{ => Companies}/Company.php (99%) create mode 100644 app/Models/Foundation/Main/Companies/ProjectSponsorshipType.php create mode 100644 app/Models/Foundation/Main/Companies/SponsoredProject.php create mode 100644 app/Models/Foundation/Main/Companies/SupportingCompany.php create mode 100644 app/Models/Foundation/Main/Factories/ProjectSponsorshipTypeFactory.php create mode 100644 app/Models/Foundation/Main/Factories/SponsoredProjectFactory.php create mode 100644 app/Models/Foundation/Main/Repositories/IProjectSponsorshipTypeRepository.php create mode 100644 app/Models/Foundation/Main/Repositories/ISponsoredProjectRepository.php create mode 100644 app/Models/Foundation/Main/Repositories/ISupportingCompanyRepository.php create mode 100644 app/Repositories/Main/DoctrineProjectSponsorshipTypeRepository.php create mode 100644 app/Repositories/Main/DoctrineSponsoredProjectRepository.php create mode 100644 app/Repositories/Main/DoctrineSupportingCompanyRepository.php create mode 100644 app/Security/SponsoredProjectScope.php create mode 100644 app/Services/Model/ISponsoredProjectService.php create mode 100644 app/Services/Model/Imp/SponsoredProjectService.php create mode 100644 database/migrations/model/Version20201119155826.php create mode 100644 database/migrations/model/Version20201120143925.php create mode 100644 tests/OAuth2SponsoredProjectsApiTest.php create mode 100644 tests/SponsoredProjectModelTest.php diff --git a/.env.example b/.env.example index 726f75fb..b42730f6 100644 --- a/.env.example +++ b/.env.example @@ -73,7 +73,6 @@ SCP_REMOTE_BASE_PATH=/tmp GOOGLE_GEO_CODING_API_KEY= # swift configuration -CLOUD_STORAGE_BASE_URL= CLOUD_STORAGE_AUTH_URL= CLOUD_STORAGE_USERNAME= CLOUD_STORAGE_APIKEY= diff --git a/Libs/ModelSerializers/AbstractSerializer.php b/Libs/ModelSerializers/AbstractSerializer.php index 6e68d77a..5efc49f9 100644 --- a/Libs/ModelSerializers/AbstractSerializer.php +++ b/Libs/ModelSerializers/AbstractSerializer.php @@ -16,6 +16,8 @@ use Illuminate\Support\Facades\Log; use libs\utils\JsonUtils; use models\oauth2\IResourceServerContext; use models\utils\IEntity; +use ModelSerializers\SerializerRegistry; + /** * Class AbstractSerializer * @package Libs\ModelSerializers @@ -157,6 +159,8 @@ abstract class AbstractSerializer implements IModelSerializer return sprintf("%s:%s", $field, $type); } + protected $expand_mappings = []; + /** * @param null $expand * @param array $fields @@ -254,6 +258,17 @@ abstract class AbstractSerializer implements IModelSerializer $values = $new_values; } + // expand logic + if (!empty($expand)) { + $exp_expand = explode(',', $expand); + foreach ($exp_expand as $relation) { + $relation = trim($relation); + if(isset($this->expand_mappings[$relation])){ + $values = $this->expand_mappings[$relation]->serialize($values, $expand); + } + } + } + return $values; } @@ -262,7 +277,7 @@ abstract class AbstractSerializer implements IModelSerializer * @param string $prefix * @return string */ - protected static function filterExpandByPrefix($expand_str, $prefix){ + public static function filterExpandByPrefix($expand_str, $prefix){ $expand_to = explode(',', $expand_str); $filtered_expand = array_filter($expand_to, function($element) use($prefix){ diff --git a/Libs/ModelSerializers/Many2OneExpandSerializer.php b/Libs/ModelSerializers/Many2OneExpandSerializer.php new file mode 100644 index 00000000..636239c7 --- /dev/null +++ b/Libs/ModelSerializers/Many2OneExpandSerializer.php @@ -0,0 +1,37 @@ +unsetOriginalAttribute($values); + $callback = $this->getRelationFn; + $res = []; + foreach ($callback($this) as $item){ + $res[] = SerializerRegistry::getInstance()->getSerializer($item)->serialize(AbstractSerializer::filterExpandByPrefix($expand, $this->attribute_name)); + } + $values[$this->attribute_name] = $res; + return $values; + } +} \ No newline at end of file diff --git a/Libs/ModelSerializers/One2ManyExpandSerializer.php b/Libs/ModelSerializers/One2ManyExpandSerializer.php new file mode 100644 index 00000000..6feceffc --- /dev/null +++ b/Libs/ModelSerializers/One2ManyExpandSerializer.php @@ -0,0 +1,78 @@ +attribute_name = $attribute_name; + $this->getRelationFn = $getRelationFn; + $this->original_attribute = $original_attribute; + } + + /** + * @param array $values + * @return array + */ + protected function unsetOriginalAttribute(array $values) + { + if (isset($values[$this->original_attribute])) + unset($values[$this->original_attribute]); + return $values; + } + + /** + * @param array $values + * @param string $expand + * @return array + */ + public function serialize(array $values, string $expand): array + { + $values = $this->unsetOriginalAttribute($values); + $callback = $this->getRelationFn; + $values[$this->attribute_name] = SerializerRegistry::getInstance()->getSerializer($callback($this))->serialize(AbstractSerializer::filterExpandByPrefix($expand, $this->attribute_name)); + return $values; + } + +} \ No newline at end of file diff --git a/app/Http/Controllers/Apis/Protected/Main/Factories/ProjectSponsorshipTypeValidationRulesFactory.php b/app/Http/Controllers/Apis/Protected/Main/Factories/ProjectSponsorshipTypeValidationRulesFactory.php new file mode 100644 index 00000000..ca6546cd --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Main/Factories/ProjectSponsorshipTypeValidationRulesFactory.php @@ -0,0 +1,44 @@ + 'sometimes|string', + 'description' => 'sometimes|string', + 'is_active' => 'sometimes|boolean', + 'order' => 'sometimes|integer|min:1', + ]; + } + return [ + 'name' => 'required|string', + 'description' => 'sometimes|string', + 'is_active' => 'sometimes|boolean', + 'order' => 'sometimes|integer|min:1', + ]; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Apis/Protected/Main/Factories/SponsoredProjectValidationRulesFactory.php b/app/Http/Controllers/Apis/Protected/Main/Factories/SponsoredProjectValidationRulesFactory.php new file mode 100644 index 00000000..8e28b4b6 --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Main/Factories/SponsoredProjectValidationRulesFactory.php @@ -0,0 +1,41 @@ + 'sometimes|string', + 'description' => 'sometimes|string', + 'is_active' => 'sometimes|boolean', + ]; + } + return [ + 'name' => 'required|string', + 'description' => 'sometimes|string', + 'is_active' => 'sometimes|boolean', + ]; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectApiController.php new file mode 100644 index 00000000..d997361e --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectApiController.php @@ -0,0 +1,378 @@ +repository = $company_repository; + $this->project_sponsorship_type_repository = $project_sponsorship_type_repository; + $this->supporting_company_repository = $supporting_company_repository; + $this->service = $service; + } + + /** + * @inheritDoc + */ + function getAddValidationRules(array $payload): array + { + return SponsoredProjectValidationRulesFactory::build($payload); + } + + /** + * @inheritDoc + */ + protected function addEntity(array $payload): IEntity + { + return $this->service->add(HTMLCleaner::cleanData($payload, ['description'])); + } + + /** + * @inheritDoc + */ + protected function deleteEntity(int $id): void + { + $this->service->delete($id); + } + + /** + * @inheritDoc + */ + protected function getEntity(int $id): IEntity + { + return $this->repository->getById($id); + } + + /** + * @inheritDoc + */ + function getUpdateValidationRules(array $payload): array + { + return SponsoredProjectValidationRulesFactory::build($payload, true); + } + + /** + * @inheritDoc + */ + protected function updateEntity($id, array $payload): IEntity + { + return $this->service->update($id, HTMLCleaner::cleanData($payload, ['description'])); + } + + /** + * @return mixed + */ + public function getAll() + { + return $this->_getAll( + function () { + return [ + 'name' => ['=@', '=='], + 'slug' => ['=@', '=='], + 'is_active' => ['=='] + ]; + }, + function () { + return [ + 'is_active' => 'sometimes|boolean', + 'name' => 'sometimes|string', + 'slug' => 'sometimes|string', + ]; + }, + function () { + return [ + 'name', + 'id', + ]; + }, + function ($filter) { + return $filter; + }, + function () { + return SerializerRegistry::SerializerType_Public; + } + ); + } + + // sponsorship types + + /** + * @param $id string|int + */ + public function getAllSponsorshipTypes($id) + { + return $this->_getAll( + function () { + return [ + 'name' => ['=@', '=='], + 'slug' => ['=@', '=='], + 'is_active' => ['=='] + ]; + }, + function () { + return [ + 'is_active' => 'sometimes|boolean', + 'name' => 'sometimes|string', + 'slug' => 'sometimes|string', + ]; + }, + function () { + return [ + 'name', + 'id', + ]; + }, + function ($filter) use($id) { + if($filter instanceof Filter){ + if(is_integer($id)) + $filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_id', intval($id))); + else + $filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_slug', $id)); + } + return $filter; + }, + function () { + return SerializerRegistry::SerializerType_Public; + }, + null, + null, + function ($page, $per_page, $filter, $order, $applyExtraFilters) { + return $this->project_sponsorship_type_repository->getAllByPage + ( + new PagingInfo($page, $per_page), + call_user_func($applyExtraFilters, $filter), + $order + ); + } + ); + } + + /** + * @param $id + * @param $sponsorship_type_id + */ + public function getSponsorshipType($id, $sponsorship_type_id){ + $this->_get($sponsorship_type_id, function($id){ + return $this->project_sponsorship_type_repository->getById(intval($id)); + }); + } + /** + * @param $id + * @return mixed + */ + public function addSponsorshipType($id) + { + $args = [intval($id)]; + return $this->_add( + function ($payload) { + return ProjectSponsorshipTypeValidationRulesFactory::build($payload); + }, + function ($payload, $id){ + return $this->service->addProjectSponsorshipType($id, HTMLCleaner::cleanData($payload, ['description'])); + }, + ...$args + ); + } + + /** + * @param $id + * @param $sponsorship_type_id + * @return mixed + */ + public function updateSponsorshipType($id, $sponsorship_type_id){ + $args = [ intval($id) ]; + return $this->_update( + $sponsorship_type_id, + function($payload){ + return ProjectSponsorshipTypeValidationRulesFactory::build($payload, true); + }, + function($sponsorship_type_id, $payload, $project_id){ + return $this->service->updateProjectSponsorshipType($project_id, $sponsorship_type_id, HTMLCleaner::cleanData($payload, ['description'])); + }, + ...$args + ); + } + + /** + * @param $id + * @param $sponsorship_type_id + * @return mixed + */ + public function deleteSponsorshipType($id, $sponsorship_type_id){ + $args = [ intval($id) ]; + + return $this->_delete( + $sponsorship_type_id, + function ($sponsorship_type_id, $project_id){ + $this->service->deleteProjectSponsorshipType($project_id, $sponsorship_type_id); + }, + ...$args + ); + } + + // supporting companies + + public function getSupportingCompanies($id, $sponsorship_type_id){ + return $this->_getAll( + function () { + return [ + 'name' => ['=@', '=='], + ]; + }, + function () { + return [ + 'name' => 'sometimes|string', + ]; + }, + function () { + return [ + 'name', + 'order', + ]; + }, + function ($filter) use($id, $sponsorship_type_id) { + if($filter instanceof Filter){ + if(is_integer($id)) + $filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_id', intval($id))); + else + $filter->addFilterCondition(FilterElement::makeEqual('sponsored_project_slug', $id)); + + if(is_integer($sponsorship_type_id)) + $filter->addFilterCondition(FilterElement::makeEqual('sponsorship_type_id', intval($sponsorship_type_id))); + else + $filter->addFilterCondition(FilterElement::makeEqual('sponsorship_type_slug', $sponsorship_type_id)); + } + return $filter; + }, + function () { + return SerializerRegistry::SerializerType_Public; + }, + null, + null, + function ($page, $per_page, $filter, $order, $applyExtraFilters) { + return $this->supporting_company_repository->getAllByPage + ( + new PagingInfo($page, $per_page), + call_user_func($applyExtraFilters, $filter), + $order + ); + } + ); + } + + /** + * @param $id + * @param $sponsorship_type_id + * @param $company_id + * @return mixed + */ + public function addSupportingCompanies($id, $sponsorship_type_id, $company_id){ + return $this->_update($company_id, + function($payload){ + return [ + 'order' => 'sometimes|integer|min:1', + ]; + }, + function($id, $payload, $project_id, $sponsorship_type_id){ + return $this->service->addCompanyToProjectSponsorshipType + ( + $project_id, + $sponsorship_type_id, + $id, + $payload + ); + }, + $id, + $sponsorship_type_id + ); + } + + /** + * @param $id + * @param $sponsorship_type_id + * @param $company_id + * @return mixed + */ + public function deleteSupportingCompanies($id, $sponsorship_type_id, $company_id){ + return $this->_delete($company_id, function($id, $project_id, $sponsorship_type_id){ + $this->service->removeCompanyToProjectSponsorshipType($id, $sponsorship_type_id, $id); + }, $id, $sponsorship_type_id); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectsApiController.php b/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectsApiController.php new file mode 100644 index 00000000..5f9414dd --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Main/OAuth2SponsoredProjectsApiController.php @@ -0,0 +1,23 @@ +error400(); + $data = Input::json(); + $payload = $data->all(); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($payload, $getAddValidationRulesFn($payload)); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $fields = Request::input('fields', ''); + $relations = Request::input('relations', ''); + + $relations = !empty($relations) ? explode(',', $relations) : []; + $fields = !empty($fields) ? explode(',', $fields) : []; + + $entity = $addEntityFn($payload, ...$args); + + return $this->created(SerializerRegistry::getInstance()->getSerializer($entity)->serialize + ( + Request::input('expand', ''), + $fields, + $relations + )); + } + catch (ValidationException $ex) { + Log::warning($ex); + return $this->error412(array($ex->getMessage())); + } + catch(EntityNotFoundException $ex) + { + Log::warning($ex); + return $this->error404(array('message'=> $ex->getMessage())); + } + catch (\HTTP401UnauthorizedException $ex) { + Log::warning($ex); + return $this->error401(); + } + catch (HTTP403ForbiddenException $ex) { + Log::warning($ex); + return $this->error403(); + } + 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/Traits/ParametrizedDeleteEntity.php b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedDeleteEntity.php new file mode 100644 index 00000000..7b837278 --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedDeleteEntity.php @@ -0,0 +1,54 @@ +deleted(); + } catch (ValidationException $ex) { + Log::warning($ex); + return $this->error412(array($ex->getMessage())); + } catch (EntityNotFoundException $ex) { + Log::warning($ex); + return $this->error404(array('message' => $ex->getMessage())); + } catch (\HTTP401UnauthorizedException $ex) { + Log::warning($ex); + return $this->error401(); + } catch (HTTP403ForbiddenException $ex) { + Log::warning($ex); + return $this->error403(); + } 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/Traits/ParametrizedGetEntity.php b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedGetEntity.php new file mode 100644 index 00000000..fede4cd4 --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedGetEntity.php @@ -0,0 +1,67 @@ +ok(SerializerRegistry::getInstance()->getSerializer($entity)->serialize( + Request::input('expand', ''), + $fields, + $relations + )); + + } catch (ValidationException $ex) { + Log::warning($ex); + return $this->error412(array($ex->getMessage())); + } catch (EntityNotFoundException $ex) { + Log::warning($ex); + return $this->error404(array('message' => $ex->getMessage())); + } catch (\HTTP401UnauthorizedException $ex) { + Log::warning($ex); + return $this->error401(); + } catch (HTTP403ForbiddenException $ex) { + Log::warning($ex); + return $this->error403(); + } 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/Traits/ParametrizedUpdateEntity.php b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedUpdateEntity.php new file mode 100644 index 00000000..bc1b082b --- /dev/null +++ b/app/Http/Controllers/Apis/Protected/Summit/Traits/ParametrizedUpdateEntity.php @@ -0,0 +1,96 @@ +error400(); + $data = Input::json(); + $payload = $data->all(); + + // Creates a Validator instance and validates the data. + $validation = Validator::make($payload, $getUpdateValidationRulesFn($payload)); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $entity = $updateEntityFn($id, $payload, ...$args); + + $fields = Request::input('fields', ''); + $relations = Request::input('relations', ''); + + $relations = !empty($relations) ? explode(',', $relations) : []; + $fields = !empty($fields) ? explode(',', $fields) : []; + + return $this->updated(SerializerRegistry::getInstance()->getSerializer($entity)->serialize + ( + Request::input('expand', ''), + $fields, + $relations + )); + } + catch (ValidationException $ex) { + Log::warning($ex); + return $this->error412(array($ex->getMessage())); + } + catch(EntityNotFoundException $ex) + { + Log::warning($ex); + return $this->error404(array('message'=> $ex->getMessage())); + } + catch (\HTTP401UnauthorizedException $ex) { + Log::warning($ex); + return $this->error401(); + } + catch (HTTP403ForbiddenException $ex) { + Log::warning($ex); + return $this->error403(); + } + catch (Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } +} \ No newline at end of file diff --git a/app/Http/Routes/public.php b/app/Http/Routes/public.php index df51f345..e3ad9c9a 100644 --- a/app/Http/Routes/public.php +++ b/app/Http/Routes/public.php @@ -28,6 +28,12 @@ Route::group([ ] ], function () { + Route::group(['prefix' => 'sponsored-projects'], function(){ + Route::group(['prefix'=>'{id}'], function(){ + Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@get']); + }); + }); + // files Route::group(['prefix' => 'files'], function () { Route::post('upload','OAuth2ChunkedFilesApiController@uploadFile' ); diff --git a/app/Http/routes.php b/app/Http/routes.php index 337e08d5..4f1f5131 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -87,6 +87,39 @@ Route::group([ }); }); + // sponsored projects + + Route::group(['prefix'=>'sponsored-projects'], function(){ + Route::get('', 'OAuth2SponsoredProjectApiController@getAll'); + Route::post('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@add']); + + Route::group(['prefix'=>'{id}'], function(){ + + Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@get']); + Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@update']); + Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@delete']); + + Route::group(['prefix'=>'sponsorship-types'], function(){ + Route::get('', 'OAuth2SponsoredProjectApiController@getAllSponsorshipTypes'); + Route::post('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@addSponsorshipType']); + Route::group(['prefix'=>'{sponsorship_type_id}'], function(){ + + Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@getSponsorshipType']); + Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@updateSponsorshipType']); + Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@deleteSponsorshipType']); + + Route::group(['prefix'=>'supporting-companies'], function(){ + Route::get('', [ 'uses' => 'OAuth2SponsoredProjectApiController@getSupportingCompanies']); + Route::group(['prefix'=>'{company_id}'], function(){ + Route::put('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@addSupportingCompanies']); + Route::delete('', [ 'middleware' => 'auth.user', 'uses' => 'OAuth2SponsoredProjectApiController@deleteSupportingCompanies']); + }); + }); + }); + }); + }); + }); + // organizations Route::group(['prefix'=>'organizations'], function(){ Route::get('', 'OAuth2OrganizationsApiController@getAll'); diff --git a/app/ModelSerializers/CompanySerializer.php b/app/ModelSerializers/Companies/CompanySerializer.php similarity index 100% rename from app/ModelSerializers/CompanySerializer.php rename to app/ModelSerializers/Companies/CompanySerializer.php diff --git a/app/ModelSerializers/Companies/ProjectSponsorshipTypeSerializer.php b/app/ModelSerializers/Companies/ProjectSponsorshipTypeSerializer.php new file mode 100644 index 00000000..84b8868d --- /dev/null +++ b/app/ModelSerializers/Companies/ProjectSponsorshipTypeSerializer.php @@ -0,0 +1,46 @@ + 'name:json_string', + 'Description' => 'description:json_string', + 'Active' => 'active:json_boolean', + 'Order' => 'order:json_int', + 'SponsoredProjectId' => 'sponsored_project_id:json_int', + 'SupportingCompaniesIds' => 'supporting_companies', + ]; + + public function __construct($object, IResourceServerContext $resource_server_context) + { + parent::__construct($object, $resource_server_context); + $this->expand_mappings = [ + 'sponsored_project' => new One2ManyExpandSerializer('sponsored_project', function () use ($object) { + return $object->getSponsoredProject(); + }, "sponsored_project_id"), + 'supporting_companies' => new Many2OneExpandSerializer('supporting_companies', function () use ($object) { + return $object->getSupportingCompanies(); + }, "supporting_companies"), + ]; + } +} \ No newline at end of file diff --git a/app/ModelSerializers/Companies/SponsoredProjectSerializer.php b/app/ModelSerializers/Companies/SponsoredProjectSerializer.php new file mode 100644 index 00000000..0d141436 --- /dev/null +++ b/app/ModelSerializers/Companies/SponsoredProjectSerializer.php @@ -0,0 +1,40 @@ + 'name:json_string', + 'Description' => 'description:json_string', + 'Slug' => 'slug:json_string', + 'Active' => 'is_active:json_boolean', + 'SponsorshipTypesIds' => 'sponsorship_types', + ]; + + public function __construct($object, IResourceServerContext $resource_server_context) + { + parent::__construct($object, $resource_server_context); + + $this->expand_mappings = [ + 'sponsorship_types' => new Many2OneExpandSerializer('sponsorship_types', function () use ($object) { + return $object->getSponsorshipTypes(); + }, "sponsorship_types"), + ]; + } +} \ No newline at end of file diff --git a/app/ModelSerializers/Companies/SupportingCompanySerializer.php b/app/ModelSerializers/Companies/SupportingCompanySerializer.php new file mode 100644 index 00000000..db64d3b2 --- /dev/null +++ b/app/ModelSerializers/Companies/SupportingCompanySerializer.php @@ -0,0 +1,48 @@ + 'company_id:json_int', + 'SponsorshipId' => 'sponsorship_type_id:json_int', + 'Order' => 'order:json_int', + ]; + + /*** + * SupportingCompanySerializer constructor. + * @param $object + * @param IResourceServerContext $resource_server_context + */ + public function __construct($object, IResourceServerContext $resource_server_context) + { + parent::__construct($object, $resource_server_context); + + $this->expand_mappings = [ + 'company' => new One2ManyExpandSerializer('company', function () use ($object) { + return $object->getCompany(); + }, "company_id"), + 'sponsorship_type' => new One2ManyExpandSerializer('sponsorship_type', function () use ($object) { + return $object->getSponsorshipType(); + }, "sponsorship_type_id"), + ]; + } + +} \ No newline at end of file diff --git a/app/ModelSerializers/SerializerRegistry.php b/app/ModelSerializers/SerializerRegistry.php index 4c17f206..4a56b2f6 100644 --- a/app/ModelSerializers/SerializerRegistry.php +++ b/app/ModelSerializers/SerializerRegistry.php @@ -206,7 +206,12 @@ final class SerializerRegistry self::SerializerType_Public => PresentationMediaUploadSerializer::class, self::SerializerType_Private => AdminPresentationMediaUploadSerializer::class ]; - $this->registry['Company'] = CompanySerializer::class; + // Company + + $this->registry['Company'] = CompanySerializer::class; + $this->registry['SponsoredProject'] = SponsoredProjectSerializer::class; + $this->registry['ProjectSponsorshipType'] = ProjectSponsorshipTypeSerializer::class; + $this->registry['SupportingCompany'] = SupportingCompanySerializer::class; $this->registry['PresentationSpeaker'] = [ diff --git a/app/Models/Foundation/Main/Company.php b/app/Models/Foundation/Main/Companies/Company.php similarity index 99% rename from app/Models/Foundation/Main/Company.php rename to app/Models/Foundation/Main/Companies/Company.php index 3900cd06..f08e3caa 100644 --- a/app/Models/Foundation/Main/Company.php +++ b/app/Models/Foundation/Main/Companies/Company.php @@ -11,14 +11,12 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use App\Models\Foundation\Main\ICompanyMemberLevel; use Doctrine\Common\Collections\ArrayCollection; use Illuminate\Support\Facades\Log; use models\exceptions\ValidationException; use models\utils\SilverstripeBaseModel; use Doctrine\ORM\Mapping AS ORM; - /** * @ORM\Entity(repositoryClass="repositories\main\DoctrineCompanyRepository") * @ORM\Table(name="Company") diff --git a/app/Models/Foundation/Main/Companies/ProjectSponsorshipType.php b/app/Models/Foundation/Main/Companies/ProjectSponsorshipType.php new file mode 100644 index 00000000..7a79f96c --- /dev/null +++ b/app/Models/Foundation/Main/Companies/ProjectSponsorshipType.php @@ -0,0 +1,242 @@ +order = $order; + } + + /** + * @inheritDoc + */ + public function getOrder() + { + return $this->order; + } + + public function __construct() + { + parent::__construct(); + $this->supporting_companies = new ArrayCollection(); + $this->is_active = false; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @param string $name + */ + public function setName(string $name): void + { + $this->name = $name; + $slugify = new Slugify(); + $this->slug = $slugify->slugify($name); + } + + /** + * @return string + */ + public function getSlug(): string + { + return $this->slug; + } + + /** + * @return string + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @param string $description + */ + public function setDescription(string $description): void + { + $this->description = $description; + } + + /** + * @return bool + */ + public function isActive(): bool + { + return $this->is_active; + } + + /** + * @param bool $is_active + */ + public function setIsActive(bool $is_active): void + { + $this->is_active = $is_active; + } + + /** + * @return SponsoredProject + */ + public function getSponsoredProject(): ?SponsoredProject + { + return $this->sponsored_project; + } + + /** + * @param SponsoredProject $sponsored_project + */ + public function setSponsoredProject(SponsoredProject $sponsored_project): void + { + $this->sponsored_project = $sponsored_project; + } + + public function clearSponsoredProject(){ + $this->sponsored_project = null; + } + + use OrderableChilds; + + /** + * @param SupportingCompany $value + * @param int $new_order + * @throws ValidationException + */ + public function recalculateSupportingCompanyOrder(SupportingCompany $value, $new_order){ + self::recalculateOrderForSelectable($this->supporting_companies, $value, $new_order); + } + + /** + * @param Company $company + * @return SupportingCompany|null + */ + public function addSupportingCompany(Company $company):?SupportingCompany { + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('company', $company)); + $supporting_company = $this->supporting_companies->matching($criteria)->first(); + if($supporting_company) return $supporting_company; + $supporting_company = new SupportingCompany(); + $supporting_company->setCompany($company); + $supporting_company->setSponsorshipType($this); + $this->supporting_companies->add($supporting_company); + $supporting_company->setOrder($this->supporting_companies->count()); + return $supporting_company; + } + + /** + * @param Company $company + */ + public function removeSupportingCompany(Company $company){ + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('company', $company)); + $supporting_company = $this->supporting_companies->matching($criteria)->first(); + if(!$supporting_company) return; + $this->supporting_companies->removeElement($supporting_company); + } + + use One2ManyPropertyTrait; + + protected $getIdMappings = [ + 'getSponsoredProjectId' => 'sponsored_project', + ]; + + protected $hasPropertyMappings = [ + 'hasSponsoredProject' => 'sponsored_project', + ]; + + /** + * @return array + */ + public function getSupportingCompaniesIds():array { + $res = []; + foreach ($this->supporting_companies as $supporting_company){ + $res[] = $supporting_company->getCompany()->getId(); + } + return $res; + } + + public function getSupportingCompanies(){ + return $this->supporting_companies; + } + + + +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Companies/SponsoredProject.php b/app/Models/Foundation/Main/Companies/SponsoredProject.php new file mode 100644 index 00000000..16fbe099 --- /dev/null +++ b/app/Models/Foundation/Main/Companies/SponsoredProject.php @@ -0,0 +1,192 @@ +name = $name; + $slugify = new Slugify(); + $this->slug = $slugify->slugify($name); + } + + /** + * @return string|null + */ + public function getDescription(): ?string + { + return $this->description; + } + + /** + * @param string $description + */ + public function setDescription(string $description): void + { + $this->description = $description; + } + + /** + * @return bool + */ + public function isActive(): bool + { + return $this->is_active; + } + + /** + * @param bool $is_active + */ + public function setIsActive(bool $is_active): void + { + $this->is_active = $is_active; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @return string + */ + public function getSlug(): string + { + return $this->slug; + } + + use OrderableChilds; + + /** + * @ORM\OneToMany(targetEntity="ProjectSponsorshipType", mappedBy="sponsored_project", cascade={"persist"}, orphanRemoval=true) + * @var ProjectSponsorshipType[] + */ + private $sponsorship_types; + + + /** + * SponsoredProject constructor. + */ + public function __construct() + { + parent::__construct(); + $this->sponsorship_types = new ArrayCollection; + $this->is_active = false; + } + + /** + * @param ProjectSponsorshipType $value + * @param int $new_order + * @throws ValidationException + */ + public function recalculateProjectSponsorshipTypeOrder(ProjectSponsorshipType $value, $new_order){ + self::recalculateOrderForSelectable($this->sponsorship_types, $value, $new_order); + } + + /** + * @return ProjectSponsorshipType[] + */ + public function getSponsorshipTypes(): array + { + return $this->sponsorship_types; + } + + /** + * @return array|int[] + */ + public function getSponsorshipTypesIds(): array { + $res = []; + foreach($this->sponsorship_types as $item){ + $res[] = $item->getId(); + } + return $res; + } + + /** + * @param string $name + * @return ProjectSponsorshipType|null + */ + public function getSponsorshipTypeByName(string $name):?ProjectSponsorshipType{ + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('name', trim($name))); + $sponsorshipType = $this->sponsorship_types->matching($criteria)->first(); + return $sponsorshipType === false ? null : $sponsorshipType; + } + + /** + * @param int $id + * @return ProjectSponsorshipType|null + */ + public function getSponsorshipTypeById(int $id):?ProjectSponsorshipType{ + $criteria = Criteria::create(); + $criteria->where(Criteria::expr()->eq('id', $id)); + $sponsorshipType = $this->sponsorship_types->matching($criteria)->first(); + return $sponsorshipType === false ? null : $sponsorshipType; + } + + public function addSponsorshipType(ProjectSponsorshipType $sponsorshipType){ + if($this->sponsorship_types->contains($sponsorshipType)) return; + $this->sponsorship_types->add($sponsorshipType); + $sponsorshipType->setSponsoredProject($this); + $sponsorshipType->setOrder($this->sponsorship_types->count()); + } + + public function removeSponsorshipType(ProjectSponsorshipType $sponsorshipType){ + if(!$this->sponsorship_types->contains($sponsorshipType)) return; + $this->sponsorship_types->removeElement($sponsorshipType); + $sponsorshipType->clearSponsoredProject(); + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Companies/SupportingCompany.php b/app/Models/Foundation/Main/Companies/SupportingCompany.php new file mode 100644 index 00000000..27f09465 --- /dev/null +++ b/app/Models/Foundation/Main/Companies/SupportingCompany.php @@ -0,0 +1,114 @@ + 'company', + 'getSponsorshipId' => 'sponsorship_type', + ]; + + protected $hasPropertyMappings = [ + 'hasCompany' => 'company', + 'hasSponsorshipType' => 'sponsorship_type', + ]; + + /** + * @ORM\ManyToOne(targetEntity="Company", fetch="EXTRA_LAZY") + * @ORM\JoinColumn(name="CompanyID", referencedColumnName="ID", onDelete="SET NULL") + * @var Company + */ + private $company; + + /** + * @ORM\ManyToOne(targetEntity="ProjectSponsorshipType", fetch="EXTRA_LAZY") + * @ORM\JoinColumn(name="ProjectSponsorshipTypeID", referencedColumnName="ID", onDelete="SET NULL") + * @var ProjectSponsorshipType + */ + private $sponsorship_type; + + /** + * @ORM\Column(name="`Order`", type="integer") + * @var int + */ + private $order; + + /** + * @inheritDoc + */ + public function setOrder($order) + { + $this->order = $order; + } + + /** + * @inheritDoc + */ + public function getOrder() + { + return $this->order; + } + + /** + * @return Company + */ + public function getCompany(): Company + { + return $this->company; + } + + /** + * @param Company $company + */ + public function setCompany(Company $company): void + { + $this->company = $company; + } + + /** + * @return ProjectSponsorshipType + */ + public function getSponsorshipType(): ProjectSponsorshipType + { + return $this->sponsorship_type; + } + + /** + * @param ProjectSponsorshipType $sponsorship_type + */ + public function setSponsorshipType(ProjectSponsorshipType $sponsorship_type): void + { + $this->sponsorship_type = $sponsorship_type; + } + + public function clearCompany(){ + $this->company = null; + } + + public function clearSponsorshipType(){ + $this->sponsorship_type = null; + } + +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Factories/ProjectSponsorshipTypeFactory.php b/app/Models/Foundation/Main/Factories/ProjectSponsorshipTypeFactory.php new file mode 100644 index 00000000..4f33bf71 --- /dev/null +++ b/app/Models/Foundation/Main/Factories/ProjectSponsorshipTypeFactory.php @@ -0,0 +1,39 @@ +setName(trim($payload['name'])); + + if(isset($payload['description'])) + $projectSponsorshipType->setDescription(trim($payload['description'])); + + if(isset($payload['is_active'])) + $projectSponsorshipType->setIsActive(boolval($payload['is_active'])); + + return $projectSponsorshipType; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Factories/SponsoredProjectFactory.php b/app/Models/Foundation/Main/Factories/SponsoredProjectFactory.php new file mode 100644 index 00000000..f5cd2ad7 --- /dev/null +++ b/app/Models/Foundation/Main/Factories/SponsoredProjectFactory.php @@ -0,0 +1,49 @@ +setName(trim($payload['name'])); + + if(isset($payload['description'])) + $sponsoredProject->setDescription(trim($payload['description'])); + + if(isset($payload['is_active'])) + $sponsoredProject->setIsActive(boolval($payload['is_active'])); + + return $sponsoredProject; + } +} \ No newline at end of file diff --git a/app/Models/Foundation/Main/Repositories/IProjectSponsorshipTypeRepository.php b/app/Models/Foundation/Main/Repositories/IProjectSponsorshipTypeRepository.php new file mode 100644 index 00000000..adc2be27 --- /dev/null +++ b/app/Models/Foundation/Main/Repositories/IProjectSponsorshipTypeRepository.php @@ -0,0 +1,22 @@ + 'e.name:json_string', + 'slug' => 'e.slug:json_string', + 'is_active' => 'e.is_active:json_int', + 'sponsored_project_slug' => 'sp.slug:json_string', + 'sponsored_project_id' => 'sp.id:json_int' + ]; + } + + /** + * @param QueryBuilder $query + * @return QueryBuilder + */ + protected function applyExtraJoins(QueryBuilder $query){ + $query = $query->innerJoin("e.sponsored_project", "sp"); + return $query; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'id' => 'e.id', + 'name' => 'e.name', + ]; + } + + + /** + * @inheritDoc + */ + protected function getBaseEntity() + { + return ProjectSponsorshipType::class; + } +} \ No newline at end of file diff --git a/app/Repositories/Main/DoctrineSponsoredProjectRepository.php b/app/Repositories/Main/DoctrineSponsoredProjectRepository.php new file mode 100644 index 00000000..2d495532 --- /dev/null +++ b/app/Repositories/Main/DoctrineSponsoredProjectRepository.php @@ -0,0 +1,61 @@ + 'e.name:json_string', + 'slug' => 'e.slug:json_string', + 'is_active' => 'e.is_active:json_int', + ]; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'id' => 'e.id', + 'name' => 'e.name', + ]; + } + + /** + * @inheritDoc + */ + protected function getBaseEntity() + { + return SponsoredProject::class; + } + + public function getByName(string $name): ?SponsoredProject + { + return $this->findOneBy(['name' => trim($name)]); + } +} \ No newline at end of file diff --git a/app/Repositories/Main/DoctrineSupportingCompanyRepository.php b/app/Repositories/Main/DoctrineSupportingCompanyRepository.php new file mode 100644 index 00000000..4b4a952d --- /dev/null +++ b/app/Repositories/Main/DoctrineSupportingCompanyRepository.php @@ -0,0 +1,73 @@ + 'c.name', + 'sponsorship_type_id' => 'st.id', + 'sponsorship_type_slug' => 'st.slug', + 'sponsored_project_id' => 'sp.id', + 'sponsored_project_slug' => 'sp.slug', + ]; + } + + /** + * @return array + */ + protected function getOrderMappings() + { + return [ + 'name' => 'c.name', + 'order' => 'e.order', + ]; + } + + /** + * @param QueryBuilder $query + * @return QueryBuilder + */ + protected function applyExtraJoins(QueryBuilder $query) + { + $query = $query->innerJoin("e.sponsorship_type", "st"); + $query = $query->innerJoin("e.company", "c"); + $query = $query->innerJoin("st.sponsored_project", "sp"); + return $query; + } + + /** + * @inheritDoc + */ + protected function getBaseEntity() + { + return SupportingCompany::class; + } +} \ No newline at end of file diff --git a/app/Repositories/RepositoriesProvider.php b/app/Repositories/RepositoriesProvider.php index 910a2003..62f4ae07 100644 --- a/app/Repositories/RepositoriesProvider.php +++ b/app/Repositories/RepositoriesProvider.php @@ -14,7 +14,10 @@ use App\Models\Foundation\Main\Language; use App\Models\Foundation\Main\Repositories\ILanguageRepository; +use App\Models\Foundation\Main\Repositories\IProjectSponsorshipTypeRepository; +use App\Models\Foundation\Main\Repositories\ISponsoredProjectRepository; use App\Models\Foundation\Main\Repositories\ISummitAdministratorPermissionGroupRepository; +use App\Models\Foundation\Main\Repositories\ISupportingCompanyRepository; use App\Models\Foundation\Summit\Defaults\DefaultSummitEventType; use App\Models\Foundation\Summit\DefaultTrackTagGroup; use App\Models\Foundation\Summit\EmailFlows\SummitEmailEventFlow; @@ -70,7 +73,10 @@ use models\main\File; use models\main\Group; use models\main\IOrganizationRepository; use models\main\Organization; +use models\main\ProjectSponsorshipType; +use models\main\SponsoredProject; use models\main\SummitAdministratorPermissionGroup; +use models\main\SupportingCompany; use models\summit\ISponsorUserInfoGrantRepository; use models\summit\ISummitRegistrationPromoCodeRepository; use models\summit\ISummitTicketTypeRepository; @@ -83,7 +89,6 @@ use models\summit\SpeakerOrganizationalRole; use models\summit\SpeakerRegistrationRequest; use models\summit\SpeakerSummitRegistrationPromoCode; use models\summit\Sponsor; -use models\summit\SponsorBadgeScan; use models\summit\SponsorshipType; use models\summit\SponsorUserInfoGrant; use models\summit\SummitAbstractLocation; @@ -610,5 +615,26 @@ final class RepositoriesProvider extends ServiceProvider return EntityManager::getRepository(SummitMetric::class); } ); + + App::singleton( + ISponsoredProjectRepository::class, + function(){ + return EntityManager::getRepository(SponsoredProject::class); + } + ); + + App::singleton( + IProjectSponsorshipTypeRepository::class, + function(){ + return EntityManager::getRepository(ProjectSponsorshipType::class); + } + ); + + App::singleton( + ISupportingCompanyRepository::class, + function(){ + return EntityManager::getRepository(SupportingCompany::class); + } + ); } } \ No newline at end of file diff --git a/app/Security/SponsoredProjectScope.php b/app/Security/SponsoredProjectScope.php new file mode 100644 index 00000000..07087974 --- /dev/null +++ b/app/Security/SponsoredProjectScope.php @@ -0,0 +1,23 @@ +repository = $repository; + $this->company_repository = $company_repository; + } + + /** + * @inheritDoc + */ + public function add(array $payload): SponsoredProject + { + return $this->tx_service->transaction(function() use ($payload){ + $name = trim($payload['name']); + $formerProject = $this->repository->getByName($name); + if(!is_null($formerProject)){ + throw new ValidationException(sprintf("sponsored project %s already exists.", $name)); + } + + $sponsoredProject = SponsoredProjectFactory::build($payload); + + $this->repository->add($sponsoredProject); + + return $sponsoredProject; + }); + } + + /** + * @inheritDoc + */ + public function update(int $project_id, array $payload): SponsoredProject + { + return $this->tx_service->transaction(function() use ($project_id, $payload){ + if(isset($payload['name'])) { + $name = trim($payload['name']); + $formerProject = $this->repository->getByName($name); + if (!is_null($formerProject) && $formerProject->getId() !== $project_id) { + throw new ValidationException(sprintf("sponsored project %s already exists.", $name)); + } + } + + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + SponsoredProjectFactory::populate($sponsoredProject, $payload); + + return $sponsoredProject; + }); + } + + /** + * @inheritDoc + */ + public function delete(int $project_id): void + { + $this->tx_service->transaction(function() use ($project_id){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + $this->repository->delete($sponsoredProject); + }); + } + + /** + * @inheritDoc + */ + public function addProjectSponsorshipType(int $project_id, array $payload): ProjectSponsorshipType + { + return $this->tx_service->transaction(function() use ($project_id, $payload){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + $name = trim($payload['name']); + if($sponsoredProject->getSponsorshipTypeByName($name)){ + throw new ValidationException(sprintf("sponsorship type %s already exists.", $name)); + } + + $projectSponsorshipType = ProjectSponsorshipTypeFactory::build($payload); + $sponsoredProject->addSponsorshipType($projectSponsorshipType); + + return $projectSponsorshipType; + }); + } + + /** + * @inheritDoc + */ + public function updateProjectSponsorshipType(int $project_id, int $sponsorship_id, array $payload): ProjectSponsorshipType + { + return $this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $payload){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + if(isset($payload['name'])) { + $name = trim($payload['name']); + $formerProjectSponsorshipType = $sponsoredProject->getSponsorshipTypeByName($name); + if ($formerProjectSponsorshipType && $formerProjectSponsorshipType->getId() !== $sponsorship_id) { + throw new ValidationException(sprintf("sponsorship type %s already exists.", $name)); + } + } + + $projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id); + if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType) + throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id)); + + $projectSponsorshipType = ProjectSponsorshipTypeFactory::populate($projectSponsorshipType, $payload); + + if (isset($payload['order']) && intval($payload['order']) != $projectSponsorshipType->getOrder()) { + // request to update order + $sponsoredProject->recalculateProjectSponsorshipTypeOrder($projectSponsorshipType, intval($payload['order'])); + } + + return $projectSponsorshipType; + }); + } + + /** + * @param int $project_id + * @param int $sponsorship_id + * @throws \Exception + */ + public function deleteProjectSponsorshipType(int $project_id, int $sponsorship_id): void + { + $this->tx_service->transaction(function() use ($project_id, $sponsorship_id){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + $projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id); + if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType) + throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id)); + + $sponsoredProject->removeSponsorshipType($projectSponsorshipType); + }); + } + + /** + * @param int $project_id + * @param int $sponsorship_id + * @param int $company_id + * @param array $payload + * @return SupportingCompany + * @throws \Exception + */ + public function addCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id, array $payload): SupportingCompany + { + return $this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $company_id, $payload){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + $projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id); + if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType) + throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id)); + + $company = $this->company_repository->getById($company_id); + + if(is_null($company) || !$company instanceof Company) + throw new EntityNotFoundException(sprintf("company %s not found.", $company_id)); + + $supportingCompany = $projectSponsorshipType->addSupportingCompany($company); + + if (isset($payload['order']) && intval($payload['order']) != $supportingCompany->getOrder()) { + // request to update order + $projectSponsorshipType->recalculateSupportingCompanyOrder($supportingCompany, intval($payload['order'])); + } + + return $supportingCompany; + }); + } + + /** + * @inheritDoc + */ + public function removeCompanyToProjectSponsorshipType(int $project_id, int $sponsorship_id, int $company_id): void + { + $this->tx_service->transaction(function() use ($project_id, $sponsorship_id, $company_id){ + $sponsoredProject = $this->repository->getById($project_id); + + if(is_null($sponsoredProject) || !$sponsoredProject instanceof SponsoredProject) + throw new EntityNotFoundException(sprintf("sponsored project %s not found.", $project_id)); + + $projectSponsorshipType = $sponsoredProject->getSponsorshipTypeById($sponsorship_id); + if(is_null($projectSponsorshipType) || !$projectSponsorshipType instanceof ProjectSponsorshipType) + throw new EntityNotFoundException(sprintf("sponsorship type %s not found.", $project_id)); + + $company = $this->company_repository->getById($company_id); + + if(is_null($company) || !$company instanceof Company) + throw new EntityNotFoundException(sprintf("company %s not found.", $company_id)); + + $projectSponsorshipType->removeSupportingCompany($company); + }); + } +} \ No newline at end of file diff --git a/app/Services/ModelServicesProvider.php b/app/Services/ModelServicesProvider.php index a0d1f0c8..e2b04eb7 100644 --- a/app/Services/ModelServicesProvider.php +++ b/app/Services/ModelServicesProvider.php @@ -24,6 +24,7 @@ use App\Services\Model\IMemberService; use App\Services\Model\Imp\CompanyService; use App\Services\Model\Imp\PaymentGatewayProfileService; use App\Services\Model\Imp\RegistrationIngestionService; +use App\Services\Model\Imp\SponsoredProjectService; use App\Services\Model\Imp\SponsorUserInfoGrantService; use App\Services\Model\Imp\SummitAdministratorPermissionGroupService; use App\Services\Model\Imp\SummitDocumentService; @@ -38,6 +39,7 @@ use App\Services\Model\IPresentationCategoryGroupService; use App\Services\Model\IRegistrationIngestionService; use App\Services\Model\IRSVPTemplateService; use App\Services\Model\IScheduleIngestionService; +use App\Services\Model\ISponsoredProjectService; use App\Services\Model\ISponsorUserInfoGrantService; use App\Services\Model\ISponsorshipTypeService; use App\Services\Model\ISummitAccessLevelTypeService; @@ -394,6 +396,12 @@ final class ModelServicesProvider extends ServiceProvider ISummitMetricService::class, SummitMetricService::class ); + + App::singleton + ( + ISponsoredProjectService::class, + SponsoredProjectService::class + ); } /** diff --git a/app/Services/Utils/DoctrineTransactionService.php b/app/Services/Utils/DoctrineTransactionService.php index c727a7e8..8716544b 100644 --- a/app/Services/Utils/DoctrineTransactionService.php +++ b/app/Services/Utils/DoctrineTransactionService.php @@ -11,7 +11,6 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - use Doctrine\DBAL\Connection; use Doctrine\DBAL\TransactionIsolationLevel; use Illuminate\Support\Facades\Log; diff --git a/database/migrations/model/Version20201119155826.php b/database/migrations/model/Version20201119155826.php new file mode 100644 index 00000000..159ab8c5 --- /dev/null +++ b/database/migrations/model/Version20201119155826.php @@ -0,0 +1,108 @@ +hasTable("SponsoredProject")) { + $builder->create('SponsoredProject', function (Table $table) { + + $table->integer("ID", true, false); + $table->primary("ID"); + + $table->timestamp('Created'); + $table->timestamp('LastEdited'); + $table->string('ClassName'); + + $table->string('Name')->setLength(255); + $table->string('Description')->setNotnull(false)->setLength(1024); + $table->string('Slug')->setLength(255); + $table->boolean('IsActive'); + $table->unique("Name"); + $table->unique("Slug"); + }); + } + + if(!$schema->hasTable("ProjectSponsorshipType")) { + $builder->create('ProjectSponsorshipType', function (Table $table) { + + $table->integer("ID", true, false); + $table->primary("ID"); + + $table->timestamp('Created'); + $table->timestamp('LastEdited'); + $table->string('ClassName'); + + $table->string('Name')->setLength(255); + $table->string('Description')->setNotnull(false)->setLength(1024); + $table->string('Slug')->setLength(255); + $table->integer('Order')->setDefault(1);; + $table->boolean('IsActive'); + // FK + $table->integer("SponsoredProjectID", false, false)->setNotnull(false)->setDefault('NULL'); + $table->index("SponsoredProjectID", "SponsoredProjectID"); + $table->foreign("SponsoredProject", "SponsoredProjectID", "ID", ["onDelete" => "CASCADE"]); + $table->unique(["Name", "SponsoredProjectID"]); + $table->unique(["Slug", "SponsoredProjectID"]); + }); + } + + if(!$schema->hasTable("SupportingCompany")) { + $builder->create('SupportingCompany', function (Table $table) { + + $table->integer("ID", true, false); + $table->primary("ID"); + + $table->integer('Order')->setDefault(1); + + // FK + $table->integer("CompanyID", false, false)->setNotnull(false)->setDefault('NULL'); + $table->index("CompanyID", "CompanyID"); + $table->foreign("Company", "CompanyID", "ID", ["onDelete" => "CASCADE"]); + + // FK + $table->integer("ProjectSponsorshipTypeID", false, false)->setNotnull(false)->setDefault('NULL'); + $table->index("ProjectSponsorshipTypeID", "ProjectSponsorshipTypeID"); + $table->foreign("ProjectSponsorshipType", "ProjectSponsorshipTypeID", "ID", ["onDelete" => "CASCADE"]); + }); + } + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + $builder = new Builder($schema); + + $builder->dropIfExists("SupportingCompany"); + + $builder->dropIfExists("ProjectSponsorshipType"); + + $builder->dropIfExists("SponsoredProject"); + } +} diff --git a/database/migrations/model/Version20201120143925.php b/database/migrations/model/Version20201120143925.php new file mode 100644 index 00000000..3b64d029 --- /dev/null +++ b/database/migrations/model/Version20201120143925.php @@ -0,0 +1,45 @@ +addSql($sql); + + $sql = <<addSql($sql); + } + + /** + * @param Schema $schema + */ + public function down(Schema $schema) + { + + } +} diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 28326514..8fdbd6f4 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -20,6 +20,7 @@ use App\Security\OrganizationScopes; use App\Security\MemberScopes; use App\Models\Foundation\Main\IGroup; use App\Security\CompanyScopes; +use App\Security\SponsoredProjectScope; /** * Class ApiEndpointsSeeder */ @@ -36,6 +37,7 @@ class ApiEndpointsSeeder extends Seeder $this->seedMemberEndpoints(); $this->seedTagsEndpoints(); $this->seedCompaniesEndpoints(); + $this->seedSponsoredProjectsEndpoints(); $this->seedGroupsEndpoints(); $this->seedOrganizationsEndpoints(); $this->seedTrackQuestionTemplateEndpoints(); @@ -5683,6 +5685,152 @@ class ApiEndpointsSeeder extends Seeder ); } + private function seedSponsoredProjectsEndpoints(){ + $current_realm = Config::get('app.scope_base_realm'); + $this->seedApiEndpoints('sponsored-projects', [ + [ + 'name' => 'get-sponsored-projects', + 'route' => '/api/v1/sponsored-projects', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SponsoredProjectScope::Read, $current_realm) + ], + ], + [ + 'name' => 'add-sponsored-projects', + 'route' => '/api/v1/sponsored-projects', + 'http_method' => 'POST', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + [ + 'name' => 'update-sponsored-projects', + 'route' => '/api/v1/sponsored-projects/{id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + [ + 'name' => 'delete-sponsored-projects', + 'route' => '/api/v1/sponsored-projects/{id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + [ + 'name' => 'get-sponsored-project', + 'route' => '/api/v1/sponsored-projects/{id}', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SponsoredProjectScope::Read, $current_realm) + ] + ], + // sponsorship types + [ + 'name' => 'get-sponsored-project-sponsorship-types', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SponsoredProjectScope::Read, $current_realm) + ], + ], + [ + 'name' => 'add-sponsored-project-sponsorship-types', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types', + 'http_method' => 'POST', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + [ + 'name' => 'update-sponsored-project-sponsorship-types', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + + [ + 'name' => 'delete-sponsored-project-sponsorship-types', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + + [ + 'name' => 'get-sponsored-project-sponsorship-type', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SponsoredProjectScope::Read, $current_realm) + ], + ], + [ + 'name' => 'get-sponsored-project-supporting-companies', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies', + 'http_method' => 'GET', + 'scopes' => [ + sprintf(SponsoredProjectScope::Read, $current_realm) + ], + ], + [ + 'name' => 'add-sponsored-project-supporting-companies', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies/{company_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + [ + 'name' => 'delete-sponsored-project-supporting-companies', + 'route' => '/api/v1/sponsored-projects/{id}/sponsorship-types/{sponsorship_type_id}/supporting-companies/{company_id}', + 'http_method' => 'DELETE', + 'scopes' => [ + sprintf(SponsoredProjectScope::Write, $current_realm) + ], + 'authz_groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + ] + ], + ] + ); + } + private function seedGroupsEndpoints(){ $current_realm = Config::get('app.scope_base_realm'); diff --git a/database/seeds/ApiScopesSeeder.php b/database/seeds/ApiScopesSeeder.php index 06f0fe19..891f6ee6 100644 --- a/database/seeds/ApiScopesSeeder.php +++ b/database/seeds/ApiScopesSeeder.php @@ -20,6 +20,7 @@ use App\Security\SummitScopes; use App\Security\OrganizationScopes; use App\Security\MemberScopes; use App\Security\CompanyScopes; +use App\Security\SponsoredProjectScope; /** * Class ApiScopesSeeder */ @@ -36,6 +37,7 @@ final class ApiScopesSeeder extends Seeder $this->seedTeamsScopes(); $this->seedTagsScopes(); $this->seedCompaniesScopes(); + $this->seedSponsoredProjectsScopes(); $this->seedGroupsScopes(); $this->seedOrganizationScopes(); $this->seedSummitAdminGroupScopes(); @@ -516,6 +518,37 @@ final class ApiScopesSeeder extends Seeder EntityManager::flush(); } + private function seedSponsoredProjectsScopes(){ + $current_realm = Config::get('app.scope_base_realm'); + $api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'sponsored-projects']); + + $scopes = [ + [ + 'name' => sprintf(SponsoredProjectScope::Read, $current_realm), + 'short_description' => 'Get Sponsored Projects Data', + 'description' => 'Grants read only access for Sponsored Projects Data', + ], + [ + 'name' => sprintf(SponsoredProjectScope::Write, $current_realm), + 'short_description' => 'Write Sponsored Projects Data', + 'description' => 'Grants write only access for Sponsored Projects Data', + ], + ]; + + foreach ($scopes as $scope_info) { + $scope = new ApiScope(); + $scope->setName($scope_info['name']); + $scope->setShortDescription($scope_info['short_description']); + $scope->setDescription($scope_info['description']); + $scope->setActive(true); + $scope->setDefault(false); + $scope->setApi($api); + EntityManager::persist($scope); + } + + EntityManager::flush(); + } + private function seedGroupsScopes(){ $current_realm = Config::get('app.scope_base_realm'); $api = EntityManager::getRepository(\App\Models\ResourceServer\Api::class)->findOneBy(['name' => 'groups']); diff --git a/database/seeds/ApiSeeder.php b/database/seeds/ApiSeeder.php index 53cf869d..1ca0d09c 100644 --- a/database/seeds/ApiSeeder.php +++ b/database/seeds/ApiSeeder.php @@ -76,6 +76,16 @@ final class ApiSeeder extends Seeder EntityManager::flush(); + // sponsored projects + $api = new Api(); + $api->setName('sponsored-projects'); + $api->setActive(true); + $api->setDescription('Sponsored Projects API'); + + EntityManager::persist($api); + + EntityManager::flush(); + //groups $api = new Api(); diff --git a/tests/OAuth2SponsoredProjectsApiTest.php b/tests/OAuth2SponsoredProjectsApiTest.php new file mode 100644 index 00000000..be02ddf0 --- /dev/null +++ b/tests/OAuth2SponsoredProjectsApiTest.php @@ -0,0 +1,221 @@ + str_random(16).'_sponsored project', + 'description' => str_random(16).'_sponsored project description', + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "POST", + "OAuth2SponsoredProjectApiController@add", + [], + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $sponsored_projects = json_decode($content); + $this->assertTrue(!is_null($sponsored_projects)); + return $sponsored_projects; + } + + public function testGelAll() + { + + $params = [ + //AND FILTER + 'filter' => ['name=@sponsored project'], + 'order' => '-id' + ]; + + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2SponsoredProjectApiController@getAll", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $companies = json_decode($content); + $this->assertTrue(!is_null($companies)); + $this->assertResponseStatus(200); + } + + public function testAddSponsorshipType(){ + + $params = [ + 'id' => 1, + ]; + + $data = [ + 'name' => str_random(16).' sponsorship type', + 'description' => str_random(16).' sponsorship type description', + 'is_active' => true, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "POST", + "OAuth2SponsoredProjectApiController@addSponsorshipType", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $sponsorship_type = json_decode($content); + $this->assertTrue(!is_null($sponsorship_type)); + return $sponsorship_type; + } + + public function testUpdateSponsorshipType(){ + + $params = [ + 'id' => 1, + 'sponsorship_type_id' => 6 + ]; + + $data = [ + 'order' => 1 + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2SponsoredProjectApiController@updateSponsorshipType", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(204); + $sponsorship_type = json_decode($content); + $this->assertTrue(!is_null($sponsorship_type)); + return $sponsorship_type; + } + + public function testGetAllSponsorshipTypes(){ + $params = [ + 'id' => 'kata-containers', + 'expand' => 'supporting_companies, supporting_companies.company' + ]; + + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2SponsoredProjectApiController@getAllSponsorshipTypes", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $page = json_decode($content); + $this->assertTrue(!is_null($page)); + $this->assertResponseStatus(200); + } + + public function testAddSupportingCompany(){ + + $params = [ + 'id' => 1, + 'sponsorship_type_id' => 1, + 'company_id' => 12, + ]; + + $data = [ + 'order' => 2 + ]; + + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "PUT", + "OAuth2SponsoredProjectApiController@addSupportingCompanies", + $params, + array(), + array(), + array(), + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $company = json_decode($content); + $this->assertTrue(!is_null($company)); + $this->assertResponseStatus(200); + } + + public function testGetAllSupportingCompanies(){ + + $params = [ + 'id' => 'kata-containers', + 'sponsorship_type_id' => 'platinum-members', + 'expand' => 'company' + ]; + + $headers = array("HTTP_Authorization" => " Bearer " . $this->access_token); + $response = $this->action( + "GET", + "OAuth2SponsoredProjectApiController@getSupportingCompanies", + $params, + array(), + array(), + array(), + $headers + ); + + $content = $response->getContent(); + $page = json_decode($content); + $this->assertTrue(!is_null($page)); + $this->assertResponseStatus(200); + } +} \ No newline at end of file diff --git a/tests/ProtectedApiTest.php b/tests/ProtectedApiTest.php index c503465a..414ce7ea 100644 --- a/tests/ProtectedApiTest.php +++ b/tests/ProtectedApiTest.php @@ -20,6 +20,7 @@ use App\Security\OrganizationScopes; use App\Security\MemberScopes; use App\Models\Foundation\Main\IGroup; use App\Security\CompanyScopes; +use App\Security\SponsoredProjectScope; /** * Class AccessTokenServiceStub */ @@ -109,6 +110,8 @@ class AccessTokenServiceStub implements IAccessTokenService sprintf(SummitScopes::WriteSummitMediaFileTypes, $url), sprintf(CompanyScopes::Write, $url), sprintf(CompanyScopes::Read, $url), + sprintf(SponsoredProjectScope::Write, $url), + sprintf(SponsoredProjectScope::Read, $url), sprintf(SummitScopes::WriteMetrics, $url), sprintf(SummitScopes::ReadMetrics, $url), ); @@ -208,6 +211,8 @@ class AccessTokenServiceStub2 implements IAccessTokenService sprintf(SummitScopes::ReadMetrics, $url), sprintf(CompanyScopes::Write, $url), sprintf(CompanyScopes::Read, $url), + sprintf(SponsoredProjectScope::Write, $url), + sprintf(SponsoredProjectScope::Read, $url), ); return AccessToken::createFromParams( diff --git a/tests/SponsoredProjectModelTest.php b/tests/SponsoredProjectModelTest.php new file mode 100644 index 00000000..c15afa10 --- /dev/null +++ b/tests/SponsoredProjectModelTest.php @@ -0,0 +1,73 @@ +persist(self::$summit); + self::$em->flush(); + } + + protected function tearDown() + { + self::clearTestData(); + parent::tearDown(); + } + + public function testCreateSponsoredProject(){ + + $company_repository = EntityManager::getRepository(Company::class); + + $p1 = new SponsoredProject(); + $p1->setName("Kata Containers"); + $p1->setIsActive(true); + + $sponsorship1 = new ProjectSponsorshipType(); + $sponsorship1->setName("PLATINUM MEMBERS"); + $description1 = <<setDescription($description1); + $sponsorship1->setIsActive(true); + + $p1->addSponsorshipType($sponsorship1); + + $companies = $company_repository->findAll(); + + $sponsorship1->addSupportingCompany($companies[0]); + $sponsorship1->addSupportingCompany($companies[1]); + + self::$em->persist($p1); + self::$em->flush(); + } +} \ No newline at end of file