diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitMembersApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitMembersApiController.php index 91865f35..c9a04424 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitMembersApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitMembersApiController.php @@ -11,9 +11,11 @@ * See the License for the specific language governing permissions and * limitations under the License. **/ - +use App\Http\Utils\EpochCellFormatter; +use App\Http\Utils\PagingConstants; use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Request; +use Illuminate\Support\Facades\Validator; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; use models\main\IMemberRepository; @@ -21,9 +23,14 @@ use models\oauth2\IResourceServerContext; use models\summit\ISummitRepository; use ModelSerializers\SerializerRegistry; use services\model\ISummitService; +use utils\Filter; +use utils\FilterElement; +use utils\FilterParser; +use utils\FilterParserException; +use utils\OrderParser; +use utils\PagingInfo; use utils\PagingResponse; use Illuminate\Support\Facades\Input; - /** * Class OAuth2SummitMembersApiController * @package App\Http\Controllers @@ -60,6 +67,11 @@ final class OAuth2SummitMembersApiController extends OAuth2ProtectedController $this->summit_service = $summit_service; } + /** + * @param $summit_id + * @param $member_id + * @return \Illuminate\Http\JsonResponse|mixed + */ public function getMyMember($summit_id, $member_id){ $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); @@ -84,6 +96,11 @@ final class OAuth2SummitMembersApiController extends OAuth2ProtectedController ); } + /** + * @param $summit_id + * @param $member_id + * @return \Illuminate\Http\JsonResponse|mixed + */ public function getMemberFavoritesSummitEvents($summit_id, $member_id){ try { @@ -400,4 +417,260 @@ final class OAuth2SummitMembersApiController extends OAuth2ProtectedController } } + + /** + * @param $summit_id + * @return \Illuminate\Http\JsonResponse|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'), [ + 'irc' => ['=@', '=='], + 'twitter' => ['=@', '=='], + 'first_name' => ['=@', '=='], + 'last_name' => ['=@', '=='], + 'email' => ['=@', '=='], + 'group_slug' => ['=@', '=='], + 'group_id' => ['=='], + 'schedule_event_id' => ['=='], + 'email_verified' => ['=='], + 'active' => ['=='], + 'github_user' => ['=@', '=='], + 'full_name' => ['=@', '=='], + 'created' => ['>', '<', '<=', '>=', '=='], + 'last_edited' => ['>', '<', '<=', '>=', '=='], + ]); + } + + if(is_null($filter)) $filter = new Filter(); + + $filter->validate([ + 'irc' => 'sometimes|required|string', + 'twitter' => 'sometimes|required|string', + 'first_name' => 'sometimes|required|string', + 'last_name' => 'sometimes|required|string', + 'email' => 'sometimes|required|string', + 'group_slug' => 'sometimes|required|string', + 'group_id' => 'sometimes|required|integer', + 'schedule_event_id' => 'sometimes|required|integer', + 'email_verified' => 'sometimes|required|boolean', + 'active' => 'sometimes|required|boolean', + 'github_user' => 'sometimes|required|string', + 'full_name' => 'sometimes|required|string', + 'created' => 'sometimes|required|date_format:U', + 'last_edited' => 'sometimes|required|date_format:U', + ]); + + $order = null; + + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), [ + 'first_name', + 'last_name', + 'id', + 'created', + 'last_edited', + ]); + } + + $filter->addFilterCondition(FilterElement::makeEqual("summit_id", $summit_id)); + $data = $this->repository->getAllByPage(new PagingInfo($page, $per_page), $filter, $order); + $fields = Request::input('fields', ''); + $fields = !empty($fields) ? explode(',', $fields) : []; + $relations = Request::input('relations', ''); + $relations = !empty($relations) ? explode(',', $relations) : []; + + return $this->ok + ( + $data->toArray + ( + Request::input('expand', ''), + $fields, + $relations, + [], + SerializerRegistry::SerializerType_Private + ) + ); + } + catch (EntityNotFoundException $ex1) { + Log::warning($ex1); + return $this->error404(); + } + catch (ValidationException $ex2) { + Log::warning($ex2); + return $this->error412($ex2->getMessages()); + } + catch(FilterParserException $ex3){ + Log::warning($ex3); + return $this->error412($ex3->getMessages()); + } + catch (\Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + + /** + * @param $summit_id + * @return \Illuminate\Http\JsonResponse|mixed + */ + public function getAllBySummitCSV($summit_id){ + $values = Input::all(); + + $rules = [ + ]; + + 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 = PHP_INT_MAX; + + 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'), [ + 'irc' => ['=@', '=='], + 'twitter' => ['=@', '=='], + 'first_name' => ['=@', '=='], + 'last_name' => ['=@', '=='], + 'email' => ['=@', '=='], + 'group_slug' => ['=@', '=='], + 'group_id' => ['=='], + 'email_verified' => ['=='], + 'active' => ['=='], + 'github_user' => ['=@', '=='], + 'full_name' => ['=@', '=='], + 'created' => ['>', '<', '<=', '>=', '=='], + 'last_edited' => ['>', '<', '<=', '>=', '=='], + 'schedule_event_id' => ['=='], + ]); + } + + if(is_null($filter)) $filter = new Filter(); + + $filter->validate([ + 'irc' => 'sometimes|required|string', + 'twitter' => 'sometimes|required|string', + 'first_name' => 'sometimes|required|string', + 'last_name' => 'sometimes|required|string', + 'email' => 'sometimes|required|string', + 'group_slug' => 'sometimes|required|string', + 'group_id' => 'sometimes|required|integer', + 'email_verified' => 'sometimes|required|boolean', + 'active' => 'sometimes|required|boolean', + 'github_user' => 'sometimes|required|string', + 'full_name' => 'sometimes|required|string', + 'created' => 'sometimes|required|date_format:U', + 'last_edited' => 'sometimes|required|date_format:U', + 'schedule_event_id' => 'sometimes|required|integer', + ]); + + $order = null; + + if (Input::has('order')) + { + $order = OrderParser::parse(Input::get('order'), [ + 'first_name', + 'last_name', + 'id', + 'created', + 'last_edited', + ]); + } + + $filter->addFilterCondition(FilterElement::makeEqual("summit_id", $summit_id)); + $data = $this->repository->getAllByPage(new PagingInfo($page, $per_page), $filter, $order); + + $filename = "members-" . date('Ymd'); + + $fields = Request::input('fields', ''); + $fields = !empty($fields) ? explode(',', $fields) : []; + $relations = Request::input('relations', ''); + $relations = !empty($relations) ? explode(',', $relations) : []; + + $list = $data->toArray + ( + Request::input('expand', ''), + $fields, + $relations, + [], + SerializerRegistry::SerializerType_Private + ); + + return $this->export + ( + 'csv', + $filename, + $list['data'], + [ + 'created' => new EpochCellFormatter(), + 'last_edited' => new EpochCellFormatter(), + ] + ); + } + catch (EntityNotFoundException $ex1) { + Log::warning($ex1); + return $this->error404(); + } + catch (ValidationException $ex2) { + Log::warning($ex2); + return $this->error412($ex2->getMessages()); + } + catch(FilterParserException $ex3){ + Log::warning($ex3); + return $this->error412($ex3->getMessages()); + } + catch (\Exception $ex) { + Log::error($ex); + return $this->error500($ex); + } + } + } \ No newline at end of file diff --git a/app/Http/routes.php b/app/Http/routes.php index 608bf558..63a61572 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -557,6 +557,8 @@ Route::group([ // members Route::group(array('prefix' => 'members'), function () { + Route::get("", [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitMembersApiController@getAllBySummit']); + Route::get("csv", [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitMembersApiController@getAllBySummitCSV']); Route::group(array('prefix' => '{member_id}'), function () { Route::get('', 'OAuth2SummitMembersApiController@getMyMember')->where('member_id', 'me'); // favorites diff --git a/app/Repositories/Summit/DoctrineMemberRepository.php b/app/Repositories/Summit/DoctrineMemberRepository.php index 0cb5ab10..9dc58cc6 100644 --- a/app/Repositories/Summit/DoctrineMemberRepository.php +++ b/app/Repositories/Summit/DoctrineMemberRepository.php @@ -62,19 +62,29 @@ final class DoctrineMemberRepository ->andWhere("m.first_name is not null") ->andWhere("m.last_name is not null"); + + if($filter->hasFilter("summit_id") || $filter->hasFilter("schedule_event_id")){ + $query = $query + ->leftJoin("m.schedule","sch") + ->leftJoin("sch.event", "evt") + ->leftJoin("evt.summit", "s"); + } + if(!is_null($filter)){ $filter->apply2Query($query, [ - 'irc' => 'm.irc_handle:json_string', - 'created' => 'm.created:datetime_epoch', - 'last_edited' => 'm.last_edited:datetime_epoch', - 'twitter' => 'm.twitter_handle:json_string', - 'first_name' => 'm.first_name:json_string', - 'last_name' => 'm.last_name:json_string', - 'github_user' => 'm.github_user:json_string', - 'full_name' => new DoctrineFilterMapping("concat(m.first_name, ' ', m.last_name) :operator :value"), - 'email' => ['m.email:json_string', 'm.second_email:json_string', 'm.third_email:json_string'], - 'group_slug' => new DoctrineJoinFilterMapping + 'irc' => 'm.irc_handle:json_string', + 'created' => 'm.created:datetime_epoch', + 'last_edited' => 'm.last_edited:datetime_epoch', + 'twitter' => 'm.twitter_handle:json_string', + 'first_name' => 'm.first_name:json_string', + 'last_name' => 'm.last_name:json_string', + 'github_user' => 'm.github_user:json_string', + 'schedule_event_id' => 'evt.id', + 'summit_id' => 's.id', + 'full_name' => new DoctrineFilterMapping("concat(m.first_name, ' ', m.last_name) :operator :value"), + 'email' => ['m.email:json_string', 'm.second_email:json_string', 'm.third_email:json_string'], + 'group_slug' => new DoctrineJoinFilterMapping ( 'm.groups', 'g', diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index d9bf653b..81dbcc4f 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -2029,6 +2029,18 @@ class ApiEndpointsSeeder extends Seeder 'http_method' => 'DELETE', 'scopes' => [sprintf(SummitScopes::WriteSummitData, $current_realm)], ], + [ + 'name' => 'get-member-from-summit', + 'route' => '/api/v1/summits/{id}/members', + 'http_method' => 'GET', + 'scopes' => [sprintf(SummitScopes::ReadAllSummitData, $current_realm)], + ], + [ + 'name' => 'get-member-from-summit-csv', + 'route' => '/api/v1/summits/{id}/members/csv', + 'http_method' => 'GET', + 'scopes' => [sprintf(SummitScopes::ReadAllSummitData, $current_realm)], + ], // notifications [ 'name' => 'get-notifications', diff --git a/tests/OAuth2SummitApiTest.php b/tests/OAuth2SummitApiTest.php index aec5d037..2feba21a 100644 --- a/tests/OAuth2SummitApiTest.php +++ b/tests/OAuth2SummitApiTest.php @@ -1309,6 +1309,67 @@ final class OAuth2SummitApiTest extends ProtectedApiTest $this->assertTrue(!is_null($member)); } + /** + * @param int $summit_id + */ + public function testGetMembersBySummit($summit_id = 27) + { + + $params = [ + + 'expand' => 'attendee,speaker,feedback,groups,presentations', + 'id' => $summit_id, + 'filter' => 'schedule_event_id==23828' + ]; + + $headers = ["HTTP_Authorization" => " Bearer " . $this->access_token]; + $response = $this->action( + "GET", + "OAuth2SummitMembersApiController@getAllBySummit", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $members = json_decode($content); + $this->assertTrue(!is_null($members)); + } + + /** + * @param int $summit_id + */ + public function testGetMembersBySummitCSV($summit_id = 27) + { + + $params = [ + + 'expand' => 'attendee,speaker,feedback,groups,presentations', + 'id' => $summit_id, + 'filter' => 'schedule_event_id==23828' + ]; + + $headers = ["HTTP_Authorization" => " Bearer " . $this->access_token]; + $response = $this->action( + "GET", + "OAuth2SummitMembersApiController@getAllBySummitCSV", + $params, + [], + [], + [], + $headers + ); + + $content = $response->getContent(); + $this->assertResponseStatus(200); + $csv = $content; + $this->assertTrue(!empty($csv)); + } + + public function testCurrentSummitMyMemberFavorites() { $params = array