diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSelectedPresentationListApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSelectedPresentationListApiController.php index 7e365c74..c6bcb21c 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSelectedPresentationListApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSelectedPresentationListApiController.php @@ -216,7 +216,7 @@ class OAuth2SummitSelectedPresentationListApiController $payload = $data->all(); // Creates a Validator instance and validates the data. $validation = Validator::make($payload,[ - 'hash' => 'required|string', + 'hash' => 'sometimes|string', 'collection' => sprintf('required|string|in:%s,%s', SummitSelectedPresentation::CollectionMaybe, SummitSelectedPresentation::CollectionSelected), 'presentations' => 'required|int_array', ]); diff --git a/app/ModelSerializers/Summit/Presentation/PresentationCategorySerializer.php b/app/ModelSerializers/Summit/Presentation/PresentationCategorySerializer.php index 065c64e9..e013a845 100644 --- a/app/ModelSerializers/Summit/Presentation/PresentationCategorySerializer.php +++ b/app/ModelSerializers/Summit/Presentation/PresentationCategorySerializer.php @@ -12,6 +12,7 @@ * limitations under the License. **/ +use Libs\ModelSerializers\AbstractSerializer; use models\summit\PresentationCategory; /** @@ -52,6 +53,7 @@ final class PresentationCategorySerializer extends SilverStripeSerializer $groups = []; $allowed_tag = []; $extra_questions = []; + $selection_lists = []; $summit = $category->getSummit(); foreach ($category->getGroups() as $group) { @@ -66,26 +68,32 @@ final class PresentationCategorySerializer extends SilverStripeSerializer $extra_questions[] = intval($question->getId()); } + foreach ($category->getSelectionLists() as $list) { + $selection_lists[] = intval($list->getId()); + } + + $values['track_groups'] = $groups; $values['allowed_tags'] = $allowed_tag; $values['extra_questions'] = $extra_questions; + $values['selection_lists'] = $selection_lists; if (!empty($expand)) { $exp_expand = explode(',', $expand); foreach ($exp_expand as $relation) { - switch (trim($relation)) { + $relation = trim($relation); + switch ($relation) { case 'track_groups': { $groups = []; unset($values['track_groups']); foreach ($category->getGroups() as $g) { - $groups[] = SerializerRegistry::getInstance()->getSerializer($g)->serialize(null, [], ['none']); + $groups[] = SerializerRegistry::getInstance()->getSerializer($g)->serialize(AbstractSerializer::filterExpandByPrefix($expand, $relation)); } $values['track_groups'] = $groups; } break; - } - switch (trim($relation)) { + case 'allowed_tags': { $allowed_tags = []; @@ -101,19 +109,30 @@ final class PresentationCategorySerializer extends SilverStripeSerializer $values['allowed_tags'] = $allowed_tags; } break; - } - switch (trim($relation)) { + case 'extra_questions': { $extra_questions = []; unset($values['extra_questions']); foreach ($category->getExtraQuestions() as $question) { - $extra_questions[] = SerializerRegistry::getInstance()->getSerializer($question)->serialize(null, [], ['none']); + $extra_questions[] = SerializerRegistry::getInstance()->getSerializer($question)->serialize(AbstractSerializer::filterExpandByPrefix($expand, $relation)); } $values['extra_questions'] = $extra_questions; } break; + + case 'selection_lists': + { + $selection_lists = []; + unset($values['selection_lists']); + foreach ($category->getSelectionLists() as $list) { + $selection_lists[] = SerializerRegistry::getInstance()->getSerializer($list)->serialize(AbstractSerializer::filterExpandByPrefix($expand, $relation)); + } + $values['selection_lists'] = $selection_lists; + } + break; } + } } diff --git a/app/ModelSerializers/Summit/Presentation/SummitSelectedPresentationListSerializer.php b/app/ModelSerializers/Summit/Presentation/SummitSelectedPresentationListSerializer.php index 7aee4d29..5c6b0737 100644 --- a/app/ModelSerializers/Summit/Presentation/SummitSelectedPresentationListSerializer.php +++ b/app/ModelSerializers/Summit/Presentation/SummitSelectedPresentationListSerializer.php @@ -30,15 +30,6 @@ final class SummitSelectedPresentationListSerializer extends SilverStripeSeriali 'OwnerId' => 'owner_id:json_int', ]; - protected static $allowed_fields = [ - 'name', - 'type', - 'popularity_score', - 'hash', - 'category_id', - 'owner_id', - ]; - protected static $allowed_relations = [ 'selected_presentations', 'interested_presentations', diff --git a/app/ModelSerializers/Summit/Presentation/SummitTrackChairSerializer.php b/app/ModelSerializers/Summit/Presentation/SummitTrackChairSerializer.php index 55efbd39..6804c23c 100644 --- a/app/ModelSerializers/Summit/Presentation/SummitTrackChairSerializer.php +++ b/app/ModelSerializers/Summit/Presentation/SummitTrackChairSerializer.php @@ -26,11 +26,6 @@ final class SummitTrackChairSerializer extends SilverStripeSerializer 'MemberId' => 'member_id:json_int', ]; - protected static $allowed_fields = [ - 'summit_id', - 'member_id', - ]; - protected static $allowed_relations = [ 'categories', ]; diff --git a/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php b/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php index 7e49aa6c..46a9f4c3 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php +++ b/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php @@ -641,6 +641,13 @@ SQL; return $list === false ? null : $list; } + /** + * @return ArrayCollection|SummitSelectedPresentationList[] + */ + public function getSelectionLists(){ + return $this->selection_lists; + } + /** * @param int $list_id * @return SummitSelectedPresentationList|null diff --git a/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitSelectedPresentationList.php b/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitSelectedPresentationList.php index b0afdb01..2d73f3c2 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitSelectedPresentationList.php +++ b/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitSelectedPresentationList.php @@ -80,6 +80,9 @@ class SummitSelectedPresentationList extends SilverstripeBaseModel */ private $selected_presentations; + /** + * SummitSelectedPresentationList constructor. + */ public function __construct() { parent::__construct(); diff --git a/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitTrackChair.php b/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitTrackChair.php index 73e118fb..fd270390 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitTrackChair.php +++ b/app/Models/Foundation/Summit/Events/Presentations/TrackChairs/SummitTrackChair.php @@ -64,6 +64,8 @@ class SummitTrackChair extends SilverstripeBaseModel * @throws ValidationException */ public function addCategory(PresentationCategory $track){ + if($this->categories->contains($track)) + return; if(!$track->isChairVisible()) throw new ValidationException(sprintf("Category %s is not visible by track chairs.", $track->getId())); @@ -73,10 +75,19 @@ class SummitTrackChair extends SilverstripeBaseModel /** * @param PresentationCategory $track + * @throws ValidationException */ public function removeCategory(PresentationCategory $track){ + if(!$this->categories->contains($track)) + return; $track->removeFromTrackChairs($this); $this->categories->removeElement($track); + + $list = $track->getSelectionListByTypeAndOwner(SummitSelectedPresentationList::Individual, $track, $this->member); + // if we remove the track , then we need to remove the selection lists + if(!is_null($list)){ + $track->removeSelectionList($list); + } } /** diff --git a/app/Services/Model/Imp/TrackChairService.php b/app/Services/Model/Imp/TrackChairService.php index dd393106..64ac0ece 100644 --- a/app/Services/Model/Imp/TrackChairService.php +++ b/app/Services/Model/Imp/TrackChairService.php @@ -16,6 +16,7 @@ use App\Models\Exceptions\AuthzException; use App\Models\Foundation\Main\IGroup; use App\Services\Model\AbstractService; use App\Services\Model\ITrackChairService; +use Illuminate\Support\Facades\Log; use libs\utils\ITransactionService; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; @@ -25,7 +26,9 @@ use models\main\Member; use models\oauth2\IResourceServerContext; use models\summit\PresentationCategory; use models\summit\Summit; +use models\summit\SummitSelectedPresentationList; use models\summit\SummitTrackChair; +use function Psy\debug; /** * Class TrackChairService @@ -111,12 +114,41 @@ final class TrackChairService foreach ($payload['categories'] as $track_id) { $track = $summit->getPresentationCategory(intval($track_id)); - if (is_null($track) || !$track instanceof PresentationCategory) + if (is_null($track) || !$track instanceof PresentationCategory || !$track->isChairVisible()) throw new EntityNotFoundException(sprintf("Presentation Category %s not found.", $track_id)); $categories[] = $track; } - return $summit->addTrackChair($member, $categories); + $track_chair = $summit->addTrackChair($member, $categories); + + foreach ($categories as $category) { + + $individual_selection_list = $category->getSelectionListByTypeAndOwner(SummitSelectedPresentationList::Individual, $category, $member); + + if (is_null($individual_selection_list)) { + $individual_selection_list = new SummitSelectedPresentationList(); + Log::debug(sprintf("TrackChaiService::addTrackChair adding individual list for track %s and member %s", $category->getId(), $member->getId())); + $individual_selection_list->setName(sprintf("%s Individual Selection List for %s", $member->getFullName(), $category->getTitle())); + $individual_selection_list->setListType(SummitSelectedPresentationList::Individual); + $individual_selection_list->setListClass(SummitSelectedPresentationList::Session); + $individual_selection_list->setOwner($member); + $category->addSelectionList($individual_selection_list); + } + + $team_selection_list = $category->getSelectionListByTypeAndOwner(SummitSelectedPresentationList::Group, $category); + if (is_null($team_selection_list)) { + Log::debug(sprintf("TrackChaiService::addTrackChair adding team list for track %s", $category->getId())); + $team_selection_list = new SummitSelectedPresentationList(); + $team_selection_list->setName(sprintf("Team Selections for %s", $category->getTitle())); + $team_selection_list->setListType(SummitSelectedPresentationList::Group); + $team_selection_list->setListClass(SummitSelectedPresentationList::Session); + $category->addSelectionList($team_selection_list); + } + + } + + return $track_chair; + }); } @@ -144,13 +176,45 @@ final class TrackChairService if(is_null($track_chair)) throw new EntityNotFoundException(sprintf("Track Chair %s not found.", $track_chair_id)); - $track_chair->clearCategories(); + $categories_2_remove = []; + + foreach ($track_chair->getCategories() as $category) { + if (!in_array($category->getId(), $payload['categories'])) + $categories_2_remove[] = $category; + } foreach ($payload['categories'] as $track_id) { - $track = $summit->getPresentationCategory(intval($track_id)); - if (is_null($track) || !$track instanceof PresentationCategory) + $category = $summit->getPresentationCategory(intval($track_id)); + if (is_null($category) || !$category instanceof PresentationCategory || !$category->isChairVisible()) throw new EntityNotFoundException(sprintf("Presentation Category %s not found.", $track_id)); - $track_chair->addCategory($track); + + $track_chair->addCategory($category); + + $individual_selection_list = $category->getSelectionListByTypeAndOwner(SummitSelectedPresentationList::Individual, $category, $track_chair->getMember()); + + if (is_null($individual_selection_list)) { + $individual_selection_list = new SummitSelectedPresentationList(); + Log::debug(sprintf("TrackChaiService::updateTrackChair adding individual list for track %s and member %s", $category->getId(), $track_chair->getMemberId())); + $individual_selection_list->setName(sprintf("%s Individual Selection List for ", $track_chair->getMember()->getFullName(), $category->getTitle())); + $individual_selection_list->setListType(SummitSelectedPresentationList::Individual); + $individual_selection_list->setListClass(SummitSelectedPresentationList::Session); + $individual_selection_list->setOwner($current_member); + $category->addSelectionList($individual_selection_list); + } + + $team_selection_list = $category->getSelectionListByTypeAndOwner(SummitSelectedPresentationList::Group, $category); + if (is_null($team_selection_list)) { + Log::debug(sprintf("TrackChaiService::updateTrackChair adding team list for track %s", $category->getId())); + $team_selection_list = new SummitSelectedPresentationList(); + $team_selection_list->setName(sprintf("Team Selections for %s", $category->getTitle())); + $team_selection_list->setListType(SummitSelectedPresentationList::Group); + $team_selection_list->setListClass(SummitSelectedPresentationList::Session); + $category->addSelectionList($team_selection_list); + } + } + + foreach ($categories_2_remove as $category){ + $track_chair->removeCategory($category); } return $track_chair; @@ -158,7 +222,9 @@ final class TrackChairService } /** - * @inheritDoc + * @param Summit $summit + * @param int $track_chair_id + * @throws \Exception */ public function deleteTrackChair(Summit $summit, int $track_chair_id): void { @@ -177,6 +243,10 @@ final class TrackChairService if(is_null($track_chair)) throw new EntityNotFoundException(sprintf("Track Chair %s not found.", $track_chair_id)); + foreach($track_chair->getCategories() as $category){ + $track_chair->removeCategory($category); + } + $summit->removeTrackChair($track_chair); }); } diff --git a/tests/OAuth2SummitSelectedPresentationListApiTest.php b/tests/OAuth2SummitSelectedPresentationListApiTest.php index 0c2e2cdf..9762cd0d 100644 --- a/tests/OAuth2SummitSelectedPresentationListApiTest.php +++ b/tests/OAuth2SummitSelectedPresentationListApiTest.php @@ -110,7 +110,7 @@ final class OAuth2SummitSelectedPresentationListApiTest /** * @return mixed */ - public function testAddIndividualSelectionListAndAddSelectionAndRemoveIt(){ + public function testAddIndividualSelectionListAndReorder(){ $params = [ 'id' => self::$summit->getId(), @@ -162,11 +162,79 @@ final class OAuth2SummitSelectedPresentationListApiTest "" ); + $content = $response->getContent(); + $this->assertResponseStatus(201); + + $params = [ + 'id' => self::$summit->getId(), + 'track_id' => self::$defaultTrack->getId(), + 'list_id' => $selection_list->id, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $data = [ + 'collection' => SummitSelectedPresentation::CollectionSelected, + 'presentations' => [ + self::$presentations[1]->getId(), + self::$presentations[0]->getId(), + self::$presentations[2]->getId() + ] + ]; + + $response = $this->action( + "PUT", + "OAuth2SummitSelectedPresentationListApiController@reorderSelectionList", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $selection_list = json_decode($content); + $this->assertTrue(!is_null($selection_list)); + $this->assertTrue(count($selection_list->selected_presentations) == 3); + + return $selection_list; + } + + /** + * @return mixed + */ + public function testAddIndividualSelectionListAndReorderRemove(){ + + $params = [ + 'id' => self::$summit->getId(), + 'track_id' => self::$defaultTrack->getId(), + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "POST", + "OAuth2SummitSelectedPresentationListApiController@createIndividualSelectionList", + $params, + [], + [], + [], + $headers, + "" + ); + $content = $response->getContent(); $this->assertResponseStatus(201); $selection_list = json_decode($content); $this->assertTrue(!is_null($selection_list)); - $this->assertTrue(count($selection_list->selected_presentations) > 0); $params = [ 'id' => self::$summit->getId(), @@ -182,8 +250,8 @@ final class OAuth2SummitSelectedPresentationListApiTest ]; $response = $this->action( - "DELETE", - "OAuth2SummitSelectedPresentationListApiController@removePresentationFromMyIndividualList", + "POST", + "OAuth2SummitSelectedPresentationListApiController@assignPresentationToMyIndividualList", $params, [], [], @@ -192,11 +260,44 @@ final class OAuth2SummitSelectedPresentationListApiTest "" ); + $content = $response->getContent(); + $this->assertResponseStatus(201); + + $params = [ + 'id' => self::$summit->getId(), + 'track_id' => self::$defaultTrack->getId(), + 'list_id' => $selection_list->id, + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $data = [ + 'collection' => SummitSelectedPresentation::CollectionSelected, + 'presentations' => [ + self::$presentations[1]->getId(), + self::$presentations[2]->getId() + ] + ]; + + $response = $this->action( + "PUT", + "OAuth2SummitSelectedPresentationListApiController@reorderSelectionList", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + $content = $response->getContent(); $this->assertResponseStatus(201); $selection_list = json_decode($content); $this->assertTrue(!is_null($selection_list)); - $this->assertTrue(count($selection_list->selected_presentations) == 0); + $this->assertTrue(count($selection_list->selected_presentations) == 2); return $selection_list; } diff --git a/tests/OAuth2SummitTrackChairsApiTest.php b/tests/OAuth2SummitTrackChairsApiTest.php index 248b069d..e34c53b1 100644 --- a/tests/OAuth2SummitTrackChairsApiTest.php +++ b/tests/OAuth2SummitTrackChairsApiTest.php @@ -76,6 +76,7 @@ class OAuth2SummitTrackChairsApiTest extends \ProtectedApiTest } public function testAddTrackChair(){ + $params = [ 'id' => self::$summit->getId(), 'expand' => 'member,categories' @@ -108,4 +109,72 @@ class OAuth2SummitTrackChairsApiTest extends \ProtectedApiTest $this->assertTrue(!is_null($track_chair)); } + public function testUpdateTrackChair(){ + + $params = [ + 'id' => self::$summit->getId(), + 'expand' => 'member,categories,categories.selection_lists' + ]; + + $data = [ + 'member_id' => self::$member2->getId(), + 'categories' => [self::$defaultTrack->getId()] + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "POST", + "OAuth2SummitTrackChairsApiController@add", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $track_chair = json_decode($content); + $this->assertTrue(!is_null($track_chair)); + + $params = [ + 'id' => self::$summit->getId(), + 'track_chair_id' => $track_chair->id, + 'expand' => 'member,categories,categories.selection_lists' + ]; + + $data = [ + 'member_id' => self::$member2->getId(), + 'categories' => [ + self::$secondaryTrack->getId() + ] + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2SummitTrackChairsApiController@update", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $track_chair = json_decode($content); + $this->assertTrue(!is_null($track_chair)); + } + } \ No newline at end of file