Skip to content

Commit

Permalink
IBX-4918: Moved Specification abstraction from AdminUi to Core (#196)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nattfarinn authored Jan 26, 2023
1 parent 4a9ec46 commit 8d555ce
Show file tree
Hide file tree
Showing 10 changed files with 283 additions and 0 deletions.
29 changes: 29 additions & 0 deletions src/contracts/Specification/AbstractSpecification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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\Specification;

abstract class AbstractSpecification implements SpecificationInterface
{
abstract public function isSatisfiedBy($item): bool;

public function and(SpecificationInterface $other): SpecificationInterface
{
return new AndSpecification($this, $other);
}

public function or(SpecificationInterface $other): SpecificationInterface
{
return new OrSpecification($this, $other);
}

public function not(): SpecificationInterface
{
return new NotSpecification($this);
}
}
27 changes: 27 additions & 0 deletions src/contracts/Specification/AndSpecification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?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\Specification;

final class AndSpecification extends AbstractSpecification
{
private SpecificationInterface $one;

private SpecificationInterface $two;

public function __construct(SpecificationInterface $one, SpecificationInterface $two)
{
$this->one = $one;
$this->two = $two;
}

public function isSatisfiedBy($item): bool
{
return $this->one->isSatisfiedBy($item) && $this->two->isSatisfiedBy($item);
}
}
24 changes: 24 additions & 0 deletions src/contracts/Specification/NotSpecification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?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\Specification;

final class NotSpecification extends AbstractSpecification
{
private SpecificationInterface $specification;

public function __construct(SpecificationInterface $specification)
{
$this->specification = $specification;
}

public function isSatisfiedBy($item): bool
{
return !$this->specification->isSatisfiedBy($item);
}
}
27 changes: 27 additions & 0 deletions src/contracts/Specification/OrSpecification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?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\Specification;

final class OrSpecification extends AbstractSpecification
{
private SpecificationInterface $one;

private SpecificationInterface $two;

public function __construct(SpecificationInterface $one, SpecificationInterface $two)
{
$this->one = $one;
$this->two = $two;
}

public function isSatisfiedBy($item): bool
{
return $this->one->isSatisfiedBy($item) || $this->two->isSatisfiedBy($item);
}
}
23 changes: 23 additions & 0 deletions src/contracts/Specification/SpecificationInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?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\Specification;

interface SpecificationInterface
{
/**
* @param mixed $item
*/
public function isSatisfiedBy($item): bool;

public function and(SpecificationInterface $other): SpecificationInterface;

public function or(SpecificationInterface $other): SpecificationInterface;

public function not(): SpecificationInterface;
}
49 changes: 49 additions & 0 deletions tests/lib/Specification/AbstractSpecificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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\Tests\Core\Specification;

class AbstractSpecificationTest extends BaseSpecificationTest
{
public function testSpecification(): void
{
$isStringSpecification = $this->getIsStringSpecification();
$isTestStringSpecification = $this->getIsTestStringSpecification();

self::assertTrue($isStringSpecification->isSatisfiedBy('test_string'));
self::assertFalse($isStringSpecification->isSatisfiedBy(1234));
}

public function testSpecificationAnd(): void
{
$isStringSpecification = $this->getIsStringSpecification();
$isTestStringSpecification = $this->getIsTestStringSpecification();

self::assertTrue($isStringSpecification->and($isTestStringSpecification)->isSatisfiedBy('test'));
self::assertFalse($isStringSpecification->and($isTestStringSpecification)->isSatisfiedBy('test_string'));
self::assertFalse($isStringSpecification->and($isTestStringSpecification)->isSatisfiedBy(1234));
}

public function testSpecificationOr(): void
{
$isStringSpecification = $this->getIsStringSpecification();
$isTestStringSpecification = $this->getIsTestStringSpecification();

self::assertTrue($isStringSpecification->or($isTestStringSpecification)->isSatisfiedBy('test'));
self::assertTrue($isStringSpecification->or($isTestStringSpecification)->isSatisfiedBy('test_string'));
self::assertFalse($isStringSpecification->or($isTestStringSpecification)->isSatisfiedBy(1234));
}

public function testSpecificationNot(): void
{
$isStringSpecification = $this->getIsStringSpecification();

self::assertFalse($isStringSpecification->not()->isSatisfiedBy('test_string'));
self::assertTrue($isStringSpecification->not()->isSatisfiedBy(1234));
}
}
24 changes: 24 additions & 0 deletions tests/lib/Specification/AndSpecificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace Ibexa\Tests\Core\Specification;

use Ibexa\Contracts\Core\Specification\AndSpecification;

class AndSpecificationTest extends BaseSpecificationTest
{
public function testAndSpecification(): void
{
$andSpecification = new AndSpecification(
$this->getIsStringSpecification(),
$this->getIsTestStringSpecification()
);

self::assertTrue($andSpecification->isSatisfiedBy('test'));
self::assertFalse($andSpecification->isSatisfiedBy('test_string'));
self::assertFalse($andSpecification->isSatisfiedBy(1234));
}
}
34 changes: 34 additions & 0 deletions tests/lib/Specification/BaseSpecificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace Ibexa\Tests\Core\Specification;

use Ibexa\Contracts\Core\Specification\AbstractSpecification;
use Ibexa\Contracts\Core\Specification\SpecificationInterface;
use PHPUnit\Framework\TestCase;

abstract class BaseSpecificationTest extends TestCase
{
protected function getIsStringSpecification(): SpecificationInterface
{
return new class() extends AbstractSpecification {
public function isSatisfiedBy($item): bool
{
return is_string($item);
}
};
}

protected function getIsTestStringSpecification(): SpecificationInterface
{
return new class() extends AbstractSpecification {
public function isSatisfiedBy($item): bool
{
return $item === 'test';
}
};
}
}
22 changes: 22 additions & 0 deletions tests/lib/Specification/NotSpecificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace Ibexa\Tests\Core\Specification;

use Ibexa\Contracts\Core\Specification\NotSpecification;

class NotSpecificationTest extends BaseSpecificationTest
{
public function testNotSpecification(): void
{
$andSpecification = new NotSpecification(
$this->getIsStringSpecification()
);

self::assertFalse($andSpecification->isSatisfiedBy('test'));
self::assertTrue($andSpecification->isSatisfiedBy(1234));
}
}
24 changes: 24 additions & 0 deletions tests/lib/Specification/OrSpecificationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/**
* @copyright Copyright (C) Ibexa AS. All rights reserved.
* @license For full copyright and license information view LICENSE file distributed with this source code.
*/
namespace Ibexa\Tests\Core\Specification;

use Ibexa\Contracts\Core\Specification\OrSpecification;

class OrSpecificationTest extends BaseSpecificationTest
{
public function testOrSpecification(): void
{
$andSpecification = new OrSpecification(
$this->getIsStringSpecification(),
$this->getIsTestStringSpecification()
);

self::assertTrue($andSpecification->isSatisfiedBy('test'));
self::assertTrue($andSpecification->isSatisfiedBy('test_string'));
self::assertFalse($andSpecification->isSatisfiedBy(1234));
}
}

0 comments on commit 8d555ce

Please sign in to comment.