...
 
Commits (3)
......@@ -62,7 +62,7 @@ If you need to upgrade to a newer release cycle, check the release history for a
- equals() - returns true if the same enum value is passed
- scalarEquals() - returns true if passed scalar value is equal to current value
### Basic enumeration
### Simplest enumeration
```php
/**
......@@ -72,28 +72,64 @@ If you need to upgrade to a newer release cycle, check the release history for a
final class DayOfWeek extends \Grifart\Enum\Enum
{
use Grifart\Enum\AutoInstances;
private const MONDAY = 'monday';
private const TUESDAY = 'tuesday';
// ...
public function process(self $value): void { /* ... */ }
}
$monday = DayOfWeek::MONDAY();
$monday->process(DayOfWeek::TUESDAY());
function process(DayOfWeek $day): void { /* ... */ }
````
### Values with behaviour
This way conditions can be replaced by composition. [full code example](tests/Example/LoyaltyProgramExample/example.phpt)
```php
/**
* Type of offer expiration.
* - FIXED - expires for all member at once,
* after days set in offer type (counting from
* - ASSIGNMENT - expires after
*
* @method static ExpirationType ASSIGNMENT()
* @method static ExpirationType FIXED()
*/
abstract class ExpirationType extends \Grifart\Enum\Enum
{
protected const ASSIGNMENT = 'assignment';
protected const FIXED = 'fixed';
abstract public function computeExpiration(Offer $offer): \DateTimeImmutable;
protected static function provideInstances() : array {
return [
new class(self::ASSIGNMENT) extends ExpirationType {
public function computeExpiration(Offer $offer): \DateTimeImmutable {
return $offer->assignedAt()
->modify('+' . $offer->type()->daysValid() . ' days');
}
},
new class(self::FIXED) extends ExpirationType {
public function computeExpiration(Offer $offer): \DateTimeImmutable {
$beginDate = $offer->type()->beginDate();
\assert($beginDate !== NULL);
return $beginDate->modify('+' . $offer->type()->daysValid() . ' days');
}
},
];
}
}
````
### Migrating from class constants
### Migrating from class constants <small>[[source code](tests/Example/MigratingLegacyCode/readme.md)]</small>
This guide show how to migrate from classes with constants to `\Grifart\Enum` in few simple steps. [Continue to example](tests/Example/MigratingLegacyCode/readme.md)
### Adding behaviour to values
### Adding behaviour to values <small>[[source code](tests/Example/AddingBehaviourToEnum/readme.md)]</small>
This guide show how to slowly add behaviour to enum values. Step by step. [Continue to example](tests/Example/AddingBehaviourToEnum/readme.md)
### Complex showcase: order lifecycle tracking
### Complex showcase: order lifecycle tracking <small>[[source code](tests/Example/OrderState/readme.md)]</small>
This example contains 5 ways of implementing order state. [Continue to example](tests/Example/OrderState/readme.md).
......
<?php
declare(strict_types=1);
use Tester\Assert;
require __DIR__ . '/../bootstrap.php';
/**
......@@ -18,14 +20,14 @@ $val1 = Enum1::VALUE1();
$val2 = Enum1::VALUE2();
/** intentionally non-strict @noinspection TypeUnsafeComparisonInspection PhpNonStrictObjectEqualityInspection */
\Tester\Assert::true($val1 == Enum1::VALUE1());
Assert::true($val1 == Enum1::VALUE1());
/** intentionally non-strict @noinspection TypeUnsafeComparisonInspection PhpNonStrictObjectEqualityInspection */
\Tester\Assert::true($val2 == Enum1::VALUE2());
Assert::true($val2 == Enum1::VALUE2());
/** intentionally non-strict @noinspection TypeUnsafeComparisonInspection PhpNonStrictObjectEqualityInspection */
\Tester\Assert::true($val1 != Enum1::VALUE2());
Assert::true($val1 != Enum1::VALUE2());
/** intentionally non-strict @noinspection TypeUnsafeComparisonInspection PhpNonStrictObjectEqualityInspection */
\Tester\Assert::true($val2 != Enum1::VALUE1());
Assert::true($val2 != Enum1::VALUE1());
$switchResult = 0;
......@@ -40,4 +42,47 @@ switch ($val1) {
$switchResult = 3;
break;
}
\Tester\Assert::same(1, $switchResult);
Assert::same(1, $switchResult);
// Check enums are handled well in in_array() function
Assert::true(
in_array(Enum1::VALUE1(), [ Enum1::VALUE1(), 'no-match' ], true),
'List of enums contains item - strict check'
);
Assert::true(
in_array(Enum1::VALUE1(), [ Enum1::VALUE1(), 'no-match' ], false),
'List of enums contains item - loose check'
);
Assert::false(
in_array(Enum1::VALUE1(), [ Enum1::VALUE2(), 'no-match' ], true),
'List of enums doesnt contain item - strict check'
);
Assert::false(
in_array(Enum1::VALUE1(), [ Enum1::VALUE2(), 'no-match' ], false),
'List of enums doesnt contain item - loose check'
);
/**
* @method static Enum2 ONE()
* @method static Enum2 TWO()
* @method static Enum2 THREE()
*/
final class Enum2 extends \Grifart\Enum\Enum
{
use Grifart\Enum\AutoInstances;
protected const ONE = 'value1';
protected const TWO = 'value2';
protected const THREE = 'value3';
}
// array_intersect
$first_array = [Enum2::ONE(), Enum2::TWO()];
$second_array = [Enum2::TWO(), Enum2::THREE()];
Assert::equal([Enum2::TWO()], array_values(array_intersect($first_array, $second_array)));
Assert::equal([Enum2::TWO()], array_values(array_intersect($second_array, $first_array)));
Assert::equal($first_array, array_values(array_intersect($first_array, $first_array)));
<?php
/**
* example from loyalty program domain
* presented by Jimmy Bogard - https://vimeo.com/43598193
*/
namespace ValuesWithBehaviourExample;
require __DIR__ . '/../../bootstrap.php';
use Tester\Assert;
/**
* Type of offer - e.g. "Summer sale in Shop A"
*/
interface OfferType {
public function name(): string;
public function beginDate(): ?\DateTimeImmutable; // when offer starts
public function expirationType(): ExpirationType;
public function daysValid(): int;
}
/**
* Loyalty program member
*/
interface Member {
public function id(): int;
}
/**
* Each offer must be namely assigned to member
*/
interface Offer {
public function assignedAt(): \DateTimeImmutable; // when ticket is assigned to client
public function type(): OfferType;
public function assignedTo(): Member;
}
/**
* Type of offer expiration.
* - FIXED - expires for all member at once,
* after days set in offer type (counting from
* - ASSIGNMENT - expires after
*
* @method static ExpirationType ASSIGNMENT()
* @method static ExpirationType FIXED()
*/
abstract class ExpirationType extends \Grifart\Enum\Enum
{
protected const ASSIGNMENT = 'assignment';
protected const FIXED = 'fixed';
abstract public function computeExpiration(Offer $offer): \DateTimeImmutable;
protected static function provideInstances() : array {
return [
new class(self::ASSIGNMENT) extends ExpirationType {
public function computeExpiration(Offer $offer): \DateTimeImmutable {
return $offer->assignedAt()
->modify('+' . $offer->type()->daysValid() . ' days');
}
},
new class(self::FIXED) extends ExpirationType {
public function computeExpiration(Offer $offer): \DateTimeImmutable {
$beginDate = $offer->type()->beginDate();
\assert($beginDate !== NULL);
return $beginDate->modify('+' . $offer->type()->daysValid() . ' days');
}
},
];
}
}
// just checking if it compiles
Assert::type(ExpirationType::class, ExpirationType::ASSIGNMENT());
\ No newline at end of file