-
Notifications
You must be signed in to change notification settings - Fork 2
feat(speakers): add unique activities count endpoints for speakers an… #539
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,3 +40,4 @@ public/apc.php | |
| .nvmrc | ||
| .codegraph | ||
| docs/ | ||
| docker-compose.override.yml | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -58,7 +58,7 @@ protected function getBaseEntity() | |
| */ | ||
| protected function applyExtraJoins(QueryBuilder $query, ?Filter $filter = null, ?Order $order = null): QueryBuilder | ||
| { | ||
| if($filter->hasFilter("summit_id") || $filter->hasFilter("schedule_event_id")){ | ||
| if(!is_null($filter) && ($filter->hasFilter("summit_id") || $filter->hasFilter("schedule_event_id"))){ | ||
| $query | ||
| ->leftJoin("e.schedule","sch") | ||
| ->leftJoin("sch.event", "evt") | ||
|
|
@@ -638,6 +638,56 @@ function ($query) { | |
| }); | ||
| } | ||
|
|
||
| /** | ||
| * @param Summit $summit | ||
| * @param Filter|null $filter | ||
| * @return int | ||
| * @throws \Doctrine\DBAL\Exception | ||
| */ | ||
| public function getUniqueActivitiesCountBySummit(Summit $summit, Filter $filter = null): int | ||
| { | ||
| // Step 1: collect distinct member IDs matching the summit + filter using the | ||
| // same base query / filter mappings as getSubmittersBySummit. | ||
| $qb = $this->getEntityManager()->createQueryBuilder() | ||
| ->distinct(true) | ||
| ->select("e.id") | ||
| ->from($this->getBaseEntity(), "e") | ||
| ->where(" | ||
| EXISTS ( | ||
| SELECT __p.id FROM models\summit\Presentation __p | ||
| JOIN __p.created_by __cb93 WITH __cb93 = e.id | ||
| WHERE __p.summit = :summit | ||
| )") | ||
| ->setParameter("summit", $summit); | ||
|
|
||
| $qb = $this->applyExtraJoins($qb, $filter); | ||
|
|
||
| if (!is_null($filter)) { | ||
| $filter->apply2Query($qb, $this->getFilterMappings($filter)); | ||
| } | ||
|
|
||
| $memberIds = array_column($qb->getQuery()->getArrayResult(), 'id'); | ||
|
|
||
| if (empty($memberIds)) return 0; | ||
|
|
||
| // Step 2: count distinct presentations submitted by those members. | ||
| $sql = <<<SQL | ||
| SELECT COUNT(DISTINCT p.ID) AS cnt | ||
| FROM Presentation p | ||
| INNER JOIN SummitEvent se ON se.ID = p.ID | ||
| WHERE se.SummitID = :summit_id | ||
| AND p.CreatedByID IN (:member_ids) | ||
| SQL; | ||
|
|
||
| $stm = $this->getEntityManager()->getConnection()->executeQuery( | ||
| $sql, | ||
| ['summit_id' => $summit->getId(), 'member_ids' => $memberIds], | ||
| ['summit_id' => \Doctrine\DBAL\ParameterType::INTEGER, 'member_ids' => \Doctrine\DBAL\ArrayParameterType::INTEGER] | ||
| ); | ||
|
|
||
| return intval($stm->fetchOne()); | ||
| } | ||
|
Comment on lines
+647
to
+689
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Loading all member IDs into PHP for the Step 1 fetches every distinct matching member ID in one unbounded query ( The analogous For typical summit sizes (hundreds to a few thousand submitters) this is acceptable, but it should be acknowledged as a scale limit. A correlated-subquery approach that stays within the database would eliminate the round-trip: SELECT COUNT(DISTINCT p.ID) AS cnt
FROM Presentation p
INNER JOIN SummitEvent se ON se.ID = p.ID
WHERE se.SummitID = :summit_id
AND p.CreatedByID IN (
SELECT m.ID
FROM Member m
WHERE EXISTS (
SELECT 1
FROM Presentation p2
WHERE p2.CreatedByID = m.ID
AND p2.SummitID = :summit_id
-- filter conditions translated here
)
)This is high-effort to implement given the complex DQL filter system, but worth tracking. 🤖 Prompt for AI Agents |
||
|
|
||
| /** | ||
| * @param PagingInfo $paging_info | ||
| * @param Filter|null $filter | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OpenAPI filter description lists fewer filterable fields than the implementation accepts
The
descriptionstring on line 520 explicitly names the accepted filter fields but omits six fields that are in fact parsed byFilterParser::parse:not_id,member_user_external_id,presentations_title,presentations_abstract,presentations_submitter_full_name, andpresentations_submitter_email. Clients reading the spec will believe those fields are unsupported and won't use them, and any contract-test tooling that enforces the documented field list will reject valid requests.Either update the description to list all accepted fields, or intentionally remove the undocumented fields from the parse map (if they truly shouldn't be filterable on this endpoint).
📝 Proposed fix: align description with implementation
Also applies to: 549-571
🤖 Prompt for AI Agents