1 | <?php |
||||
2 | |||||
3 | /** |
||||
4 | * @license LGPLv3, http://opensource.org/licenses/LGPL-3.0 |
||||
5 | * @copyright Aimeos (aimeos.org), 2015-2024 |
||||
6 | * @package Admin |
||||
7 | * @subpackage JsonAdm |
||||
8 | */ |
||||
9 | |||||
10 | |||||
11 | namespace Aimeos\Admin\JsonAdm; |
||||
12 | |||||
13 | |||||
14 | /** |
||||
15 | * JSON API common client |
||||
16 | * |
||||
17 | * @package Admin |
||||
18 | * @subpackage JsonAdm |
||||
19 | */ |
||||
20 | abstract class Base |
||||
21 | implements \Aimeos\Admin\JsonAdm\Iface, \Aimeos\Macro\Iface |
||||
22 | { |
||||
23 | use \Aimeos\Macro\Macroable; |
||||
24 | |||||
25 | |||||
26 | private \Aimeos\MShop\ContextIface $context; |
||||
27 | private ?\Aimeos\Base\View\Iface $view = null; |
||||
28 | private ?\Aimeos\Bootstrap $aimeos = null; |
||||
29 | private string $path; |
||||
30 | |||||
31 | |||||
32 | /** |
||||
33 | * Initializes the client |
||||
34 | * |
||||
35 | * @param \Aimeos\MShop\ContextIface $context MShop context object |
||||
36 | * @param string $path Name of the client separated by slashes, e.g "product/property" |
||||
37 | */ |
||||
38 | public function __construct( \Aimeos\MShop\ContextIface $context, string $path ) |
||||
39 | { |
||||
40 | $this->context = $context; |
||||
41 | $this->path = $path; |
||||
42 | } |
||||
43 | |||||
44 | |||||
45 | /** |
||||
46 | * Returns the Aimeos bootstrap object |
||||
47 | * |
||||
48 | * @return \Aimeos\Bootstrap The Aimeos bootstrap object |
||||
49 | */ |
||||
50 | protected function getAimeos() : \Aimeos\Bootstrap |
||||
51 | { |
||||
52 | if( !isset( $this->aimeos ) ) { |
||||
53 | throw new \Aimeos\Admin\JsonAdm\Exception( 'Aimeos object not available', 500 ); |
||||
54 | } |
||||
55 | |||||
56 | return $this->aimeos; |
||||
57 | } |
||||
58 | |||||
59 | |||||
60 | /** |
||||
61 | * Sets the Aimeos bootstrap object |
||||
62 | * |
||||
63 | * @param \Aimeos\Bootstrap $aimeos The Aimeos bootstrap object |
||||
64 | * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls |
||||
65 | */ |
||||
66 | public function setAimeos( \Aimeos\Bootstrap $aimeos ) : \Aimeos\Admin\JsonAdm\Iface |
||||
67 | { |
||||
68 | $this->aimeos = $aimeos; |
||||
69 | return $this; |
||||
70 | } |
||||
71 | |||||
72 | |||||
73 | /** |
||||
74 | * Returns the view object that will generate the admin output. |
||||
75 | * |
||||
76 | * @return \Aimeos\Base\View\Iface The view object which generates the admin output |
||||
77 | */ |
||||
78 | protected function view() : \Aimeos\Base\View\Iface |
||||
79 | { |
||||
80 | if( !isset( $this->view ) ) { |
||||
81 | throw new \Aimeos\Admin\JsonAdm\Exception( 'No view available', 500 ); |
||||
82 | } |
||||
83 | |||||
84 | return $this->view; |
||||
85 | } |
||||
86 | |||||
87 | |||||
88 | /** |
||||
89 | * Sets the view object that will generate the admin output. |
||||
90 | * |
||||
91 | * @param \Aimeos\Base\View\Iface $view The view object which generates the admin output |
||||
92 | * @return \Aimeos\Admin\JsonAdm\Iface Reference to this object for fluent calls |
||||
93 | */ |
||||
94 | public function setView( \Aimeos\Base\View\Iface $view ) : \Aimeos\Admin\JsonAdm\Iface |
||||
95 | { |
||||
96 | $this->view = $view; |
||||
97 | return $this; |
||||
98 | } |
||||
99 | |||||
100 | |||||
101 | /** |
||||
102 | * Returns the items with parent/child relationships |
||||
103 | * |
||||
104 | * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface |
||||
105 | * @param array $include List of resource types that should be fetched |
||||
106 | * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface |
||||
107 | */ |
||||
108 | protected function getChildItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map |
||||
109 | { |
||||
110 | return map(); |
||||
111 | } |
||||
112 | |||||
113 | |||||
114 | /** |
||||
115 | * Returns the context item object |
||||
116 | * |
||||
117 | * @return \Aimeos\MShop\ContextIface Context object |
||||
118 | */ |
||||
119 | protected function context() : \Aimeos\MShop\ContextIface |
||||
120 | { |
||||
121 | return $this->context; |
||||
122 | } |
||||
123 | |||||
124 | |||||
125 | /** |
||||
126 | * Returns the list of domains that are available as resources |
||||
127 | * |
||||
128 | * @param \Aimeos\Base\View\Iface $view View object with "resource" parameter |
||||
129 | * @return array List of domain names |
||||
130 | */ |
||||
131 | protected function getDomains( \Aimeos\Base\View\Iface $view ) : array |
||||
132 | { |
||||
133 | if( ( $domains = $view->param( 'resource' ) ) == '' ) |
||||
134 | { |
||||
135 | /** admin/jsonadm/domains |
||||
136 | * A list of domain names whose clients are available for the JSON API |
||||
137 | * |
||||
138 | * The HTTP OPTIONS method returns a list of resources known by the |
||||
139 | * JSON API including their URLs. The list of available resources |
||||
140 | * can be exteded dynamically be implementing a new Jsonadm client |
||||
141 | * class handling request for this new domain. |
||||
142 | * |
||||
143 | * To add the new domain client to the list of resources returned |
||||
144 | * by the HTTP OPTIONS method, you have to add its name in lower case |
||||
145 | * to the existing configuration. |
||||
146 | * |
||||
147 | * @param array List of domain names |
||||
148 | * @since 2016.01 |
||||
149 | * @category Developer |
||||
150 | * @see admin/jsonadm/resources |
||||
151 | */ |
||||
152 | $domains = $this->context()->config()->get( 'admin/jsonadm/domains', [] ); |
||||
153 | } |
||||
154 | |||||
155 | return (array) $domains; |
||||
156 | } |
||||
157 | |||||
158 | |||||
159 | /** |
||||
160 | * Returns the list items for association relationships |
||||
161 | * |
||||
162 | * @param \Aimeos\Map $items List of items implementing \Aimeos\MShop\Common\Item\Iface |
||||
163 | * @param array $include List of resource types that should be fetched |
||||
164 | * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface |
||||
165 | */ |
||||
166 | protected function getListItems( \Aimeos\Map $items, array $include ) : \Aimeos\Map |
||||
167 | { |
||||
168 | return $items->filter( function( $item ) { |
||||
169 | return $item instanceof \Aimeos\MShop\Common\Item\Lists\Iface; |
||||
170 | } ); |
||||
171 | } |
||||
172 | |||||
173 | |||||
174 | /** |
||||
175 | * Returns the path to the client |
||||
176 | * |
||||
177 | * @return string Client path, e.g. "product/property" |
||||
178 | */ |
||||
179 | protected function getPath() : string |
||||
180 | { |
||||
181 | return $this->path; |
||||
182 | } |
||||
183 | |||||
184 | |||||
185 | /** |
||||
186 | * Returns the items associated via a lists table |
||||
187 | * |
||||
188 | * @param \Aimeos\Map $listItems List of items implementing \Aimeos\MShop\Common\Item\Lists\Iface |
||||
189 | * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface |
||||
190 | */ |
||||
191 | protected function getRefItems( \Aimeos\Map $listItems ) : \Aimeos\Map |
||||
192 | { |
||||
193 | $list = []; |
||||
194 | |||||
195 | foreach( $listItems as $listItem ) |
||||
196 | { |
||||
197 | if( $refItem = $listItem->getRefItem() ) { |
||||
198 | $list[$refItem->getResourceType() . '-' . $refItem->getId()] = $refItem; |
||||
199 | } |
||||
200 | } |
||||
201 | |||||
202 | return map( $list ); |
||||
203 | } |
||||
204 | |||||
205 | |||||
206 | /** |
||||
207 | * Returns the list of allowed resources |
||||
208 | * |
||||
209 | * @param \Aimeos\Base\View\Iface $view View object with "access" helper |
||||
210 | * @param array $resources List of all available resources |
||||
211 | * @return array List of allowed resources |
||||
212 | */ |
||||
213 | protected function getAllowedResources( \Aimeos\Base\View\Iface $view, array $resources ) : array |
||||
214 | { |
||||
215 | $config = $this->context()->config(); |
||||
216 | $allowed = []; |
||||
217 | |||||
218 | foreach( $resources as $resource ) |
||||
219 | { |
||||
220 | if( $view->access( $config->get( 'admin/jsonadm/resource/' . $resource . '/groups', [] ) ) === true ) { |
||||
221 | $allowed[] = $resource; |
||||
222 | } |
||||
223 | } |
||||
224 | |||||
225 | return $allowed; |
||||
226 | } |
||||
227 | |||||
228 | |||||
229 | /** |
||||
230 | * Returns the list of additional resources |
||||
231 | * |
||||
232 | * @param \Aimeos\Base\View\Iface $view View object with "resource" parameter |
||||
233 | * @return array List of domain names |
||||
234 | */ |
||||
235 | protected function getResources( \Aimeos\Base\View\Iface $view ) : array |
||||
236 | { |
||||
237 | /** admin/jsonadm/resources |
||||
238 | * A list of additional resources name whose clients are available for the JSON API |
||||
239 | * |
||||
240 | * The HTTP OPTIONS method returns a list of resources known by the |
||||
241 | * JSON API including their URLs. The list of available resources |
||||
242 | * can be exteded dynamically be implementing a new Jsonadm client |
||||
243 | * class handling request for this new domain. |
||||
244 | * |
||||
245 | * The resource config lists the resources that are not automatically |
||||
246 | * derived from the admin/jsonadm/domains configuration. |
||||
247 | * |
||||
248 | * @param array List of domain names |
||||
249 | * @since 2017.07 |
||||
250 | * @category Developer |
||||
251 | * @see admin/jsonadm/domains |
||||
252 | */ |
||||
253 | return (array) $view->config( 'admin/jsonadm/resources', [] ); |
||||
254 | } |
||||
255 | |||||
256 | |||||
257 | /** |
||||
258 | * Initializes the criteria object based on the given parameter |
||||
259 | * |
||||
260 | * @param \Aimeos\Base\Criteria\Iface $criteria Criteria object |
||||
261 | * @param array $params List of criteria data with condition, sorting and paging |
||||
262 | * @return \Aimeos\Base\Criteria\Iface Initialized criteria object |
||||
263 | */ |
||||
264 | protected function initCriteria( \Aimeos\Base\Criteria\Iface $criteria, array $params ) : \Aimeos\Base\Criteria\Iface |
||||
265 | { |
||||
266 | return $criteria->order( $params['sort'] ?? [] ) |
||||
267 | ->add( $criteria->parse( $params['filter'] ?? [] ) ) |
||||
268 | ->slice( $params['page']['offset'] ?? 0, $params['page']['limit'] ?? 25 ); |
||||
269 | } |
||||
270 | |||||
271 | |||||
272 | /** |
||||
273 | * Creates of updates several items at once |
||||
274 | * |
||||
275 | * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items |
||||
276 | * @param \stdClass $request Object with request body data |
||||
277 | * @return \Aimeos\Map List of items |
||||
278 | */ |
||||
279 | protected function saveData( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $request ) : \Aimeos\Map |
||||
280 | { |
||||
281 | $data = []; |
||||
282 | |||||
283 | if( isset( $request->data ) ) |
||||
284 | { |
||||
285 | foreach( (array) $request->data as $entry ) { |
||||
286 | $data[] = $this->saveEntry( $manager, $entry ); |
||||
287 | } |
||||
288 | } |
||||
289 | |||||
290 | return map( $data ); |
||||
291 | } |
||||
292 | |||||
293 | |||||
294 | /** |
||||
295 | * Saves and returns the new or updated item |
||||
296 | * |
||||
297 | * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items |
||||
298 | * @param \stdClass $entry Object including "id" and "attributes" elements |
||||
299 | * @return \Aimeos\MShop\Common\Item\Iface New or updated item |
||||
300 | */ |
||||
301 | protected function saveEntry( \Aimeos\MShop\Common\Manager\Iface $manager, \stdClass $entry ) : \Aimeos\MShop\Common\Item\Iface |
||||
302 | { |
||||
303 | if( isset( $entry->id ) ) { |
||||
304 | $item = $manager->get( $entry->id ); |
||||
305 | } else { |
||||
306 | $item = $manager->create(); |
||||
307 | } |
||||
308 | |||||
309 | if( isset( $entry->attributes ) && ( $attr = (array) $entry->attributes ) ) |
||||
310 | { |
||||
311 | if( $item instanceof \Aimeos\MShop\Common\Item\Config\Iface ) |
||||
312 | { |
||||
313 | $key = str_replace( '/', '.', $this->path ) . '.config'; |
||||
314 | $attr[$key] = (array) ( $attr[$key] ?? [] ); |
||||
315 | } |
||||
316 | |||||
317 | $item = $item->fromArray( $attr, true ); |
||||
318 | } |
||||
319 | |||||
320 | $item = $manager->save( $item ); |
||||
321 | |||||
322 | if( isset( $entry->relationships ) ) { |
||||
323 | $this->saveRelationships( $manager, $item, $entry->relationships ); |
||||
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||
324 | } |
||||
325 | |||||
326 | return $manager->get( $item->getId() ); |
||||
0 ignored issues
–
show
It seems like
$item->getId() can also be of type Aimeos\Map and null ; however, parameter $id of Aimeos\MShop\Common\Manager\Iface::get() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
327 | } |
||||
328 | |||||
329 | |||||
330 | /** |
||||
331 | * Saves the item references associated via the list |
||||
332 | * |
||||
333 | * @param \Aimeos\MShop\Common\Manager\Iface $manager Manager responsible for the items |
||||
334 | * @param \Aimeos\MShop\Common\Item\Iface $item Domain item with an unique ID set |
||||
335 | * @param \stdClass $relationships Object including the <domain>/data/attributes structure |
||||
336 | */ |
||||
337 | protected function saveRelationships( \Aimeos\MShop\Common\Manager\Iface $manager, |
||||
338 | \Aimeos\MShop\Common\Item\Iface $item, \stdClass $relationships ) |
||||
339 | { |
||||
340 | $id = $item->getId(); |
||||
341 | $listManager = $manager->getSubManager( 'lists' ); |
||||
342 | |||||
343 | foreach( (array) $relationships as $domain => $list ) |
||||
344 | { |
||||
345 | if( isset( $list->data ) ) |
||||
346 | { |
||||
347 | foreach( (array) $list->data as $data ) |
||||
348 | { |
||||
349 | $listItem = $listManager->create()->setType( 'default' ); |
||||
350 | |||||
351 | if( isset( $data->attributes ) && ( $attr = (array) $data->attributes ) ) { |
||||
352 | $key = str_replace( '/', '.', $this->path ) . '.config'; |
||||
353 | $attr[$key] = (array) ( $attr[$key] ?? [] ); |
||||
354 | $listItem = $listItem->fromArray( $attr, true ); |
||||
355 | } |
||||
356 | |||||
357 | if( isset( $data->id ) ) { |
||||
358 | $listItem->setRefId( $data->id ); |
||||
359 | } |
||||
360 | |||||
361 | $listItem->setParentId( $id )->setDomain( $domain ); |
||||
362 | $listManager->save( $listItem, false ); |
||||
363 | } |
||||
364 | } |
||||
365 | } |
||||
366 | } |
||||
367 | } |
||||
368 |