Skip to content

Commit 2928941

Browse files
fix(population): exclude nested circles from population counts
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
1 parent 070bc80 commit 2928941

File tree

4 files changed

+93
-7
lines changed

4 files changed

+93
-7
lines changed

lib/Db/MembershipRequest.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use OCA\Circles\Exceptions\MembershipNotFoundException;
1515
use OCA\Circles\Model\FederatedUser;
16+
use OCA\Circles\Model\Member;
1617
use OCA\Circles\Model\Membership;
1718
use OCP\DB\QueryBuilder\IQueryBuilder;
1819

@@ -113,6 +114,45 @@ public function getInherited(string $singleId, int $level = 0): array {
113114
return $this->getItemsFromRequest($qb);
114115
}
115116

117+
/**
118+
* @param string $singleId
119+
* @param int $level
120+
*
121+
* @return list<Membership>
122+
*/
123+
public function getInheritedExcludingCircles(string $singleId, int $level = 0): array {
124+
$qb = $this->getMembershipSelectSql();
125+
$qb->limitToCircleId($singleId);
126+
$qb->leftJoinCircleConfig(CoreQueryBuilder::MEMBERSHIPS);
127+
128+
$expr = $qb->expr();
129+
if ($level > 1) {
130+
$qb->andWhere(
131+
$expr->gte(
132+
CoreQueryBuilder::MEMBERSHIPS . '.level',
133+
$qb->createNamedParameter($level, IQueryBuilder::PARAM_INT)
134+
)
135+
);
136+
}
137+
$qb->innerJoin(
138+
CoreQueryBuilder::MEMBERSHIPS,
139+
CoreRequestBuilder::TABLE_MEMBER,
140+
CoreQueryBuilder::MEMBER,
141+
$expr->eq(CoreQueryBuilder::MEMBERSHIPS . '.single_id', CoreQueryBuilder::MEMBER . '.single_id')
142+
);
143+
$qb->andWhere(
144+
$expr->neq(
145+
CoreQueryBuilder::MEMBER . '.user_type',
146+
$qb->createNamedParameter(Member::TYPE_CIRCLE, IQueryBuilder::PARAM_INT)
147+
)
148+
);
149+
$qb->groupBy([
150+
CoreQueryBuilder::MEMBERSHIPS . '.circle_id',
151+
CoreQueryBuilder::MEMBERSHIPS . '.single_id'
152+
]);
153+
154+
return $this->getItemsFromRequest($qb);
155+
}
116156

117157
/**
118158
* @param string $singleId

lib/FederatedItems/CircleDestroy.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,15 @@ public function manage(FederatedEvent $event): void {
107107

108108
$this->eventService->circleDestroying($event);
109109

110+
$parentCirlces = $this->membershipService->getParentCircles($circle);
111+
110112
$this->circleRequest->delete($circle);
111113
$this->memberRequest->deleteAllFromCircle($circle);
112114
$this->membershipService->onUpdate($circle->getSingleId());
115+
116+
foreach ($parentCirlces as $parentCircle) {
117+
$this->membershipService->updatePopulation($parentCircle);
118+
}
113119
}
114120

115121

lib/Model/Circle.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ public function jsonSerialize(): array {
829829
'sanitizedName' => $this->getSanitizedName(),
830830
'source' => $this->getSource(),
831831
'population' => $this->getPopulation(),
832+
'populationInherited' => $this->getPopulationInherited(),
832833
'config' => $this->getConfig(),
833834
'description' => $this->getDescription(),
834835
'url' => $this->getUrl(),

lib/Service/MembershipService.php

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -388,23 +388,62 @@ private function getMembershipsFromList(array $list, string $circleId): Membersh
388388
throw new ItemNotFoundException();
389389
}
390390

391+
/**
392+
* Get all circles that contain a given circle as a member
393+
*
394+
* @param Circle $circle
395+
*
396+
* @return list<Circle>
397+
*/
398+
public function getParentCircles(Circle $circle): array {
399+
$memberships = $this->membershipRequest->getMemberships($circle->getSingleId());
400+
$parentCircles = [];
401+
foreach ($memberships as $membership) {
402+
$parentCircles[] = $this->circleRequest->getCircle($membership->getCircleId());
403+
}
404+
405+
return $parentCircles;
406+
}
391407

392408
/**
409+
* Update population counts for a given circle and all circles that contain it as a member
410+
*
393411
* @param Circle $circle
394412
*/
395413
public function updatePopulation(Circle $circle): void {
396-
$local = $inherited = 0;
397-
$memberships = $this->membershipRequest->getInherited($circle->getSingleId(), Member::LEVEL_MEMBER);
414+
$this->calculateAndSavePopulation($circle);
415+
416+
$parentCircles = $this->getParentCircles($circle);
417+
foreach ($parentCircles as $parentCircle) {
418+
$this->calculateAndSavePopulation($parentCircle);
419+
}
420+
}
421+
422+
/**
423+
* Calculate and save population counts for a given circle
424+
*
425+
* population: direct member count (excluding nested circles)
426+
* populationInherited: total member count (direct + inherited from nested circles)
427+
*
428+
* @param Circle $circle
429+
*/
430+
private function calculateAndSavePopulation(Circle $circle): void {
431+
$population = $populationInherited = 0;
432+
433+
$memberships = $this->membershipRequest->getInheritedExcludingCircles(
434+
$circle->getSingleId(),
435+
Member::LEVEL_MEMBER
436+
);
398437
foreach ($memberships as $membership) {
399-
$inherited++;
400-
if ($membership->getCircleId() === $circle->getSingleId()) {
401-
$local++;
438+
$populationInherited++;
439+
if ($membership->getInheritanceDepth() === 1) {
440+
$population++;
402441
}
403442
}
404443

405444
$settings = $circle->getSettings();
406-
$settings['population'] = $local;
407-
$settings['populationInherited'] = $inherited;
445+
$settings['population'] = $population;
446+
$settings['populationInherited'] = $populationInherited;
408447
$this->circleRequest->updateSettings($circle->setSettings($settings));
409448
}
410449
}

0 commit comments

Comments
 (0)