diff --git a/app/Events/TrackUpdated.php b/app/Events/TrackUpdated.php new file mode 100644 index 00000000..ade2b994 --- /dev/null +++ b/app/Events/TrackUpdated.php @@ -0,0 +1,45 @@ +track = $track; + } + + /** + * @return PresentationCategory + */ + public function getTrack() + { + return $this->track; + } +} \ No newline at end of file diff --git a/app/Factories/EntityEvents/TrackUpdatedEntityEventFactory.php b/app/Factories/EntityEvents/TrackUpdatedEntityEventFactory.php new file mode 100644 index 00000000..08d3328c --- /dev/null +++ b/app/Factories/EntityEvents/TrackUpdatedEntityEventFactory.php @@ -0,0 +1,55 @@ +getCurrentUserExternalId(); + if(is_null($owner_id)) $owner_id = 0; + + foreach($event->getTrack()->getRelatedPublishedSummitEvents() as $summit_event) { + + $entity_event = new SummitEntityEvent; + $entity_event->setEntityClassName($summit_event->getClassName()); + $entity_event->setEntityId($summit_event->getId()); + $entity_event->setType('UPDATE'); + + if ($owner_id > 0) { + $member = $member_repository->getById($owner_id); + $entity_event->setOwner($member); + } + + $entity_event->setSummit($summit_event->getSummit()); + $entity_event->setMetadata(''); + + $list[] = $entity_event; + } + + return $list; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTracksApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTracksApiController.php index c0802024..cc1f8726 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTracksApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitTracksApiController.php @@ -337,4 +337,60 @@ final class OAuth2SummitTracksApiController extends OAuth2ProtectedController return $this->error500($ex); } } + + /** + * @param $summit_id + * @param $track_id + * @return mixed + */ + public function updateTrackBySummit($summit_id, $track_id){ + try { + if(!Request::isJson()) return $this->error403(); + $data = Input::json(); + + $summit = SummitFinderStrategyFactory::build($this->summit_repository, $this->resource_server_context)->find($summit_id); + if (is_null($summit)) return $this->error404(); + + $rules = [ + 'title' => 'sometimes|string|max:50', + 'description' => 'sometimes|string|max:500', + 'code' => 'sometimes|string|max:5', + 'session_count' => 'sometimes|integer', + 'alternate_count' => 'sometimes|integer', + 'lightning_count' => 'sometimes|integer', + 'lightning_alternate_count' => 'sometimes|integer', + 'voting_visible' => 'sometimes|boolean', + 'chair_visible' => 'sometimes|boolean', + ]; + + // Creates a Validator instance and validates the data. + $validation = Validator::make($data->all(), $rules); + + if ($validation->fails()) { + $messages = $validation->messages()->toArray(); + + return $this->error412 + ( + $messages + ); + } + + $track = $this->track_service->updateTrack($summit, $track_id, $data->all()); + + return $this->updated(SerializerRegistry::getInstance()->getSerializer($track)->serialize()); + } + catch (ValidationException $ex1) { + Log::warning($ex1); + return $this->error412(array($ex1->getMessage())); + } + catch(EntityNotFoundException $ex2) + { + Log::warning($ex2); + return $this->error404(array('message'=> $ex2->getMessage())); + } + 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 e8024a1d..1ceeecec 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -349,6 +349,7 @@ Route::group([ Route::post('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitTracksApiController@addTrackBySummit']); Route::group(['prefix' => '{track_id}'], function () { Route::get('', 'OAuth2SummitTracksApiController@getTrackBySummit'); + Route::put('', [ 'middleware' => 'auth.user:administrators|summit-front-end-administrators', 'uses' => 'OAuth2SummitTracksApiController@updateTrackBySummit']); }); }); diff --git a/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php b/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php index bd71d3c9..c69ac2bc 100644 --- a/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php +++ b/app/Models/Foundation/Summit/Events/Presentations/PresentationCategory.php @@ -14,6 +14,7 @@ use App\Models\Foundation\Summit\Events\Presentations\PresentationCategoryAllowedTag; use Doctrine\ORM\Event\PreUpdateEventArgs; use Doctrine\ORM\Mapping AS ORM; +use Doctrine\ORM\Query\ResultSetMappingBuilder; use models\utils\SilverstripeBaseModel; use Doctrine\Common\Collections\ArrayCollection; /** @@ -289,4 +290,30 @@ class PresentationCategory extends SilverstripeBaseModel $this->slug = preg_replace('/\s+/', '-', strtolower($clean_title)); return $this; } + + /** + * @return SummitEvent[] + */ + public function getRelatedPublishedSummitEvents(){ + $query = <<getEM()); + $rsm->addRootEntityFromClassMetadata(\models\summit\SummitEvent::class, 'e'); + + // build rsm here + $native_query = $this->getEM()->createNativeQuery($query, $rsm); + + $native_query->setParameter("summit_id", $this->summit->getId()); + $native_query->setParameter("track_id", $this->id); + + return $native_query->getResult(); + + } } \ No newline at end of file diff --git a/app/Models/Foundation/Summit/Summit.php b/app/Models/Foundation/Summit/Summit.php index c52d580e..d32c2e04 100644 --- a/app/Models/Foundation/Summit/Summit.php +++ b/app/Models/Foundation/Summit/Summit.php @@ -874,7 +874,7 @@ class Summit extends SilverstripeBaseModel */ public function getPresentationCategoryByCode($category_code){ $criteria = Criteria::create(); - $criteria->where(Criteria::expr()->eq('code', intval($category_code))); + $criteria->where(Criteria::expr()->eq('code', trim($category_code))); $category = $this->presentation_categories->matching($criteria)->first(); return $category === false ? null:$category; } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 4e14cec7..f2aed2db 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -30,6 +30,7 @@ use App\Factories\EntityEvents\PresentationSpeakerUpdatedEntityEventFactory; use App\Factories\EntityEvents\SummitEventCreatedEntityEventFactory; use App\Factories\EntityEvents\SummitEventDeletedEntityEventFactory; use App\Factories\EntityEvents\SummitEventUpdatedEntityEventFactory; +use App\Factories\EntityEvents\TrackUpdatedEntityEventFactory; use App\Services\Utils\SCPFileUploader; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; use Illuminate\Support\Facades\Event; @@ -134,5 +135,10 @@ final class EventServiceProvider extends ServiceProvider EntityEventPersister::persist_list(PresentationSpeakerDeletedEntityEventFactory::build($event)); }); + Event::listen(\App\Events\TrackUpdated::class, function($event) + { + EntityEventPersister::persist_list(TrackUpdatedEntityEventFactory::build($event)); + }); + } } diff --git a/app/Services/Model/SummitTrackService.php b/app/Services/Model/SummitTrackService.php index 2675f3f3..8318ce0d 100644 --- a/app/Services/Model/SummitTrackService.php +++ b/app/Services/Model/SummitTrackService.php @@ -1,4 +1,5 @@ tx_service->transaction(function() use($summit, $data){ + return $this->tx_service->transaction(function () use ($summit, $data) { - $former_track = $summit->getPresentationCategoryByCode($data['code']); - if(!is_null($former_track)) - throw new ValidationException(sprintf("track id %s already has code %s assigned on summit id %s", $former_track->getId(), $data['code'], $summit->getId())); + $former_track = $summit->getPresentationCategoryByCode($data['code']); + if (!is_null($former_track)) + throw new ValidationException(sprintf("track id %s already has code %s assigned on summit id %s", $former_track->getId(), $data['code'], $summit->getId())); - $former_track = $summit->getPresentationCategoryByTitle($data['title']); - if(!is_null($former_track)) + $former_track = $summit->getPresentationCategoryByTitle($data['title']); + if (!is_null($former_track)) throw new ValidationException(sprintf("track id %s already has title %s assigned on summit id %s", $former_track->getId(), $data['title'], $summit->getId())); $track = PresentationCategoryFactory::build($summit, $data); @@ -81,7 +85,33 @@ final class SummitTrackService implements ISummitTrackService */ public function updateTrack(Summit $summit, $track_id, array $data) { - // TODO: Implement updateTrack() method. + return $this->tx_service->transaction(function () use ($summit, $track_id, $data) { + + $track = $summit->getPresentationCategory($track_id); + + if (is_null($track)) + throw new EntityNotFoundException + ( + sprintf("track id %s does not belong to summit id %s", $track_id, $summit->getId()) + ); + + if (isset($data['code'])) { + $former_track = $summit->getPresentationCategoryByCode($data['code']); + if (!is_null($former_track) && $former_track->getId() != $track_id) + throw new ValidationException(sprintf("track id %s already has code %s assigned on summit id %s", $former_track->getId(), $data['code'], $summit->getId())); + } + + if (isset($data['title'])) { + $former_track = $summit->getPresentationCategoryByTitle($data['title']); + if (!is_null($former_track) && $former_track->getId() != $track_id) + throw new ValidationException(sprintf("track id %s already has title %s assigned on summit id %s", $former_track->getId(), $data['title'], $summit->getId())); + } + + return PresentationCategoryFactory::populate($track, $data); + + Event::fire(new TrackUpdated($track)); + + }); } /** diff --git a/database/seeds/ApiEndpointsSeeder.php b/database/seeds/ApiEndpointsSeeder.php index 15847b75..2cb2181c 100644 --- a/database/seeds/ApiEndpointsSeeder.php +++ b/database/seeds/ApiEndpointsSeeder.php @@ -637,6 +637,15 @@ class ApiEndpointsSeeder extends Seeder sprintf(SummitScopes::WriteSummitData, $current_realm) ], ], + [ + 'name' => 'update-tracks', + 'route' => '/api/v1/summits/{id}/tracks/{track_id}', + 'http_method' => 'PUT', + 'scopes' => [ + sprintf(SummitScopes::WriteTracksData, $current_realm), + sprintf(SummitScopes::WriteSummitData, $current_realm) + ], + ], // track groups array( 'name' => 'get-track-groups', diff --git a/tests/OAuth2TracksApiTest.php b/tests/OAuth2TracksApiTest.php index 420bcecb..58d40ad6 100644 --- a/tests/OAuth2TracksApiTest.php +++ b/tests/OAuth2TracksApiTest.php @@ -17,6 +17,10 @@ */ final class OAuth2TracksApiTest extends ProtectedApiTest { + /** + * @param int $summit_id + * @return mixed + */ public function testGetTracksByTitle($summit_id = 23){ $params = [ @@ -50,6 +54,11 @@ final class OAuth2TracksApiTest extends ProtectedApiTest return $tracks; } + /** + * @param int $summit_id + * @param int $track_id + * @return mixed + */ public function testGetTracksById($summit_id = 23, $track_id = 152){ $params = [ @@ -79,6 +88,9 @@ final class OAuth2TracksApiTest extends ProtectedApiTest return $track; } + /** + * @param int $summit_id + */ public function testGetTracksByTitleCSV($summit_id = 23){ $params = [ @@ -109,6 +121,10 @@ final class OAuth2TracksApiTest extends ProtectedApiTest $this->assertTrue(!empty($csv)); } + /** + * @param int $summit_id + * @return mixed + */ public function testAddTrack($summit_id = 23){ $params = [ 'id' => $summit_id, @@ -143,4 +159,48 @@ final class OAuth2TracksApiTest extends ProtectedApiTest $this->assertTrue(!is_null($track)); return $track; } + + /** + * @param int $summit_id + * @return mixed + */ + public function testUpdateTrack($summit_id = 23){ + + $new_track = $this->testAddTrack($summit_id); + + $params = [ + 'id' => $summit_id, + 'track_id' => $new_track->id + ]; + + $name = str_random(16).'_track'; + $data = [ + 'description' => 'test desc updated', + 'code' => 'SMX' , + ]; + + $headers = [ + "HTTP_Authorization" => " Bearer " . $this->access_token, + "CONTENT_TYPE" => "application/json" + ]; + + $response = $this->action( + "PUT", + "OAuth2SummitTracksApiController@updateTrackBySummit", + $params, + [], + [], + [], + $headers, + json_encode($data) + ); + + $content = $response->getContent(); + $this->assertResponseStatus(201); + $track = json_decode($content); + $this->assertTrue(!is_null($track)); + $this->assertTrue(!empty($track->description) && $track->description == 'test desc updated'); + $this->assertTrue(!empty($track->code) && $track->code == 'SMX'); + return $track; + } } \ No newline at end of file