Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,28 @@ public function calculateSlug(){
return $this;
}

/**
* @param int[] $selection_plan_ids
* @return Presentation[]
*/
public function getPresentationsBySelectionPlanIds(array $selection_plan_ids): array
{
if (empty($selection_plan_ids)) return [];

$query = <<<DQL
SELECT p
FROM models\summit\Presentation p
WHERE p.category = :track
AND p.selection_plan IN (:selection_plan_ids)
DQL;

return $this->getEM()
->createQuery($query)
->setParameter('track', $this)
->setParameter('selection_plan_ids', $selection_plan_ids)
->getResult();
}

/**
* @return SummitEvent[]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
**/

use App\Models\Foundation\Summit\ScheduleEntity;
use App\Models\Foundation\Summit\SelectionPlan;
use Doctrine\Common\Collections\Criteria;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
Expand Down Expand Up @@ -70,13 +71,43 @@ class PresentationCategoryGroup extends SilverstripeBaseModel
protected $max_attendee_votes;


/**
* inverse side
* @var SelectionPlan[]
*/
#[ORM\ManyToMany(targetEntity: \App\Models\Foundation\Summit\SelectionPlan::class, mappedBy: 'category_groups', fetch: 'EXTRA_LAZY')]
protected $selection_plans;

public function __construct()
{
parent::__construct();
$this->begin_attendee_voting_period_date = null;
$this->end_attendee_voting_period_date = null;
$this->max_attendee_votes = 0;
$this->categories = new ArrayCollection;
$this->selection_plans = new ArrayCollection;
}

/**
* @return int[]
*/
public function getSelectionPlanIds(): array
{
return $this->selection_plans->map(function ($sp) {
return $sp->getId();
})->toArray();
}

public function addSelectionPlan(SelectionPlan $selection_plan): void
{
if ($this->selection_plans->contains($selection_plan)) return;
$this->selection_plans->add($selection_plan);
}

public function removeSelectionPlan(SelectionPlan $selection_plan): void
{
if (!$this->selection_plans->contains($selection_plan)) return;
$this->selection_plans->removeElement($selection_plan);
}


Expand Down Expand Up @@ -382,4 +413,4 @@ public function clearAttendeeVotingPeriod():void{
}

use ScheduleEntity;
}
}
4 changes: 3 additions & 1 deletion app/Models/Foundation/Summit/SelectionPlan.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ class SelectionPlan extends SilverstripeBaseModel
#[ORM\JoinTable(name: 'SelectionPlan_CategoryGroups')]
#[ORM\JoinColumn(name: 'SelectionPlanID', referencedColumnName: 'ID')]
#[ORM\InverseJoinColumn(name: 'PresentationCategoryGroupID', referencedColumnName: 'ID')]
#[ORM\ManyToMany(targetEntity: \models\summit\PresentationCategoryGroup::class, fetch: 'EXTRA_LAZY')]
#[ORM\ManyToMany(targetEntity: \models\summit\PresentationCategoryGroup::class, inversedBy: 'selection_plans', fetch: 'EXTRA_LAZY')]
private $category_groups;

/**
Expand Down Expand Up @@ -596,6 +596,7 @@ public function addTrackGroup(PresentationCategoryGroup $track_group)
{
if ($this->category_groups->contains($track_group)) return;
$this->category_groups->add($track_group);
$track_group->addSelectionPlan($this);
}

/**
Expand All @@ -605,6 +606,7 @@ public function removeTrackGroup(PresentationCategoryGroup $track_group)
{
if (!$this->category_groups->contains($track_group)) return;
$this->category_groups->removeElement($track_group);
$track_group->removeSelectionPlan($this);
}

public function addEventType(SummitEventType $eventType)
Expand Down
23 changes: 22 additions & 1 deletion app/Services/Model/Imp/PresentationCategoryGroupService.php
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,27 @@ public function disassociateTrack2TrackGroup(Summit $summit, $track_group_id, $t
);
}

$presentations = $track->getPresentationsBySelectionPlanIds($track_group->getSelectionPlanIds());

// Only clear the selection plan if no other category group in that plan
// still contains $track. A selection plan can span multiple groups, so
// removing $track from $track_group does not necessarily invalidate the
// plan for presentations under $track — another group may still cover it.
// We exclude $track_group from the check because removeCategory has not
// been called yet at this point.
foreach ($presentations as $presentation) {
$selection_plan = $presentation->getSelectionPlan();
$track_reachable_via_another_group = $selection_plan->getCategoryGroups()->exists(
function ($key, $group) use ($track, $track_group) {
return $group->getId() !== $track_group->getId()
&& $group->hasCategory($track->getId());
}
);
if (!$track_reachable_via_another_group) {
$presentation->clearSelectionPlan();
}
}

$track_group->removeCategory($track);

});
Expand Down Expand Up @@ -380,4 +401,4 @@ public function disassociateAllowedGroup2TrackGroup(Summit $summit, $track_group

});
}
}
}
24 changes: 23 additions & 1 deletion tests/oauth2/OAuth2TrackGroupsApiTest.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
<?php namespace Tests;
use LaravelDoctrine\ORM\Facades\Registry;
use models\summit\Presentation;
use models\utils\SilverstripeBaseModel;

/**
* Copyright 2018 OpenStack Foundation
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -341,6 +345,16 @@ public function testDisassociateTrack2TrackGroup(){

$this->assertResponseStatus(201);

// verify presentations of defaultTrack have a selection plan before disassociation
$presentations = self::$defaultTrack->getPresentationsBySelectionPlanIds(
self::$defaultTrackGroup->getSelectionPlanIds()
);
$this->assertNotEmpty($presentations);
foreach ($presentations as $presentation) {
$this->assertTrue($presentation->getSelectionPlanId() > 0);
}
$presentation_ids = array_map(fn($p) => $p->getId(), $presentations);

// now disassociate
$response = $this->action(
"DELETE",
Expand All @@ -353,6 +367,14 @@ public function testDisassociateTrack2TrackGroup(){
);

$this->assertResponseStatus(204);

// reset EM (closed after the API transaction) and re-fetch presentations to verify selection plan was cleared
self::$em = Registry::resetManager(SilverstripeBaseModel::EntityManager);
foreach ($presentation_ids as $id) {
$presentation = self::$em->find(Presentation::class, $id);
$this->assertNotNull($presentation);
$this->assertEquals(0, $presentation->getSelectionPlanId());
}
}

public function testAddPrivateTrackGroup(){
Expand Down Expand Up @@ -480,4 +502,4 @@ public function testDeleteExistentTrackGroup(){
$content = $response->getContent();
$this->assertResponseStatus(204);
}
}
}
Loading