Completed
Push — master ( cd5eb9...af944c )
by Aimeos
02:24
created

Base::getErrorDetails()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 29
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 29
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 9
nc 4
nop 2
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2017
6
 * @package Client
7
 * @subpackage JsonApi
8
 */
9
10
11
namespace Aimeos\Client\JsonApi;
12
13
use Psr\Http\Message\ResponseInterface;
14
use Psr\Http\Message\ServerRequestInterface;
15
16
17
/**
18
 * JSON API common client
19
 *
20
 * @package Client
21
 * @subpackage JsonApi
22
 */
23
abstract class Base
24
{
25
	private $view;
26
	private $context;
27
	private $templatePaths;
28
	private $path;
29
30
31
	/**
32
	 * Initializes the client
33
	 *
34
	 * @param \Aimeos\MShop\Context\Item\Iface $context MShop context object
35
	 * @param \Aimeos\MW\View\Iface $view View object
36
	 * @param array $templatePaths List of file system paths where the templates are stored
37
	 * @param string $path Name of the client separated by slashes, e.g "catalog/lists"
38
	 */
39
	public function __construct( \Aimeos\MShop\Context\Item\Iface $context, \Aimeos\MW\View\Iface $view, array $templatePaths, $path )
40
	{
41
		$this->view = $view;
42
		$this->context = $context;
43
		$this->templatePaths = $templatePaths;
44
		$this->path = $path;
45
	}
46
47
48
	/**
49
	 * Catch unknown methods
50
	 *
51
	 * @param string $name Name of the method
52
	 * @param array $param List of method parameter
53
	 * @throws \Aimeos\Client\JsonApi\Exception If method call failed
54
	 */
55
	public function __call( $name, array $param )
56
	{
57
		throw new \Aimeos\Client\JsonApi\Exception( sprintf( 'Unable to call method "%1$s"', $name ) );
58
	}
59
60
61
	/**
62
	 * Deletes the resource or the resource list
63
	 *
64
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
65
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
66
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
67
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
68
	 */
69
	public function delete( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
70
	{
71
		return $this->defaultAction( $request, $response );
72
	}
73
74
75
	/**
76
	 * Retrieves the resource or the resource list
77
	 *
78
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
79
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
80
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
81
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
82
	 */
83
	public function get( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
84
	{
85
		return $this->defaultAction( $request, $response );
86
	}
87
88
89
	/**
90
	 * Updates the resource or the resource list partitially
91
	 *
92
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
93
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
94
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
95
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
96
	 */
97
	public function patch( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
98
	{
99
		return $this->defaultAction( $request, $response );
100
	}
101
102
103
	/**
104
	 * Creates or updates the resource or the resource list
105
	 *
106
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
107
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
108
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
109
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
110
	 */
111
	public function post( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
112
	{
113
		return $this->defaultAction( $request, $response );
114
	}
115
116
117
	/**
118
	 * Creates or updates the resource or the resource list
119
	 *
120
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
121
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
122
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
123
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
124
	 */
125
	public function put( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
126
	{
127
		return $this->defaultAction( $request, $response );
128
	}
129
130
131
	/**
132
	 * Creates or updates the resource or the resource list
133
	 *
134
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
135
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
136
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
137
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
138
	 */
139
	public function options( ServerRequestInterface $request, ResponseInterface $response, $prefix = null )
140
	{
141
		return $this->defaultAction( $request, $response );
142
	}
143
144
145
	/**
146
	 * Returns the default response for the resource
147
	 *
148
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
149
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
150
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
151
	 */
152
	protected function defaultAction( ServerRequestInterface $request, ResponseInterface $response )
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
153
	{
154
		$status = 403;
155
		$view = $this->getView();
156
157
		$view->errors = array( array(
158
			'title' => $this->getContext()->getI18n()->dt( 'client/jsonapi', 'Not allowed for this resource' ),
159
		) );
160
161
		/** client/jsonapi/standard/template-error
162
		 * Relative path to the default JSON API template
163
		 *
164
		 * The template file contains the code and processing instructions
165
		 * to generate the result shown in the JSON API body. The
166
		 * configuration string is the path to the template file relative
167
		 * to the templates directory (usually in client/jsonapi/templates).
168
		 *
169
		 * You can overwrite the template file configuration in extensions and
170
		 * provide alternative templates. These alternative templates should be
171
		 * named like the default one but with the string "standard" replaced by
172
		 * an unique name. You may use the name of your project for this. If
173
		 * you've implemented an alternative client class as well, "standard"
174
		 * should be replaced by the name of the new class.
175
		 *
176
		 * @param string Relative path to the template creating the body for the JSON API response
177
		 * @since 2017.02
178
		 * @category Developer
179
		 * @see client/jsonapi/standard/template-delete
180
		 * @see client/jsonapi/standard/template-patch
181
		 * @see client/jsonapi/standard/template-post
182
		 * @see client/jsonapi/standard/template-get
183
		 * @see client/jsonapi/standard/template-options
184
		 */
185
		$tplconf = 'client/jsonapi/standard/template-error';
186
		$default = 'error-standard.php';
187
188
		$body = $view->render( $view->config( $tplconf, $default ) );
189
190
		return $response->withHeader( 'Content-Type', 'application/vnd.api+json' )
191
			->withBody( $view->response()->createStreamFromString( $body ) )
192
			->withStatus( $status );
193
	}
194
195
196
	/**
197
	 * Returns the context item object
198
	 *
199
	 * @return \Aimeos\MShop\Context\Item\Iface Context object
200
	 */
201
	protected function getContext()
202
	{
203
		return $this->context;
204
	}
205
206
207
	/**
208
	 * Returns the translated title and the details of the error
209
	 *
210
	 * @param \Exception $e Thrown exception
211
	 * @param string|null $domain Translation domain
212
	 * @return array Associative list with "title" and "detail" key (if debug config is enabled)
213
	 */
214
	protected function getErrorDetails( \Exception $e, $domain = null )
215
	{
216
		$details = [];
217
218
		if( $domain !== null ) {
219
			$details['title'] = $this->context->getI18n()->dt( $domain, $e->getMessage() );
220
		} else {
221
			$details['title'] = $e->getMessage();
222
		}
223
224
		/** client/jsonapi/debug
225
		 * Send debug information withing responses to clients if an error occurrs
226
		 *
227
		 * By default, the Aimeos client JSON REST API won't send any details
228
		 * besides the error message to the client if an error occurred. This
229
		 * prevents leaking sensitive information to attackers. For debugging
230
		 * your requests it's helpful to see the stack strace. If you set this
231
		 * configuration option to true, the stack trace will be returned too.
232
		 *
233
		 * @param boolean True to return the stack trace in JSON response, false for error message only
234
		 * @since 2017.07
235
		 * @category Developer
236
		 */
237
		if( $this->context->getConfig()->get( 'client/jsonapi/debug', false ) == true ) {
238
			$details['detail'] = $e->getTraceAsString();
239
		}
240
241
		return [$details]; // jsonapi.org requires a list of error objects
242
	}
243
244
245
	/**
246
	 * Returns the path to the client
247
	 *
248
	 * @return string Client path, e.g. "product/property"
249
	 */
250
	protected function getPath()
251
	{
252
		return $this->path;
253
	}
254
255
256
	/**
257
	 * Returns the paths to the template files
258
	 *
259
	 * @return array List of file system paths
260
	 */
261
	protected function getTemplatePaths()
262
	{
263
		return $this->templatePaths;
264
	}
265
266
267
	/**
268
	 * Returns the view object
269
	 *
270
	 * @return \Aimeos\MW\View\Iface View object
271
	 */
272
	protected function getView()
273
	{
274
		return $this->view;
275
	}
276
277
278
	/**
279
	 * Initializes the criteria object based on the given parameter
280
	 *
281
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
282
	 * @param array $params List of criteria data with condition, sorting and paging
283
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
284
	 */
285
	protected function initCriteria( \Aimeos\MW\Criteria\Iface $criteria, array $params )
286
	{
287
		$this->initCriteriaConditions( $criteria, $params );
288
		$this->initCriteriaSortations( $criteria, $params );
289
		$this->initCriteriaSlice( $criteria, $params );
290
291
		return $criteria;
292
	}
293
294
295
	/**
296
	 * Initializes the criteria object with conditions based on the given parameter
297
	 *
298
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
299
	 * @param array $params List of criteria data with condition, sorting and paging
300
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
301
	 */
302
	protected function initCriteriaConditions( \Aimeos\MW\Criteria\Iface $criteria, array $params )
303
	{
304
		if( !isset( $params['filter'] ) ) {
305
			return $criteria;
306
		}
307
308
		$existing = $criteria->getConditions();
309
		$criteria->setConditions( $criteria->toConditions( (array) $params['filter'] ) );
310
311
		$expr = array( $criteria->getConditions(), $existing );
312
		return $criteria->setConditions( $criteria->combine( '&&', $expr ) );
313
	}
314
315
316
	/**
317
	 * Initializes the criteria object with the slice based on the given parameter.
318
	 *
319
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
320
	 * @param array $params List of criteria data with condition, sorting and paging
321
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
322
	 */
323
	protected function initCriteriaSlice( \Aimeos\MW\Criteria\Iface $criteria, array $params )
324
	{
325
		$start = ( isset( $params['page']['offset'] ) ? (int) $params['page']['offset'] : 0 );
326
		$size = ( isset( $params['page']['limit'] ) ? (int) $params['page']['limit'] : 25 );
327
328
		return $criteria->setSlice( $start, $size );
329
	}
330
331
332
	/**
333
	 * Initializes the criteria object with sortations based on the given parameter
334
	 *
335
	 * @param \Aimeos\MW\Criteria\Iface $criteria Criteria object
336
	 * @param array $params List of criteria data with condition, sorting and paging
337
	 * @return \Aimeos\MW\Criteria\Iface Initialized criteria object
0 ignored issues
show
Documentation introduced by
Should the return type not be \Aimeos\MW\Criteria\Iface|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
338
	 */
339
	protected function initCriteriaSortations( \Aimeos\MW\Criteria\Iface $criteria, array $params )
340
	{
341
		if( !isset( $params['sort'] ) ) {
342
			return;
343
		}
344
345
		$sortation = [];
346
347
		foreach( explode( ',', $params['sort'] ) as $sort )
348
		{
349
			if( $sort[0] === '-' ) {
350
				$sortation[] = $criteria->sort( '-', substr( $sort, 1 ) );
351
			} else {
352
				$sortation[] = $criteria->sort( '+', $sort );
353
			}
354
		}
355
356
		return $criteria->setSortations( $sortation );
357
	}
358
359
360
	/**
361
	 * Returns the available REST verbs and the available parameters
362
	 *
363
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
364
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
365
	 * @param string|null $prefix Form parameter prefix when nesting parameters is required
366
	 * @param string $allow Allowed HTTP methods
367
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
368
	 */
369
	public function getOptionsResponse( ServerRequestInterface $request, ResponseInterface $response, $prefix, $allow )
0 ignored issues
show
Unused Code introduced by
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
370
	{
371
		$view = $this->getView();
372
		$view->prefix = $prefix;
373
374
		$tplconf = 'client/jsonapi/standard/template-options';
375
		$default = 'options-standard.php';
376
377
		$body = $view->render( $view->config( $tplconf, $default ) );
378
379
		return $response->withHeader( 'Allow', $allow )
380
			->withHeader( 'Cache-Control', 'max-age=300' )
381
			->withHeader( 'Content-Type', 'application/vnd.api+json' )
382
			->withBody( $view->response()->createStreamFromString( $body ) )
383
			->withStatus( 200 );
384
	}
385
}
386