1: <?php
2: namespace NGS\Client;
3:
4: require_once(__DIR__.'/../Utils.php');
5: require_once(__DIR__.'/../Name.php');
6: require_once(__DIR__.'/RestHttp.php');
7: require_once(__DIR__.'/../Patterns/Repository.php');
8:
9: use NGS\Name;
10: use NGS\Patterns\AggregateRoot;
11: use NGS\Patterns\Repository;
12: use NGS\Utils;
13:
14: /**
15: * Proxy service to remote CRUD REST-like API.
16: * Single aggregate root instance can be used.
17: * New object instance will be returned when doing modifications.
18: * All commands are performed on a single aggregate root.
19: * Use {@see StandardProxy} when response is not required, or for bulk
20: * versions of CRUD commands.
21: * It is preferred to use domain patterns instead of this proxy service.
22: *
23: * @package NGS\Client
24: */
25: class CrudProxy
26: {
27: const CRUD_URI = 'Crud.svc';
28:
29: protected $http;
30:
31: protected static $instance;
32:
33: /**
34: * Create a new CrudProxy instance
35: *
36: * @param RestHttp $http RestHttp instance used for http request.
37: * Optionally specify an instance, otherwise use a singleton instance
38: */
39: public function __construct(RestHttp $http = null)
40: {
41: $this->http = $http !== null ? $http : RestHttp::instance();
42: }
43:
44: /**
45: * Gets singleton instance of Crud.svc proxy
46: *
47: * @return CrudProxy
48: */
49: public static function instance()
50: {
51: if(self::$instance === null)
52: self::$instance = new CrudProxy();
53: return self::$instance;
54: }
55:
56: /**
57: * Create (insert) a single aggregate root on the remote server.
58: * Created object will be returned with its identity
59: * and all calculated properties evaluated.
60: *
61: * @param AggregateRoot $aggregate
62: * @return AggregateRoot Persisted aggregate root
63: */
64: public function create(AggregateRoot $aggregate)
65: {
66: $class = get_class($aggregate);
67: $name = Name::full($class);
68: $response =
69: $this->http->sendRequest(
70: self::CRUD_URI.'/'.rawurlencode($name),
71: 'POST',
72: $aggregate->toJson(),
73: array(201));
74: return RestHttp::parseResult($response, $class);
75: }
76:
77: /**
78: * Modify existing aggregate root on the remote server.
79: * Aggregate root will be saved and all calculated properties evaluated.
80: *
81: * @param AggregateRoot $aggregate
82: * @return AggregateRoot Persisted aggregate root
83: */
84: public function update(AggregateRoot $aggregate)
85: {
86: $class = get_class($aggregate);
87: $name = Name::full($class);
88: $response =
89: $this->http->sendRequest(
90: self::CRUD_URI.'/'.rawurlencode($name).'?uri='.rawurlencode($aggregate->getURI()),
91: 'PUT',
92: $aggregate->toJson(),
93: array(200));
94: Repository::instance()->invalidate($class, $aggregate->URI);
95: return RestHttp::parseResult($response, $class);
96: }
97:
98: /**
99: * Delete existing aggregate root from the remote server.
100: * If possible, aggregate root will be deleted and it's instance
101: * will be provided.
102: *
103: * @param string $class
104: * @param string $uri
105: * @return AggregateRoot Deleted aggregate root
106: */
107: public function delete($class, $uri)
108: {
109: $name = Name::full($class);
110: $response =
111: $this->http->sendRequest(
112: self::CRUD_URI.'/'.rawurlencode($name).'?uri='.rawurlencode($uri),
113: 'DELETE',
114: null,
115: array(200));
116: Repository::instance()->invalidate($class, $uri);
117: return RestHttp::parseResult($response, $class);
118: }
119:
120: /**
121: * Get domain object from remote server using provided identity.
122: * If domain object is not found an exception will be thrown.
123: *
124: * @param string $class
125: * @param string $uri
126: * @return AggregateRoot Fetched aggregate root
127: */
128: public function read($class, $uri)
129: {
130: $name = Name::full($class);
131: $response =
132: $this->http->sendRequest(
133: self::CRUD_URI.'/'.rawurlencode($name).'?uri='.rawurlencode($uri),
134: 'GET',
135: null,
136: array(200));
137: return RestHttp::parseResult($response, $class);
138: }
139: }
140: