1: <?php
2: namespace NGS\Patterns;
3:
4: require_once(__DIR__.'/Identifiable.php');
5: require_once(__DIR__.'/../Client/CrudProxy.php');
6:
7: use NGS\Client\CrudProxy;
8: use NGS\Client\DomainProxy;
9: use NGS\Patterns\Identifiable;
10: use NGS\Patterns\AggregateDomainEvent;
11:
12: /**
13: * Aggregate root is a meaningful object in the domain.
14: * It can be viewed as a write boundary for entities and value objects
15: * that will maintain write consistency.
16: * <p>
17: * Usually it represents a single table, but can span several tables
18: * and can be used like document or similar data structure.
19: * Since every aggregate is also an entity, it has a unique
20: * identification represented by its URI.
21: * <p>
22: * DSL example:
23: * <blockquote><pre>
24: * module Todo {
25: * aggregate Task {
26: * timestamp startedAt;
27: * timestamp? finishedAt;
28: * int? priority;
29: * List<Note> notes;
30: * }
31: * value Note {
32: * date entered;
33: * string remark;
34: * }
35: * }
36: * </pre></blockquote>
37: */
38: abstract class AggregateRoot extends Identifiable
39: {
40: /**
41: * Persists object on the server.
42: * Insert is performed if object's URI is not set, otherwise, if URI is set,
43: * current object is updated.
44: *
45: * @return AggregateRoot Persisted object
46: */
47: public function persist()
48: {
49: return $this->getURI() === null
50: ? CrudProxy::instance()->create($this)
51: : CrudProxy::instance()->update($this);
52: }
53:
54: /**
55: * Deletes object from the server
56: *
57: * @return AggregateRoot Deleted object
58: * @throws \LogicException If object instance was created, but not persisted
59: */
60: public function delete()
61: {
62: if ($this->URI===null) {
63: throw new \LogicException('Cannot delete instance of root "'.get_class($this).'" because it\'s URI was null.');
64: }
65: return CrudProxy::instance()->delete(get_called_class(), $this->URI);
66: }
67:
68: /**
69: * Applies aggregate domain event on object
70: *
71: * @param \NGS\Patterns\AggregateDomainEvent $event
72: * @return AggregateRoot New instance of AggregateRoot with updated values
73: * after applying event
74: * @throws \LogicException If object instance was created, but not persisted
75: */
76: public function apply(AggregateDomainEvent $event)
77: {
78: $proxy = DomainProxy::instance();
79: if($this->URI===null) {
80: throw new \LogicException('Event '.get_class($event).' cannot be applied on instance of root "'.get_class($this).'" because it\'s URI was null.');
81: }
82: return $proxy->submitAggregateEvent($event, $this->URI);
83: }
84: }
85: