Skip to content
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

IBX-6827: Aggregation API improvements #287

Merged
merged 8 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class DateMetadataRangeAggregation extends AbstractRangeAggregation
{
public const MODIFIED = 'modified';
Expand All @@ -27,6 +30,19 @@ public function getType(): string
{
return $this->type;
}

public static function fromGenerator(
string $name,
string $type,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new self($name, $type, $ranges);
}
}

class_alias(DateMetadataRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\DateMetadataRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Field;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class DateRangeAggregation extends AbstractFieldRangeAggregation
{
public static function fromGenerator(
string $name,
string $contentTypeIdentifier,
string $fieldDefinitionIdentifier,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new self($name, $contentTypeIdentifier, $fieldDefinitionIdentifier, $ranges);
}
}

class_alias(DateRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\Field\DateRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Field;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class DateTimeRangeAggregation extends AbstractFieldRangeAggregation
{
public static function fromGenerator(
string $name,
string $contentTypeIdentifier,
string $fieldDefinitionIdentifier,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new self($name, $contentTypeIdentifier, $fieldDefinitionIdentifier, $ranges);
}
}

class_alias(DateTimeRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\Field\DateTimeRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Field;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class FloatRangeAggregation extends AbstractFieldRangeAggregation
{
public static function fromGenerator(
string $name,
string $contentTypeIdentifier,
string $fieldDefinitionIdentifier,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new self($name, $contentTypeIdentifier, $fieldDefinitionIdentifier, $ranges);
}
}

class_alias(FloatRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\Field\FloatRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Field;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class IntegerRangeAggregation extends AbstractFieldRangeAggregation
{
public static function fromGenerator(
string $name,
string $contentTypeIdentifier,
string $fieldDefinitionIdentifier,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new static($name, $contentTypeIdentifier, $fieldDefinitionIdentifier, $ranges);
}
}

class_alias(IntegerRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\Field\IntegerRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,24 @@

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Field;

use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges\RangesGeneratorInterface;
use Traversable;

final class TimeRangeAggregation extends AbstractFieldRangeAggregation
{
public static function fromGenerator(
string $name,
string $contentTypeIdentifier,
string $fieldDefinitionIdentifier,
RangesGeneratorInterface $generator
): self {
$ranges = $generator->generate();
if ($ranges instanceof Traversable) {
$ranges = iterator_to_array($ranges);
}

return new self($name, $contentTypeIdentifier, $fieldDefinitionIdentifier, $ranges);
}
}

class_alias(TimeRangeAggregation::class, 'eZ\Publish\API\Repository\Values\Content\Query\Aggregation\Field\TimeRangeAggregation');
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@

final class Range extends ValueObject
{
public const INF = null;

/**
* Beginning of the range (included).
*
Expand All @@ -27,12 +29,15 @@ final class Range extends ValueObject
*/
private $to;

public function __construct($from, $to)
private ?string $label;

public function __construct($from, $to, ?string $label = null)
{
parent::__construct();

$this->from = $from;
$this->to = $to;
$this->label = $label;
}

public function getFrom()
Expand All @@ -45,15 +50,39 @@ public function getTo()
return $this->to;
}

public function getLabel(): ?string
{
return $this->label;
}

public function setLabel(?string $label): void
{
$this->label = $label;
}

public function __toString(): string
{
if ($this->label !== null) {
return sprintf(
'%s:[%s;%s)',
$this->label,
$this->getRangeValueAsString($this->from),
$this->getRangeValueAsString($this->to)
);
}

return sprintf(
'[%s;%s)',
$this->getRangeValueAsString($this->from),
$this->getRangeValueAsString($this->to)
);
}

public function equalsTo(Range $value): bool
{
return $this->from == $value->from && $this->to == $value->to;
}

private function getRangeValueAsString($value): string
{
if ($value === null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
declare(strict_types=1);

namespace Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Ranges;

use DateInterval;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range;

final class DateTimeStepRangesGenerator implements RangesGeneratorInterface
{
private DateTimeInterface $start;

private DateTimeInterface $end;

private DateInterval $step;

private bool $isLeftOpen = true;

private bool $isRightOpen = true;

public function __construct(DateTimeInterface $start, DateTimeInterface $end)
{
$this->start = $start;
$this->end = $end;
$this->step = new DateInterval('P1D');
}

public function getStart(): DateTimeInterface
{
return $this->start;
}

public function setStart(DateTimeInterface $start): self
{
$this->start = $start;

return $this;
}

public function getEnd(): DateTimeInterface
{
return $this->end;
}

public function setEnd(DateTimeInterface $end): self
{
$this->end = $end;

return $this;
}

public function getStep(): DateInterval
{
return $this->step;
}

public function setStep(DateInterval $step): self
{
$this->step = $step;

return $this;
}

public function isLeftOpen(): bool
{
return $this->isLeftOpen;
}

public function setLeftOpen(bool $isLeftOpen): void
{
$this->isLeftOpen = $isLeftOpen;
}

public function isRightOpen(): bool
{
return $this->isRightOpen;
}

public function setRightOpen(bool $isRightOpen): self
{
$this->isRightOpen = $isRightOpen;

return $this;
}

/**
* @return \Ibexa\Contracts\Core\Repository\Values\Content\Query\Aggregation\Range[]
*/
public function generate(): array
{
if ($this->start == $this->end && $this->isLeftOpen && $this->isRightOpen) {
adamwojs marked this conversation as resolved.
Show resolved Hide resolved
return [
new Range(Range::INF, Range::INF),
];
}

$ranges = [];

if ($this->isLeftOpen) {
$ranges[] = Range::ofDateTime(Range::INF, $this->start);
}

/** @var \DateTimeImmutable $current */
$current = $this->start;
if ($current instanceof DateTime) {
$current = DateTimeImmutable::createFromMutable($current);
}

while ($current < $this->end) {
$next = $current->add($this->step);
$ranges[] = Range::ofDateTime($current, $next);
$current = $next;
}

if ($this->isRightOpen) {
$ranges[] = Range::ofDateTime($this->end, Range::INF);
}

return $ranges;
}
}
Loading
Loading