diff --git a/src/Graph.php b/src/Graph.php index 8ce325ea..784e21fc 100644 --- a/src/Graph.php +++ b/src/Graph.php @@ -27,6 +27,11 @@ class Graph implements DualAggregate, AttributeAware protected $attributes = array(); + /** + * @var Group[] + */ + protected $groups = array(); + public function __construct() { $this->vertices = VerticesMap::factoryArrayReference($this->verticesStorage); @@ -466,4 +471,33 @@ public function getAttributeBag() { return new AttributeBagReference($this->attributes); } + + /** + * @param int|string $groupId + * @param bool $returnDuplicate + * @return Group + */ + public function createGroup($groupId, $returnDuplicate = false) + { + if ($returnDuplicate && isset($this->groups[$groupId])) { + return $this->groups[$groupId]; + } + + if (isset($this->groups[$groupId])) { + throw new OverflowException('Group already exists: ' . $groupId); + } + + $group = new Group($this, $groupId); + $this->groups[$groupId] = $group; + + return $group; + } + + /** + * @return array|Group[] + */ + public function getGroups() + { + return array_values($this->groups); + } } diff --git a/src/Group.php b/src/Group.php new file mode 100644 index 00000000..46a4c02c --- /dev/null +++ b/src/Group.php @@ -0,0 +1,79 @@ +id = $id; + $this->graph = $graph; + } + + public function getId() + { + return $this->id; + } + + public function getVerticesInGroup() + { + $thisGroup = $this; + + return array_values(array_filter( + $this->graph->getVertices()->getMap(), + function (Vertex $vertex) use ($thisGroup) { + return $vertex->getGroup() instanceof Group && $vertex->getGroup()->equals($thisGroup); + } + )); + } + + public function getAttribute($name, $default = null) + { + return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + } + + public function setAttribute($name, $value) + { + $this->attributes[$name] = $value; + } + + public function removeAttribute($name) + { + unset($this->attributes[$name]); + } + + public function getAttributeBag() + { + return new AttributeBagReference($this->attributes); + } + + public function __toString() + { + return (string)$this->id; + } + + public function equals(Group $other) + { + return $this->id === $other->id; + } +} diff --git a/src/Set/Vertices.php b/src/Set/Vertices.php index e11a1f06..790287c5 100644 --- a/src/Set/Vertices.php +++ b/src/Set/Vertices.php @@ -2,6 +2,7 @@ namespace Fhaculty\Graph\Set; +use Fhaculty\Graph\Group; use Fhaculty\Graph\Vertex; use Fhaculty\Graph\Exception\InvalidArgumentException; use Fhaculty\Graph\Exception\OutOfBoundsException; @@ -511,19 +512,16 @@ private function getCallback($callback) return $callback; } - static $methods = array( - self::ORDER_ID => 'getId', - self::ORDER_GROUP => 'getGroup' - ); - - if (!is_int($callback) || !isset($methods[$callback])) { - throw new InvalidArgumentException('Invalid callback given'); + if ($callback === self::ORDER_ID) { + return function (Vertex $vertex) { + return $vertex->getId(); + }; + } elseif ($callback === self::ORDER_GROUP) { + return function (Vertex $vertex) { + return $vertex->getGroup() instanceof Group ? $vertex->getGroup()->getId() : null; + }; } - $method = $methods[$callback]; - - return function (Vertex $vertex) use ($method) { - return $vertex->$method(); - }; + throw new InvalidArgumentException('Invalid callback given'); } } diff --git a/src/Vertex.php b/src/Vertex.php index 13e5b9cf..4a27596e 100644 --- a/src/Vertex.php +++ b/src/Vertex.php @@ -36,12 +36,13 @@ class Vertex implements EdgesAggregate, AttributeAware private $balance; /** - * group number + * group * - * @var int + * @var Group|null * @see Vertex::setGroup() + * @see Vertex::getGroup() */ - private $group = 0; + private $group; private $attributes = array(); @@ -90,26 +91,23 @@ public function setBalance($balance) } /** - * set group number of this vertex + * set group of this vertex * - * @param int $group + * @param Group|null $group * @return Vertex $this (chainable) * @throws InvalidArgumentException if group is not numeric */ - public function setGroup($group) + public function setGroup(Group $group = null) { - if (!is_int($group)) { - throw new InvalidArgumentException('Invalid group number'); - } $this->group = $group; return $this; } /** - * get group number + * get group * - * @return int + * @return Group|null */ public function getGroup() { diff --git a/tests/GraphTest.php b/tests/GraphTest.php index a8bea3bb..24f39af8 100644 --- a/tests/GraphTest.php +++ b/tests/GraphTest.php @@ -2,9 +2,11 @@ namespace Fhaculty\Graph\Tests; +use Fhaculty\Graph\Exception\OutOfBoundsException; use Fhaculty\Graph\Exception\OverflowException; use Fhaculty\Graph\Exception\InvalidArgumentException; use Fhaculty\Graph\Graph; +use Fhaculty\Graph\Group; use Fhaculty\Graph\Tests\Attribute\AbstractAttributeAwareTest; class GraphTest extends AbstractAttributeAwareTest @@ -17,7 +19,7 @@ public function setup() public function testVertexClone() { $graph = new Graph(); - $vertex = $graph->createVertex(123)->setBalance(10)->setGroup(4); + $vertex = $graph->createVertex(123)->setBalance(10)->setGroup($graph->createGroup(4)); $newgraph = new Graph(); $newvertex = $newgraph->createVertexClone($vertex); @@ -56,7 +58,7 @@ public function testGetVertexNonexistant() public function testGraphClone() { $graph = new Graph(); - $graph->createVertex(123)->setBalance(10)->setGroup(4); + $graph->createVertex(123)->setBalance(10)->setGroup($graph->createGroup(4)); $newgraph = $graph->createGraphClone(); @@ -391,6 +393,42 @@ public function testCreateGraphCloneVertices() $this->assertEquals(1, count($graphClone->getEdges())); } + public function testGetGroups() + { + $graph = new Graph(); + $graph->createGroup(1); + $graph->createGroup(2); + + $this->assertEquals( + array( + new Group($graph, 1), + new Group($graph, 2) + ), + $graph->getGroups() + ); + } + + public function testCreateGroupReturnDuplicate() + { + $graph = new Graph(); + $alreadyCreated = $graph->createGroup(1); + + $this->assertSame( + $alreadyCreated, + $graph->createGroup(1, true) + ); + } + + /** + * @expectedException OverflowException + */ + public function testCreateGroupAlreadyExists() + { + $graph = new Graph(); + $graph->createGroup(1); + $graph->createGroup(1); + } + protected function createAttributeAware() { return new Graph(); diff --git a/tests/GroupTest.php b/tests/GroupTest.php new file mode 100644 index 00000000..e3aff5b5 --- /dev/null +++ b/tests/GroupTest.php @@ -0,0 +1,77 @@ +assertSame(1, $group->getId()); + } + + public function testGroupIdCanBeAString() + { + $group = new Group(new Graph(), 'string'); + + $this->assertSame('string', $group->getId()); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testGroupIdCanNotBeSomethingElse() + { + new Group(new Graph(), null); + } + + public function testGroupEquals() + { + $group = new Group(new Graph(), 1); + + $this->assertTrue($group->equals(new Group(new Graph(), 1))); + } + + public function testGroupIsNotEqual() + { + $group = new Group(new Graph(), 1); + + $this->assertFalse($group->equals(new Group(new Graph(), 2))); + } + + public function testFindAllVerticesInGroup() + { + $graph = new Graph(); + $group1 = $graph->createGroup(1); + $vertex1 = $graph->createVertex(1)->setGroup($group1); + $vertex2 = $graph->createVertex(2)->setGroup($group1); + $group2 = $graph->createGroup(2); + $vertex3 = $graph->createVertex(3)->setGroup($group2); + + $this->assertEquals( + array( + $vertex1, + $vertex2 + ), + $group1->getVerticesInGroup() + ); + + $this->assertEquals( + array( + $vertex3 + ), + $group2->getVerticesInGroup() + ); + } + + protected function createAttributeAware() + { + return new Group(new Graph(), 1); + } +} diff --git a/tests/Set/BaseVerticesTest.php b/tests/Set/BaseVerticesTest.php index 06b0a3ac..df3761e0 100644 --- a/tests/Set/BaseVerticesTest.php +++ b/tests/Set/BaseVerticesTest.php @@ -198,26 +198,26 @@ public function returnTrue(Vertex $vertex) public function testOrderByGroup() { $graph = new Graph(); - $graph->createVertex()->setGroup(1); - $graph->createVertex()->setGroup(100); - $graph->createVertex()->setGroup(5); - $graph->createVertex()->setGroup(100); - $graph->createVertex()->setGroup(100); - $graph->createVertex()->setGroup(2); - $biggest = $graph->createVertex()->setGroup(200); + $graph->createVertex()->setGroup($graph->createGroup(1)); + $graph->createVertex()->setGroup($graph->createGroup(100)); + $graph->createVertex()->setGroup($graph->createGroup(5)); + $graph->createVertex()->setGroup($graph->createGroup(100, true)); + $graph->createVertex()->setGroup($graph->createGroup(100, true)); + $graph->createVertex()->setGroup($graph->createGroup(2)); + $biggest = $graph->createVertex()->setGroup($graph->createGroup(200)); $vertices = $graph->getVertices(); $verticesOrdered = $vertices->getVerticesOrder(Vertices::ORDER_GROUP); $this->assertInstanceOf('Fhaculty\Graph\Set\Vertices', $verticesOrdered); - $this->assertEquals(1, $verticesOrdered->getVertexFirst()->getGroup()); - $this->assertEquals(200, $verticesOrdered->getVertexLast()->getGroup()); + $this->assertEquals(1, $verticesOrdered->getVertexFirst()->getGroup()->getId()); + $this->assertEquals(200, $verticesOrdered->getVertexLast()->getGroup()->getId()); $this->assertSame($biggest, $verticesOrdered->getVertexLast()); $this->assertSame($biggest, $vertices->getVertexOrder(Vertices::ORDER_GROUP, true)); $sumgroups = function(Vertex $vertex) { - return $vertex->getGroup(); + return $vertex->getGroup()->getId(); }; $this->assertSame(508, $vertices->getSumCallback($sumgroups)); $this->assertSame(508, $verticesOrdered->getSumCallback($sumgroups)); diff --git a/tests/VertexTest.php b/tests/VertexTest.php index 69103e39..e0700b75 100644 --- a/tests/VertexTest.php +++ b/tests/VertexTest.php @@ -8,6 +8,16 @@ class VertexTest extends AbstractAttributeAwareTest { + /** + * @var Graph + */ + private $graph; + + /** + * @var Vertex + */ + private $vertex; + public function setUp() { $this->graph = new Graph(); @@ -91,16 +101,8 @@ public function testBalanceInvalid() public function testGroup() { - $this->vertex->setGroup(2); - $this->assertEquals(2, $this->vertex->getGroup()); - } - - /** - * @expectedException InvalidArgumentException - */ - public function testGroupInvalid() - { - $this->vertex->setGroup("3"); + $this->vertex->setGroup($this->graph->createGroup(2)); + $this->assertEquals(2, $this->vertex->getGroup()->getId()); } /**