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
47 changes: 19 additions & 28 deletions app/Repositories/Summit/DoctrineSpeakerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -705,54 +705,45 @@ 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 the EXISTS inner QB rooted at PresentationSpeaker (e) with the joins that
// filter mappings expect (m, rr). The initial WHERE ties e to the outer presentation
// p via assignment or moderator role; filter conditions are then appended by
// apply2Query. The EXISTS approach lets MySQL use the
// index on Presentation_Speakers(PresentationID) to reach speakers for each p directly
// and short-circuit on the first match.
$innerQb = $this->getEntityManager()->createQueryBuilder()
->select('e.id')
->distinct(true)
->select('1')
->from('models\summit\PresentationSpeaker', 'e')
->leftJoin('e.registration_request', 'rr')
->leftJoin('e.member', 'm')
->leftJoin('e.registration_request', 'rr')
->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());
. ' WHERE __a.presentation = p AND __a.speaker = e)'
. ' OR p.moderator = e'
);

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()
$qb = $this->getEntityManager()->createQueryBuilder()
->select('COUNT(DISTINCT p.id)')
->from('models\summit\Presentation', 'p')
->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('EXISTS (' . $innerDql . ')')
->setParameter('summit', $summit);

// Copy filter-specific parameter bindings (e.g. :value_N for text/id filters).
// Filter sub-queries reference :summit by name; that is satisfied by the binding above.
foreach ($innerQb->getParameters() as $param) {
$outerQb->setParameter($param->getName(), $param->getValue());
if ($param->getName() !== 'summit') {
$qb->setParameter($param->getName(), $param->getValue(), $param->getType());
}
}

return intval($outerQb->getQuery()->getSingleScalarResult());
return intval($qb->getQuery()->getSingleScalarResult());
}

/**
Expand Down
Loading