diff options
author | Maxence Lange <maxence@artificial-owl.com> | 2022-11-10 15:46:06 +0300 |
---|---|---|
committer | Maxence Lange <maxence@artificial-owl.com> | 2022-11-10 15:51:56 +0300 |
commit | bfe262eba01ecd27a6999a09ee8360fa78fd5c3d (patch) | |
tree | a890927af3ec7709d475da9714fc4311177fd1e3 | |
parent | 5dc232a9a4ede25e8cbdf64f14a3a84cc3aaca32 (diff) |
improving probesenh/noid/adding-data-to-dataprobe
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
-rw-r--r-- | lib/Collaboration/v2/CollaboratorSearchPlugin.php | 21 | ||||
-rw-r--r-- | lib/Db/CircleRequest.php | 87 | ||||
-rw-r--r-- | lib/Db/CoreQueryBuilder.php | 74 | ||||
-rw-r--r-- | lib/Model/Probes/CircleProbe.php | 14 | ||||
-rw-r--r-- | lib/Model/Probes/MemberProbe.php | 18 | ||||
-rw-r--r-- | lib/Service/CircleService.php | 52 | ||||
-rw-r--r-- | lib/ShareByCircleProvider.php | 24 |
7 files changed, 208 insertions, 82 deletions
diff --git a/lib/Collaboration/v2/CollaboratorSearchPlugin.php b/lib/Collaboration/v2/CollaboratorSearchPlugin.php index cce2c517..4e734e1b 100644 --- a/lib/Collaboration/v2/CollaboratorSearchPlugin.php +++ b/lib/Collaboration/v2/CollaboratorSearchPlugin.php @@ -31,13 +31,14 @@ declare(strict_types=1); namespace OCA\Circles\Collaboration\v2; -use OCA\Circles\Tools\Traits\TNCLogger; use Exception; use OCA\Circles\AppInfo\Application; use OCA\Circles\Model\Circle; use OCA\Circles\Model\Probes\CircleProbe; +use OCA\Circles\Model\Probes\DataProbe; use OCA\Circles\Service\CircleService; use OCA\Circles\Service\FederatedUserService; +use OCA\Circles\Tools\Traits\TNCLogger; use OCP\Collaboration\Collaborators\ISearchPlugin; use OCP\Collaboration\Collaborators\ISearchResult; use OCP\Collaboration\Collaborators\SearchResultType; @@ -114,11 +115,21 @@ class CollaboratorSearchPlugin implements ISearchPlugin { ->filterSystemCircles() ->setItemsLimit($limit) ->setItemsOffset($offset) - ->setFilterCircle($filterCircle) - ->mustBeMember(!$fromFrontEnd) - ->filterConfig(Circle::CFG_ROOT, $fromFrontEnd); + ->setFilterCircle($filterCircle); + + // If from the OCS API, we use getCircles(), to get more complex result at the price of huge resource, + // if not (ie. share popup) we only need probeCircles() + if ($fromFrontEnd) { + $probe->mustBeMember(false) + ->filterConfig(Circle::CFG_ROOT, true); - $circles = $this->circleService->getCircles($probe); + $circles = $this->circleService->getCircles($probe); + } else { + $dataProbe = new DataProbe(); + $dataProbe->add(DataProbe::OWNER); + + $circles = $this->circleService->probeCircles($probe, $dataProbe); + } } catch (Exception $e) { return false; } diff --git a/lib/Db/CircleRequest.php b/lib/Db/CircleRequest.php index 0610e5ff..0896603f 100644 --- a/lib/Db/CircleRequest.php +++ b/lib/Db/CircleRequest.php @@ -191,7 +191,7 @@ class CircleRequest extends CircleRequestBuilder { $qb->limitToDirectMembership(CoreQueryBuilder::CIRCLE, $probe->getFilterMember()); } if ($probe->hasFilterCircle()) { - $qb->filterCircle($probe->getFilterCircle()); + $qb->filterCircleDetails($probe->getFilterCircle()); } if ($probe->hasFilterRemoteInstance()) { $qb->limitToRemoteInstance(CoreQueryBuilder::CIRCLE, $probe->getFilterRemoteInstance(), false); @@ -204,6 +204,33 @@ class CircleRequest extends CircleRequestBuilder { /** + * get data about single Circle. + * + * - CircleProbe is used to confirm the visibility of the targeted circle, + * - DataProbe is used to define the complexity of the data to be returned for each entry of the list + * + * @param string $singleId + * @param IFederatedUser|null $initiator + * @param CircleProbe $circleProbe + * @param DataProbe $dataProbe + * + * @return Circle + * @throws CircleNotFoundException + * @throws RequestBuilderException + */ + public function probeCircle( + string $singleId, + ?IFederatedUser $initiator, + CircleProbe $circleProbe, + DataProbe $dataProbe + ): Circle { + $qb = $this->buildProbeCircle($initiator, $circleProbe, $dataProbe); + $qb->limit('unique_id', $singleId); + + return $this->getItemFromRequest($qb); + } + + /** * get data about multiple Circles. * * - CircleProbe is used to define the list of circles to be returned by the method, @@ -221,30 +248,66 @@ class CircleRequest extends CircleRequestBuilder { CircleProbe $circleProbe, DataProbe $dataProbe ): array { + $qb = $this->buildProbeCircle($initiator, $circleProbe, $dataProbe); + + $qb->chunk($circleProbe->getItemsOffset(), $circleProbe->getItemsLimit()); + + return $this->getItemsFromRequest($qb); + } + + /** + * @param IFederatedUser|null $initiator + * @param CircleProbe $circleProbe + * @param DataProbe $dataProbe + * + * @return CoreQueryBuilder + * @throws RequestBuilderException + */ + private function buildProbeCircle( + ?IFederatedUser $initiator, + CircleProbe $circleProbe, + DataProbe $dataProbe + ): CoreQueryBuilder { $qb = $this->getCircleSelectSql(); - if (!$dataProbe->has(CoreQueryBuilder::MEMBERSHIPS)) { - $dataProbe->add(CoreQueryBuilder::MEMBERSHIPS); + if (!$dataProbe->has(DataProbe::MEMBERSHIPS)) { + $dataProbe->add(DataProbe::MEMBERSHIPS); } $qb->setSqlPath(CoreQueryBuilder::CIRCLE, $dataProbe->getPath()) - ->setOptions([CoreQueryBuilder::CIRCLE], $circleProbe->getAsOptions()); + ->setOptions([CoreQueryBuilder::CIRCLE], $circleProbe->getAsOptions()) + ->filterCircles(CoreQueryBuilder::CIRCLE, $circleProbe); + + if ($circleProbe->hasFilterCircle()) { + $qb->filterCircleDetails($circleProbe->getFilterCircle()); + } $qb->leftJoinOwner(CoreQueryBuilder::CIRCLE); + $qb->innerJoinMembership($circleProbe, CoreQueryBuilder::CIRCLE); - $qb->innerJoinMembership(CoreQueryBuilder::CIRCLE); + $aliasMembership = $qb->generateAlias(CoreQueryBuilder::CIRCLE, CoreQueryBuilder::MEMBERSHIPS); - if (!is_null($initiator)) { - $qb->limitToSingleId( - $initiator->getSingleId(), $qb->generateAlias( - CoreQueryBuilder::CIRCLE, - CoreQueryBuilder::MEMBERSHIPS - ) + $limit = $qb->expr()->orX(); + if (is_null($initiator)) { + // to get unique result, enforce a limit on level=owner + $limit->add($qb->exprLimitInt('level', Member::LEVEL_OWNER, $aliasMembership)); + } else { + $limit->add( + $qb->exprLimit( + 'single_id', + $initiator->getSingleId(), + $aliasMembership + ) ); + $qb->completeProbeWithInitiator(CoreQueryBuilder::CIRCLE, 'single_id', $aliasMembership); } - return $this->getItemsFromRequest($qb); + $qb->andWhere($limit); + $qb->resetSqlPath(); + + return $qb; } + /** * @param array $circleIds * diff --git a/lib/Db/CoreQueryBuilder.php b/lib/Db/CoreQueryBuilder.php index a09bba62..9fbea8eb 100644 --- a/lib/Db/CoreQueryBuilder.php +++ b/lib/Db/CoreQueryBuilder.php @@ -382,9 +382,11 @@ class CoreQueryBuilder extends ExtendedQueryBuilder { /** + * filter result on details (ie. displayName, Description, ...) + * * @param Circle $circle */ - public function filterCircle(Circle $circle): void { + public function filterCircleDetails(Circle $circle): void { if ($this->getType() !== QueryBuilder::SELECT) { return; } @@ -885,12 +887,15 @@ class CoreQueryBuilder extends ExtendedQueryBuilder { /** + * @param CircleProbe $probe * @param string $alias * @param string $field - * - * @throws RequestBuilderException */ - public function innerJoinMembership(string $alias, string $field = 'unique_id'): void { + public function innerJoinMembership( + CircleProbe $probe, + string $alias, + string $field = 'unique_id' + ): void { if ($this->getType() !== QueryBuilder::SELECT) { return; } @@ -902,22 +907,17 @@ class CoreQueryBuilder extends ExtendedQueryBuilder { } $expr = $this->expr(); - $this->generateMembershipSelectAlias($aliasMembership) - ->innerJoin( - $alias, CoreRequestBuilder::TABLE_MEMBERSHIP, $aliasMembership, - $expr->andX( - $expr->eq($aliasMembership . '.circle_id', $alias . '.' . $field), - $expr->eq( - $aliasMembership . '.level', - $this->createNamedParameter( - Member::LEVEL_MEMBER, - self::PARAM_INT - ) - ) - ) - ); -// $this->leftJoinBasedOn($aliasMember); + $on = $expr->andX($expr->eq($aliasMembership . '.circle_id', $alias . '.' . $field)); + + // limit on membership level if requested + $minLevel = $probe->getMinimumLevel(); + if ($minLevel > Member::LEVEL_MEMBER) { + $on->add($this->exprGt('level', $minLevel, true, $aliasMembership)); + } + + $this->generateMembershipSelectAlias($aliasMembership) + ->innerJoin($alias, CoreRequestBuilder::TABLE_MEMBERSHIP, $aliasMembership, $on); } @@ -1319,6 +1319,36 @@ class CoreQueryBuilder extends ExtendedQueryBuilder { } + public function completeProbeWithInitiator( + string $alias, + string $field = 'single_id', + string $helperAlias = '' + ): void { + if ($this->getType() !== QueryBuilder::SELECT) { + return; + } + + try { + $aliasInitiator = $this->generateAlias($alias, self::INITIATOR); + } catch (RequestBuilderException $e) { + return; + } + + $helperAlias = ($helperAlias === '') ? $alias : $helperAlias; + + $expr = $this->expr(); + $this->generateMemberSelectAlias($aliasInitiator) + ->leftJoin( + $alias, CoreRequestBuilder::TABLE_MEMBER, $aliasInitiator, + $expr->andX( + $expr->eq($aliasInitiator . '.circle_id', $helperAlias . '.' . $field), + $this->exprLimitInt('level', Member::LEVEL_OWNER, $aliasInitiator) + ) + ); +// +// $this->leftJoinBasedOn($aliasInitiator); + } + /** * @param string $alias * @@ -1768,4 +1798,10 @@ class CoreQueryBuilder extends ExtendedQueryBuilder { return $this; } + + public function resetSqlPath(): self { + $this->sqlPath = []; + + return $this; + } } diff --git a/lib/Model/Probes/CircleProbe.php b/lib/Model/Probes/CircleProbe.php index 11006792..7aadd424 100644 --- a/lib/Model/Probes/CircleProbe.php +++ b/lib/Model/Probes/CircleProbe.php @@ -41,16 +41,10 @@ use OCA\Circles\Model\Circle; class CircleProbe extends MemberProbe { - /** @var int */ - private $include = 0; - - /** @var int */ - private $filter = Circle::CFG_SINGLE; - - /** @var bool */ - private $includeNonVisible = false; - /** @var bool */ - private $visitSingleCircles = false; + private int $include = 0; + private int $filter = Circle::CFG_SINGLE; + private bool $includeNonVisible = false; + private bool $visitSingleCircles = false; /** diff --git a/lib/Model/Probes/MemberProbe.php b/lib/Model/Probes/MemberProbe.php index e2cdb1bb..f391f604 100644 --- a/lib/Model/Probes/MemberProbe.php +++ b/lib/Model/Probes/MemberProbe.php @@ -39,20 +39,10 @@ use OCA\Circles\Model\Member; * @package OCA\Circles\Model\Probes */ class MemberProbe extends BasicProbe { - - - /** @var int */ - private $minimumLevel = Member::LEVEL_NONE; - - /** @var bool */ - private $emulateVisitor = false; - - /** @var bool */ - private $requestingMembership = false; - - /** @var bool */ - private $initiatorDirectMember = false; - + private int $minimumLevel = Member::LEVEL_NONE; + private bool $emulateVisitor = false; + private bool $requestingMembership = false; + private bool $initiatorDirectMember = false; /** * allow the initiator as a requesting member diff --git a/lib/Service/CircleService.php b/lib/Service/CircleService.php index 7d0a241b..b4e023e8 100644 --- a/lib/Service/CircleService.php +++ b/lib/Service/CircleService.php @@ -735,13 +735,17 @@ class CircleService { return $this->l10n->t('Personal Circle'); } - return $this->l10n->t( - '%s owned by %s', - [ - $source, - $this->configService->displayFederatedUser($circle->getOwner(), true) - ] - ); + if ($circle->hasOwner()) { + return $this->l10n->t( + '%s owned by %s', + [ + $source, + $this->configService->displayFederatedUser($circle->getOwner(), true) + ] + ); + } + + return $source; } /** @@ -760,6 +764,40 @@ class CircleService { /** + * @param string $circleId + * @param CircleProbe $circleProbe + * @param DataProbe|null $dataProbe + * + * @return Circle + * @throws InitiatorNotFoundException + * @throws RequestBuilderException + * @throws CircleNotFoundException + */ + public function probeCircle( + string $circleId, + ?CircleProbe $circleProbe = null, + ?DataProbe $dataProbe = null + ): Circle { + $this->federatedUserService->mustHaveCurrentUser(); + + if (is_null($circleProbe)) { + $circleProbe = new CircleProbe(); + $circleProbe->includeSystemCircles(); + } + + if (is_null($dataProbe)) { + $dataProbe = new DataProbe(); + } + + return $this->circleRequest->probeCircle( + $circleId, + $this->federatedUserService->getCurrentUser(), + $circleProbe, + $dataProbe + ); + } + + /** * @param CircleProbe $circleProbe * @param DataProbe|null $dataProbe * diff --git a/lib/ShareByCircleProvider.php b/lib/ShareByCircleProvider.php index 844fdc7b..d3582580 100644 --- a/lib/ShareByCircleProvider.php +++ b/lib/ShareByCircleProvider.php @@ -58,8 +58,8 @@ use OCA\Circles\Exceptions\UnknownRemoteException; use OCA\Circles\FederatedItems\Files\FileShare; use OCA\Circles\FederatedItems\Files\FileUnshare; use OCA\Circles\Model\Federated\FederatedEvent; -use OCA\Circles\Model\Helpers\MemberHelper; use OCA\Circles\Model\Probes\CircleProbe; +use OCA\Circles\Model\Probes\DataProbe; use OCA\Circles\Model\ShareWrapper; use OCA\Circles\Service\CircleService; use OCA\Circles\Service\EventService; @@ -217,21 +217,18 @@ class ShareByCircleProvider implements IShareProvider { } $this->federatedUserService->initCurrentUser(); - $circle = $this->circleService->getCircle($share->getSharedWith()); - $owner = $circle->getInitiator(); - - $initiatorHelper = new MemberHelper($owner); - $initiatorHelper->mustBeMember(); + $circleProbe = new CircleProbe(); + $dataProbe = new DataProbe(); + $dataProbe->add(DataProbe::OWNER) + ->add(DataProbe::INITIATOR, [DataProbe::BASED_ON]); + $circle = $this->circleService->probeCircle($share->getSharedWith(), $circleProbe, $dataProbe); $share->setToken($this->token(15)); + $owner = $circle->getInitiator(); $this->shareWrapperService->save($share); try { - $wrappedShare = $this->shareWrapperService->getShareById( - (int)$share->getId(), - $this->federatedUserService->getCurrentUser() - ); - + $wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId()); $wrappedShare->setOwner($owner); } catch (ShareWrapperNotFoundException $e) { throw new ShareNotFound(); @@ -291,10 +288,7 @@ class ShareByCircleProvider implements IShareProvider { $this->federatedUserService->initCurrentUser(); try { - $wrappedShare = $this->shareWrapperService->getShareById( - (int)$share->getId(), - $this->federatedUserService->getCurrentUser() - ); + $wrappedShare = $this->shareWrapperService->getShareById((int)$share->getId()); } catch (ShareWrapperNotFoundException $e) { return; } |