1: <?php
2: /**
3: * Generic resource class
4: *
5: * @author Yannick Huerre <dev@sheoak.fr>
6: * @copyright 2015 (c) Oasiswork
7: * @license https://opensource.org/licenses/MIT MIT
8: */
9:
10: namespace Crunchmail\Resources;
11:
12: use Crunchmail\Client;
13:
14: /**
15: * Generic resource class
16: */
17: class GenericResource
18: {
19: /**
20: * The client object
21: *
22: * @var Client
23: */
24: public $client;
25:
26: /**
27: * Path to resource
28: *
29: * @var string
30: */
31: protected $_path;
32:
33: /**
34: * Forced url to resource
35: *
36: * @var string
37: */
38: protected $_url;
39:
40: /**
41: * Applied filters
42: *
43: * @var array
44: */
45: private $_filters = [];
46:
47: /**
48: * Instanciate a new resource
49: *
50: * @param Client $client Client object
51: * @param string $path resource path
52: * @param string $url forced url
53: */
54: public function __construct(Client $client, $path, $url = '')
55: {
56: $this->client = $client;
57: $this->_path = $path;
58: $this->_url = empty($url) ? $this->client->mapPath($path) . '/' : $url;
59: }
60:
61: /**
62: * Return resource default path
63: *
64: * @return string
65: */
66: public function getPath()
67: {
68: return $this->_path;
69: }
70:
71: /**
72: * Registers request filters
73: *
74: * Ex: $client->messages->filter($filter)->get()
75: *
76: * @param array $filters
77: *
78: * @return Crunchmail\Resources\GenericResource
79: */
80: public function filter(array $filters)
81: {
82: $this->_filters = $filters;
83: return $this;
84: }
85:
86: /**
87: * Direct acces to a specific page (shortcut)
88: *
89: * @param int $page page number
90: *
91: * @return Crunchmail\Collection\GenericCollection
92: */
93: public function page($page)
94: {
95: $this->_filters['page'] = (int) $page;
96: return $this->get();
97: }
98:
99: /**
100: * Return the class name for collection, depending on resource path
101: *
102: * @return string
103: */
104: public function getCollectionClass()
105: {
106: return $this->getClass($this->_path, 'Collections', 'Collection');
107: }
108:
109: /**
110: * Map the resource name to the entity name by default we remove the
111: * trailing "s", but Client::$entities can contains special cases:
112: *
113: * @return string
114: */
115: public function getEntityName()
116: {
117: return !empty(Client::$entities[$this->_path]) ?
118: Client::$entities[$this->_path] :
119: preg_replace('/(s)$/', '', $this->_path);
120: }
121:
122: /**
123: * Return the class name for the entity, depending on resource path
124: *
125: * @return string
126: */
127: public function getEntityClass()
128: {
129: $path = $this->getEntityName();
130: return $this->getClass($path, 'Entities', 'Entity');
131: }
132:
133: /**
134: * Return the class name for the given type, group and suffix
135: *
136: * @param string $type class type
137: * @param string $group class group
138: * @param string $classSuffix class suffix
139: *
140: * @return string
141: */
142: private function getClass($type, $classGroup, $classSuffix)
143: {
144: $classPrefix = '\\Crunchmail\\' . $classGroup . '\\';
145: $className = ucfirst($type) . $classSuffix;
146:
147: if (!class_exists($classPrefix . $className))
148: {
149: $className = 'Generic' . $classSuffix;
150: }
151:
152: return $classPrefix . $className;
153: }
154:
155: /**
156: * Execute a client request and return an entity or a collection of
157: * entities
158: *
159: * @param string $method get, post, put…
160: * @param string $url forced url
161: * @param array $values data
162: * @param string $format json or multipart
163: *
164: * @return mixed
165: *
166: * message->get(url)
167: * message->put($values, 'multipart', url)
168: * message->post($values, $options=['url' => force, 'format' => 'json])
169: */
170: public function request($method, $url = null, $values = [], $format = 'json')
171: {
172: // forced url, or resource url
173: $url = is_null($url) ? $this->_url : $url;
174:
175: // guzzle call to the api, including the applied filters
176: // for the current collection
177: $data = $this->client->apiRequest(
178: $method, $url, $values, $this->_filters, $format
179: );
180:
181: // if the response has a results field, we create a collection
182: // otherwise we create an entity
183: $method = isset($data->results) ? 'getCollectionClass' : 'getEntityClass';
184: $class = $this->$method();
185:
186: return new $class($this, $data);
187: }
188:
189: /**
190: * Call the request() with the given method and arguments
191: *
192: * @param string $method method name
193: * @param array $args arguments (values, format)
194: * @param string $url force url
195: *
196: * @return mixed
197: */
198: public function callRequest($method, $args, $url = null)
199: {
200: if (!in_array($method, Client::$methods))
201: {
202: throw new \RuntimeException("Unknow method: $method");
203: }
204:
205: // url
206: array_unshift($args, $url);
207:
208: // method is the first parameter
209: array_unshift($args, $method);
210:
211: return call_user_func_array([$this, 'request'], $args);
212: }
213:
214: /**
215: * Get method is different that post, patch… because the first parameter
216: * is an url (or null)
217: *
218: * Ex: $message->get($url);
219: *
220: * @param string $url resource url
221: *
222: * @return mixed
223: */
224: public function get($url = null)
225: {
226: return $this->request('get', $url);
227: }
228:
229: /**
230: * Change resource content-type and returns it
231: *
232: * @param string $type Content Type
233: *
234: * @return GenericResource
235: */
236: public function contentType($type)
237: {
238: $that = clone $this;
239: $that->client->headers['Content-Type'] = $type;
240: return $that;
241: }
242:
243: /**
244: * Change ressource format to multipart and returns it
245: *
246: * @return GenericResource
247: */
248: public function multipart()
249: {
250: $that = clone $this;
251: $that->client->format = 'multipart';
252: return $that;
253: }
254:
255: /**
256: * Catch post, put… methods but no get
257: *
258: * Ex: $cli->messages->post($values)
259: * Ex: $cli->messages->post($values, 'multipart')
260: *
261: * @param string $name method name
262: * @param array $args arguments
263: *
264: * @return mixed
265: *
266: * @method mixed post() post(array $values, string $format='json') post values
267: * @method mixed put() put(array $values, string $format='json') put values
268: * @method mixed patch() patch(array $values, string $format='json') patch values
269: */
270: public function __call($method, $args)
271: {
272: return $this->callRequest($method, $args);
273: }
274:
275: /**
276: * Create a resource when accessing resource properties and returns it
277: *
278: * Example:
279: * $client->contacts->lists
280: *
281: * @param string $name property
282: *
283: * @return Crunchmail\Resources\GenericResource
284: */
285: public function __get($name)
286: {
287: $path = $this->_url . $this->client->mapPath($name) . '/';
288: return $this->$name = $this->client->createResource($name, $path);
289: }
290: }
291: