Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Merge pull request #11 from bhulsman/master
Browse files Browse the repository at this point in the history
Add generic collection support. Fixes #2
  • Loading branch information
brendt authored Oct 24, 2018
2 parents 3f57f79 + e27b5ba commit bacaace
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 1 deletion.
23 changes: 22 additions & 1 deletion src/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ protected function resolveTypeDefinition()
return;
}

preg_match('/\@var ([\w|\\\\]+)/', $docComment, $matches);
preg_match('/\@var ((?:(?:[\w|\\\\])+(?:\[\])?)+)/', $docComment, $matches);

if (! count($matches)) {
return;
Expand Down Expand Up @@ -108,6 +108,10 @@ protected function isValidType($value): bool

protected function assertTypeEquals(string $type, $value): bool
{
if (strpos($type, '[]') !== false) {
return $this->isValidGenericCollection($type, $value);
}

if ($type === 'mixed' && $value !== null) {
return true;
}
Expand All @@ -118,4 +122,21 @@ protected function assertTypeEquals(string $type, $value): bool

return gettype($value) === (self::$typeMapping[$type] ?? $type);
}

protected function isValidGenericCollection(string $type, $collection): bool
{
if (! is_array($collection)) {
return false;
}

$valueType = str_replace('[]', '', $type);

foreach ($collection as $value) {
if (! $this->assertTypeEquals($valueType, $value)) {
return false;
}
}

return true;
}
}
4 changes: 4 additions & 0 deletions src/ValueObjectError.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ public static function invalidType(Property $property, $value): ValueObjectError
$value = get_class($value);
}

if (is_array($value)) {
$value = 'array';
}

$expectedTypes = implode(', ', $property->getTypes());

return new self("Invalid type: expected {$property->getFqn()} to be of type {$expectedTypes}, instead got value `{$value}`.");
Expand Down
39 changes: 39 additions & 0 deletions src/ValueObjectException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace Spatie\ValueObject;

use Exception;

class ValueObjectException extends Exception
{
public static function unknownPublicProperty(string $name, string $className): ValueObjectException
{
return new self("Public property {$name} not found on {$className}");
}

public static function invalidType(
string $propertyName,
string $className,
string $expectedType,
$value
): ValueObjectException {
if ($value === null) {
$value = 'null';
}

if (is_object($value)) {
$value = get_class($value);
}

if (is_array($value)) {
$value = 'array';
}

return new self("Invalid type: expected {$className}::{$propertyName} to be of type {$expectedType}; instead got value `{$value}`.");
}

public static function uninitialisedProperty(string $name): ValueObjectException
{
return new self("Non-nullable property `{$name}` has not been initialised.");
}
}
7 changes: 7 additions & 0 deletions tests/TestClasses/OtherClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<?php

namespace Spatie\ValueObject\Tests\TestClasses;

class OtherClass
{
}
30 changes: 30 additions & 0 deletions tests/ValueObjectTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Spatie\ValueObject\ValueObject;
use Spatie\ValueObject\ValueObjectError;
use Spatie\ValueObject\Tests\TestClasses\DummyClass;
use Spatie\ValueObject\Tests\TestClasses\OtherClass;

class ValueObjectTest extends TestCase
{
Expand Down Expand Up @@ -151,6 +152,35 @@ public function classes_are_supported()
};
}

/** @test */
public function generic_collections_are_supported()
{
new class(['foo' => [new DummyClass()]]) extends ValueObject {
/** @var \Spatie\ValueObject\Tests\TestClasses\DummyClass[] */
public $foo;
};

$this->markTestSucceeded();

$this->expectException(ValueObjectError::class);

new class(['foo' => [new OtherClass()]]) extends ValueObject {
/** @var \Spatie\ValueObject\Tests\TestClasses\DummyClass[] */
public $foo;
};
}

/** @test */
public function an_exception_is_thrown_for_a_generic_collection_of_null()
{
$this->expectException(ValueObjectError::class);

new class(['foo' => [null]]) extends ValueObject {
/** @var string[] */
public $foo;
};
}

/** @test */
public function an_exception_is_thrown_when_property_was_not_initialised()
{
Expand Down

0 comments on commit bacaace

Please sign in to comment.