Skip to content
Closed
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
55 changes: 25 additions & 30 deletions app/Repositories/Summit/DoctrineSpeakerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -705,54 +705,49 @@ function ($query) {
*/
public function getUniqueActivitiesCountBySummit(Summit $summit, Filter $filter = null): int
{
// Inner query: distinct IDs of speakers who belong to this summit (via assignment
// or moderator role) and match any caller-supplied filter. Uses IDENTITY() with a
// scalar summit ID so no entity parameter is embedded in the getDQL() string —
// entity parameters copied into an outer QB via getDQL() are not correctly resolved
// to their primary key by Doctrine's type system.
// Build a non-correlated inner QB that selects IDs of speakers matching the filter.
// MySQL can materialise this set once per query rather than re-executing per row.
$innerQb = $this->getEntityManager()->createQueryBuilder()
->select('e.id')
->distinct(true)
->from('models\summit\PresentationSpeaker', 'e')
->leftJoin('e.registration_request', 'rr')
->leftJoin('e.member', 'm')
->where(
'EXISTS (SELECT 1 FROM App\Models\Foundation\Summit\Speakers\PresentationSpeakerAssignment __a'
. ' JOIN __a.presentation __ap WHERE IDENTITY(__ap.summit) = :summit_id AND __a.speaker = e)'
. ' OR EXISTS (SELECT 1 FROM models\summit\Presentation __mp WHERE IDENTITY(__mp.summit) = :summit_id AND __mp.moderator = e)'
)
->setParameter('summit_id', $summit->getId());
->leftJoin('e.registration_request', 'rr');

if (!is_null($filter)) {
$filter->apply2Query($innerQb, $this->getFilterMappings($filter));
}

$innerDql = $innerQb->getDQL();

// Outer query counts distinct presentations where at least one matched speaker is
// either an assigned speaker or the moderator. The inner DQL is embedded exactly
// once (inside a single wrapper EXISTS) to avoid Doctrine alias-conflict errors.
$outerQb = $this->getEntityManager()->createQueryBuilder()
->select('COUNT(DISTINCT p.id)')
// Q1: presentation IDs where a qualifying speaker is formally assigned.
$assignmentQb = $this->getEntityManager()->createQueryBuilder()
->select('p.id')
->from('models\summit\Presentation', 'p')
->join('p.speakers', 'a')
->where('p.summit = :summit')
->andWhere(
'EXISTS ('
. 'SELECT 1 FROM models\summit\PresentationSpeaker __spk'
. ' WHERE __spk.id IN (' . $innerDql . ')'
. ' AND ('
. 'EXISTS (SELECT 1 FROM App\Models\Foundation\Summit\Speakers\PresentationSpeakerAssignment __cnt WHERE __cnt.presentation = p AND __cnt.speaker = __spk)'
. ' OR p.moderator = __spk'
. ')'
. ')'
)
->andWhere('a.speaker IN (' . $innerDql . ')')
->setParameter('summit', $summit);

foreach ($innerQb->getParameters() as $param) {
$outerQb->setParameter($param->getName(), $param->getValue());
$assignmentQb->setParameter($param->getName(), $param->getValue(), $param->getType());
}

return intval($outerQb->getQuery()->getSingleScalarResult());
// Q2: presentation IDs where the moderator is a qualifying speaker.
$moderatorQb = $this->getEntityManager()->createQueryBuilder()
->select('p.id')
->from('models\summit\Presentation', 'p')
->where('p.summit = :summit')
->andWhere('p.moderator IN (' . $innerDql . ')')
->setParameter('summit', $summit);

foreach ($innerQb->getParameters() as $param) {
$moderatorQb->setParameter($param->getName(), $param->getValue(), $param->getType());
}

$assignmentIds = array_column($assignmentQb->getQuery()->getScalarResult(), 'id');
$moderatorIds = array_column($moderatorQb->getQuery()->getScalarResult(), 'id');

return count(array_unique(array_merge($assignmentIds, $moderatorIds)));
}

/**
Expand Down
Loading