Issues (87)

src/Client/JsonApi/Base.php (2 issues)

Labels
Severity
1
<?php
2
3
/**
4
 * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2017-2025
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
	implements \Aimeos\Client\JsonApi\Iface, \Aimeos\Macro\Iface
25
{
26
	use \Aimeos\Macro\Macroable;
27
28
29
	private \Aimeos\MShop\ContextIface $context;
30
	private ?\Aimeos\Base\View\Iface $view = null;
31
32
33
	/**
34
	 * Initializes the client
35
	 *
36
	 * @param \Aimeos\MShop\ContextIface $context MShop context object
37
	 */
38
	public function __construct( \Aimeos\MShop\ContextIface $context )
39
	{
40
		$this->context = $context;
41
	}
42
43
44
	/**
45
	 * Deletes the resource or the resource list
46
	 *
47
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
48
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
49
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
50
	 */
51
	public function delete( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
52
	{
53
		return $this->defaultAction( $request, $response );
54
	}
55
56
57
	/**
58
	 * Retrieves the resource or the resource list
59
	 *
60
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
61
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
62
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
63
	 */
64
	public function get( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
65
	{
66
		return $this->defaultAction( $request, $response );
67
	}
68
69
70
	/**
71
	 * Updates the resource or the resource list partitially
72
	 *
73
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
74
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
75
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
76
	 */
77
	public function patch( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
78
	{
79
		return $this->defaultAction( $request, $response );
80
	}
81
82
83
	/**
84
	 * Creates or updates the resource or the resource list
85
	 *
86
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
87
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
88
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
89
	 */
90
	public function post( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
91
	{
92
		return $this->defaultAction( $request, $response );
93
	}
94
95
96
	/**
97
	 * Creates or updates the resource or the resource list
98
	 *
99
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
100
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
101
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
102
	 */
103
	public function put( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
104
	{
105
		return $this->defaultAction( $request, $response );
106
	}
107
108
109
	/**
110
	 * Creates or updates the resource or the resource list
111
	 *
112
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
113
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
114
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
115
	 */
116
	public function options( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
117
	{
118
		return $this->defaultAction( $request, $response );
119
	}
120
121
122
	/**
123
	 * Sets the view object that will generate the admin output.
124
	 *
125
	 * @param \Aimeos\Base\View\Iface $view The view object which generates the admin output
126
	 * @return \Aimeos\Client\JsonApi\Iface Reference to this object for fluent calls
127
	 */
128
	public function setView( \Aimeos\Base\View\Iface $view ) : \Aimeos\Client\JsonApi\Iface
129
	{
130
		$this->view = $view;
131
		return $this;
132
	}
133
134
135
	/**
136
	 * Returns the default response for the resource
137
	 *
138
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
139
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
140
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
141
	 */
142
	protected function defaultAction( ServerRequestInterface $request, ResponseInterface $response ) : \Psr\Http\Message\ResponseInterface
143
	{
144
		$status = 403;
145
		$view = $this->view();
146
147
		$view->errors = [['title' => 'Not allowed for this resource']];
148
149
		/** client/jsonapi/template-error
150
		 * Relative path to the default JSON API template
151
		 *
152
		 * The template file contains the code and processing instructions
153
		 * to generate the result shown in the JSON API body. The
154
		 * configuration string is the path to the template file relative
155
		 * to the templates directory (usually in templates/client/jsonapi).
156
		 *
157
		 * You can overwrite the template file configuration in extensions and
158
		 * provide alternative templates. These alternative templates should be
159
		 * named like the default one but with the string "standard" replaced by
160
		 * an unique name. You may use the name of your project for this. If
161
		 * you've implemented an alternative client class as well, "standard"
162
		 * should be replaced by the name of the new class.
163
		 *
164
		 * @param string Relative path to the template creating the body for the JSON API response
165
		 * @since 2017.02
166
		 * @category Developer
167
		 * @see client/jsonapi/template-delete
168
		 * @see client/jsonapi/template-patch
169
		 * @see client/jsonapi/template-post
170
		 * @see client/jsonapi/template-get
171
		 * @see client/jsonapi/template-options
172
		 */
173
		$tplconf = 'client/jsonapi/template-error';
174
		$default = 'error-standard';
175
176
		$body = $view->render( $view->config( $tplconf, $default ) );
177
178
		return $response->withHeader( 'Content-Type', 'application/vnd.api+json' )
179
			->withBody( $view->response()->createStreamFromString( $body ) )
180
			->withStatus( $status );
0 ignored issues
show
The method withStatus() does not exist on Psr\Http\Message\MessageInterface. It seems like you code against a sub-type of Psr\Http\Message\MessageInterface such as Psr\Http\Message\ResponseInterface or Aimeos\Base\View\Helper\Request\Standard. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

180
			->/** @scrutinizer ignore-call */ withStatus( $status );
Loading history...
181
	}
182
183
184
	/**
185
	 * Returns the context item object
186
	 *
187
	 * @return \Aimeos\MShop\ContextIface Context object
188
	 */
189
	protected function context() : \Aimeos\MShop\ContextIface
190
	{
191
		return $this->context;
192
	}
193
194
195
	/**
196
	 * Returns the translated title and the details of the error
197
	 *
198
	 * @param \Exception $e Thrown exception
199
	 * @param string|null $domain Translation domain
200
	 * @param string|null $msg Additional error details
201
	 * @return array Associative list with "title" and "detail" key (if debug config is enabled)
202
	 */
203
	protected function getErrorDetails( \Exception $e, ?string $domain = null ) : array
204
	{
205
		$details = [];
206
207
		if( $domain !== null ) {
208
			$details['title'] = $this->context->translate( $domain, $e->getMessage() );
209
		} else {
210
			$details['title'] = $this->context->translate( 'admin', 'An error occured and has been added to the logs' );
211
			$this->context->logger()->log( $e->getMessage() . PHP_EOL . $e->getTraceAsString() );
212
		}
213
214
		if( $e instanceof \Aimeos\MShop\Plugin\Provider\Exception ) {
215
			$details['detail'] = join( "\n", $this->translatePluginErrorCodes( $e->getErrorCodes() ) );
216
		}
217
218
		/** client/jsonapi/debug
219
		 * Send debug information withing responses to clients if an error occurrs
220
		 *
221
		 * By default, the Aimeos client JSON REST API won't send any details
222
		 * besides the error message to the client if an error occurred. This
223
		 * prevents leaking sensitive information to attackers. For debugging
224
		 * your requests it's helpful to see the stack strace. If you set this
225
		 * configuration option to true, the stack trace will be returned too.
226
		 *
227
		 * @param boolean True to return the stack trace in JSON response, false for error message only
228
		 * @since 2017.07
229
		 * @category Developer
230
		 */
231
		if( $this->context->config()->get( 'client/jsonapi/debug', false ) == true )
232
		{
233
			$details['title'] = $e->getMessage();
234
			$details['detail'] = ( isset( $details['detail'] ) ? $details['detail'] . "\n" : '' ) . $e->getTraceAsString();
235
		}
236
237
		return [$details]; // jsonapi.org requires a list of error objects
238
	}
239
240
241
	/**
242
	 * Returns the available REST verbs and the available parameters
243
	 *
244
	 * @param \Psr\Http\Message\ServerRequestInterface $request Request object
245
	 * @param \Psr\Http\Message\ResponseInterface $response Response object
246
	 * @param string $allow Allowed HTTP methods
247
	 * @return \Psr\Http\Message\ResponseInterface Modified response object
248
	 */
249
	protected function getOptionsResponse( ServerRequestInterface $request, ResponseInterface $response, string $allow ) : \Psr\Http\Message\ResponseInterface
250
	{
251
		$view = $this->view();
252
253
		$tplconf = 'client/jsonapi/template-options';
254
		$default = 'options-standard';
255
256
		$body = $view->render( $view->config( $tplconf, $default ) );
257
258
		return $response->withHeader( 'Allow', $allow )
259
			->withHeader( 'Cache-Control', 'max-age=300' )
260
			->withHeader( 'Content-Type', 'application/vnd.api+json' )
261
			->withBody( $view->response()->createStreamFromString( $body ) )
262
			->withStatus( 200 );
263
	}
264
265
266
	/**
267
	 * Initializes the criteria object based on the given parameter
268
	 *
269
	 * @param \Aimeos\Base\Criteria\Iface $criteria Criteria object
270
	 * @param array $params List of criteria data with condition, sorting and paging
271
	 * @return \Aimeos\Base\Criteria\Iface Initialized criteria object
272
	 */
273
	protected function initCriteria( \Aimeos\Base\Criteria\Iface $criteria, array $params ) : \Aimeos\Base\Criteria\Iface
274
	{
275
		return $criteria->order( $params['sort'] ?? [] )
276
			->add( $criteria->parse( $params['filter'] ?? [] ) )
277
			->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 );
278
	}
279
280
281
	/**
282
	 * Translates the plugin error codes to human readable error strings.
283
	 *
284
	 * @param array $codes Associative list of scope and object as key and error code as value
285
	 * @return array List of translated error messages
286
	 */
287
	protected function translatePluginErrorCodes( array $codes ) : array
288
	{
289
		$errors = [];
290
		$i18n = $this->context()->i18n();
291
292
		foreach( $codes as $scope => $list )
293
		{
294
			foreach( $list as $object => $errcode )
295
			{
296
				$key = $scope . ( !in_array( $scope, ['coupon', 'product'] ) ? '.' . $object : '' ) . '.' . $errcode;
297
				$errors[] = sprintf( $i18n->dt( 'mshop/code', $key ), $object );
298
			}
299
		}
300
301
		return array_unique( $errors );
302
	}
303
304
305
	/**
306
	 * Returns the view object that will generate the admin output.
307
	 *
308
	 * @return \Aimeos\Base\View\Iface The view object which generates the admin output
309
	 */
310
	protected function view() : \Aimeos\Base\View\Iface
311
	{
312
		if( !isset( $this->view ) ) {
313
			throw new \Aimeos\Admin\JsonAdm\Exception( 'No view available' );
0 ignored issues
show
The type Aimeos\Admin\JsonAdm\Exception was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
314
		}
315
316
		return $this->view;
317
	}
318
}
319