• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

aimeos / aimeos-core / 5b867e15-acfe-4983-b234-a12890fc1eef

13 Aug 2024 01:29PM UTC coverage: 91.844% (+0.04%) from 91.806%
5b867e15-acfe-4983-b234-a12890fc1eef

push

circleci

aimeos
Simplified order product manager

122 of 122 new or added lines in 3 files covered. (100.0%)

50 existing lines in 6 files now uncovered.

10416 of 11341 relevant lines covered (91.84%)

60.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.12
/src/MShop/Common/Manager/Base.php
1
<?php
2

3
/**
4
 * @license LGPLv3, https://opensource.org/licenses/LGPL-3.0
5
 * @copyright Aimeos (aimeos.org), 2015-2024
6
 * @package MShop
7
 * @subpackage Common
8
 */
9

10

11
namespace Aimeos\MShop\Common\Manager;
12

13

14
/**
15
 * Provides common methods required by most of the manager classes.
16
 *
17
 * @package MShop
18
 * @subpackage Common
19
 */
20
abstract class Base implements \Aimeos\Macro\Iface
21
{
22
        use \Aimeos\Macro\Macroable;
23
        use Sub\Traits;
24
        use Methods;
25
        use Site;
26
        use DB;
27

28

29
        private \Aimeos\MShop\ContextIface $context;
30

31

32
        /**
33
         * Initialization of class.
34
         *
35
         * @param \Aimeos\MShop\ContextIface $context Context object
36
         */
37
        public function __construct( \Aimeos\MShop\ContextIface $context )
38
        {
39
                $this->context = $context;
1,785✔
40

41
                $this->setResourceName( $context->config()->get( 'mshop/' . $this->getDomain() . '/manager/resource', 'db-' . $this->getDomain() ) );
1,785✔
42
        }
43

44

45
        /**
46
         * Removes old entries from the storage.
47
         *
48
         * @param iterable $siteids List of IDs for sites whose entries should be deleted
49
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
50
         */
51
        public function clear( iterable $siteids ) : \Aimeos\MShop\Common\Manager\Iface
52
        {
53
                foreach( $this->context()->config()->get( $this->getConfigKey( 'submanagers' ), [] ) as $domain ) {
21✔
54
                        $this->object()->getSubManager( $domain )->clear( $siteids );
5✔
55
                }
56

57
                return $this->clearBase( $siteids, $this->getConfigKey( 'delete' ) );
21✔
58
        }
59

60

61
        /**
62
         * Creates a new empty item instance
63
         *
64
         * @param array $values Values the item should be initialized with
65
         * @return \Aimeos\MShop\Common\Item\Iface New attribute item object
66
         */
67
        public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
68
        {
69
                $prefix = $this->prefix();
5✔
70
                $values[$prefix . 'siteid'] = $values[$prefix . 'siteid'] ?? $this->context()->locale()->getSiteId();
5✔
71

72
                return new \Aimeos\MShop\Common\Item\Base( $prefix, $values );
5✔
73
        }
74

75

76
        /**
77
         * Removes multiple items.
78
         *
79
         * @param \Aimeos\MShop\Common\Item\Iface[]|string[] $itemIds List of item objects or IDs of the items
80
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
81
         */
82
        public function delete( $itemIds ) : \Aimeos\MShop\Common\Manager\Iface
83
        {
84
                return $this->deleteItemsBase( $itemIds, $this->getConfigKey( 'delete' ) );
29✔
85
        }
86

87

88
        /**
89
         * Creates a search critera object
90
         *
91
         * @param bool|null $default Add default criteria or NULL for relaxed default criteria
92
         * @param bool $site TRUE for adding site criteria to limit items by the site of related items
93
         * @return \Aimeos\Base\Criteria\Iface New search criteria object
94
         */
95
        public function filter( ?bool $default = false, bool $site = false ) : \Aimeos\Base\Criteria\Iface
96
        {
97
                return $this->filterBase( $this->getDomain() );
896✔
98
        }
99

100

101
        /**
102
         * Returns the attributes item specified by its ID.
103
         *
104
         * @param string $id Unique ID of the attribute item in the storage
105
         * @param string[] $ref List of domains to fetch list items and referenced items for
106
         * @param bool|null $default Add default criteria or NULL for relaxed default criteria
107
         * @return \Aimeos\MShop\Common\Item\Iface Returns the attribute item of the given id
108
         * @throws \Aimeos\MShop\Exception If item couldn't be found
109
         */
110
        public function get( string $id, array $ref = [], ?bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
111
        {
112
                return $this->getItemBase( $this->prefix() . 'id', $id, $ref, $default );
32✔
113
        }
114

115

116
        /**
117
         * Returns the available manager types
118
         *
119
         * @param bool $withsub Return also the resource type of sub-managers if true
120
         * @return string[] Type of the manager and submanagers, subtypes are separated by slashes
121
         */
122
        public function getResourceType( bool $withsub = true ) : array
123
        {
124
                return $this->getResourceTypeBase( $this->getManagerPath(), $this->getConfigKey( 'submanagers' ), [], $withsub );
460✔
125
        }
126

127

128
        /**
129
         * Returns the attributes that can be used for searching.
130
         *
131
         * @param bool $withsub Return also attributes of sub-managers if true
132
         * @return \Aimeos\Base\Criteria\Attribute\Iface[] List of attribute items
133
         */
134
        public function getSearchAttributes( bool $withsub = true ) : array
135
        {
136
                $prefix = $this->prefix();
474✔
137

138
                $attr = array_replace( $this->createAttributes( [
474✔
139
                        $prefix . 'id' => [
474✔
140
                                'internalcode' => 'id',
474✔
141
                                'label' => 'ID',
474✔
142
                                'type' => 'int',
474✔
143
                                'public' => false,
474✔
144
                        ],
474✔
145
                        $prefix . 'siteid' => [
474✔
146
                                'internalcode' => 'siteid',
474✔
147
                                'label' => 'Site ID',
474✔
148
                                'public' => false,
474✔
149
                        ],
474✔
150
                        $prefix . 'ctime' => [
474✔
151
                                'internalcode' => 'ctime',
474✔
152
                                'label' => 'Create date/time',
474✔
153
                                'type' => 'datetime',
474✔
154
                                'public' => false,
474✔
155
                        ],
474✔
156
                        $prefix . 'mtime' => [
474✔
157
                                'internalcode' => 'mtime',
474✔
158
                                'label' => 'Modification date/time',
474✔
159
                                'type' => 'datetime',
474✔
160
                                'public' => false,
474✔
161
                        ],
474✔
162
                        $prefix . 'editor' => [
474✔
163
                                'internalcode' => 'editor',
474✔
164
                                'label' => 'Editor',
474✔
165
                                'public' => false,
474✔
166
                        ],
474✔
167
                ] ), $this->getSaveAttributes() );
474✔
168

169
                if( $withsub )
474✔
170
                {
171
                        $domains = $this->context()->config()->get( $this->getConfigKey( 'submanagers' ), [] );
474✔
172

173
                        foreach( $domains as $domain ) {
474✔
174
                                $attr += $this->object()->getSubManager( $domain )->getSearchAttributes( true );
149✔
175
                        }
176
                }
177

178
                return $attr;
474✔
179
        }
180

181

182
        /**
183
         * Returns a new manager for attribute extensions
184
         *
185
         * @param string $manager Name of the sub manager type in lower case
186
         * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
187
         * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g Type, List's etc.
188
         */
189
        public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
190
        {
191
                return $this->getSubManagerBase( $this->getDomain(), trim( $this->getSubPath() . '/' . $manager, '/'), $name );
231✔
192
        }
193

194

195
        /**
196
         * Iterates over all matched items and returns the found ones
197
         *
198
         * @param \Aimeos\MShop\Common\Cursor\Iface $cursor Cursor object with filter, domains and cursor
199
         * @param string[] $ref List of domains whose items should be fetched too
200
         * @return \Aimeos\Map|null List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
201
         */
202
        public function iterate( \Aimeos\MShop\Common\Cursor\Iface $cursor, array $ref = [] ) : ?\Aimeos\Map
203
        {
204
                if( $cursor->value() === '' ) {
3✔
205
                        return null;
×
206
                }
207

208
                if( ( $first = current( $this->getSearchAttributes() ) ) === false ) {
3✔
209
                        throw new \Aimeos\MShop\Exception( sprintf( 'No search configuration available for "%1$s"', get_class( $this ) ) );
×
210
                }
211

212
                $filter = $cursor->filter()->add( $first->getCode(), '>', (int) $cursor->value() )->order( $first->getCode() );
3✔
213
                $items = $this->search( $filter, $ref );
3✔
214
                $cursor->setValue( $items->lastKey() ?: '' );
3✔
215

216
                return !$items->isEmpty() ? $items : null;
3✔
217
        }
218

219

220
        /**
221
         * Adds or updates an item object or a list of them.
222
         *
223
         * @param \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface[]|\Aimeos\MShop\Common\Item\Iface $items Item or list of items whose data should be saved
224
         * @param bool $fetch True if the new ID should be returned in the item
225
         * @return \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface Saved item or items
226
         */
227
        public function save( $items, bool $fetch = true )
228
        {
229
                foreach( map( $items ) as $item )
112✔
230
                {
231
                        if( method_exists( $this, 'saveItem' ) ) {
112✔
232
                                $this->saveItem( $item, $fetch );
93✔
233
                        } else {
234
                                $this->saveBase( $item, $fetch );
26✔
235
                        }
236
                }
237

238
                return is_array( $items ) ? map( $items ) : $items;
111✔
239
        }
240

241

242
        /**
243
         * Searches for all items matching the given critera.
244
         *
245
         * @param \Aimeos\Base\Criteria\Iface $filter Criteria object with conditions, sortations, etc.
246
         * @param string[] $ref List of domains to fetch list items and referenced items for
247
         * @param int &$total Number of items that are available in total
248
         * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
249
         */
250
        public function search( \Aimeos\Base\Criteria\Iface $filter, array $ref = [], int &$total = null ) : \Aimeos\Map
251
        {
252
                /** mshop/common/manager/search/mysql
253
                 * Retrieves the records matched by the given criteria in the database
254
                 *
255
                 * @see mshop/common/manager/search/ansi
256
                 */
257

258
                /** mshop/common/manager/search/ansi
259
                 * Retrieves the records matched by the given criteria in the database
260
                 *
261
                 * Fetches the records matched by the given criteria from the
262
                 * database. The records must be from one of the sites that are
263
                 * configured via the context item. If the current site is part of
264
                 * a tree of sites, the SELECT statement can retrieve all records
265
                 * from the current site and the complete sub-tree of sites.
266
                 *
267
                 * As the records can normally be limited by criteria from sub-managers,
268
                 * their tables must be joined in the SQL context. This is done by
269
                 * using the "internaldeps" property from the definition of the ID
270
                 * column of the sub-managers. These internal dependencies specify
271
                 * the JOIN between the tables and the used columns for joining. The
272
                 * ":joins" placeholder is then replaced by the JOIN strings from
273
                 * the sub-managers.
274
                 *
275
                 * To limit the records matched, conditions can be added to the given
276
                 * criteria object. It can contain comparisons like column names that
277
                 * must match specific values which can be combined by AND, OR or NOT
278
                 * operators. The resulting string of SQL conditions replaces the
279
                 * ":cond" placeholder before the statement is sent to the database
280
                 * server.
281
                 *
282
                 * If the records that are retrieved should be ordered by one or more
283
                 * columns, the generated string of column / sort direction pairs
284
                 * replaces the ":order" placeholder. Columns of
285
                 * sub-managers can also be used for ordering the result set but then
286
                 * no index can be used.
287
                 *
288
                 * The number of returned records can be limited and can start at any
289
                 * number between the begining and the end of the result set. For that
290
                 * the ":size" and ":start" placeholders are replaced by the
291
                 * corresponding values from the criteria object. The default values
292
                 * are 0 for the start and 100 for the size value.
293
                 *
294
                 * The SQL statement should conform to the ANSI standard to be
295
                 * compatible with most relational database systems. This also
296
                 * includes using double quotes for table and column names.
297
                 *
298
                 * @param string SQL statement for searching items
299
                 * @since 2023.10
300
                 * @see mshop/common/manager/insert/ansi
301
                 * @see mshop/common/manager/update/ansi
302
                 * @see mshop/common/manager/newid/ansi
303
                 * @see mshop/common/manager/delete/ansi
304
                 * @see mshop/common/manager/count/ansi
305
                 */
306
                $cfgPathSearch = 'mshop/common/manager/search';
430✔
307

308
                /** mshop/common/manager/count/mysql
309
                 * Counts the number of records matched by the given criteria in the database
310
                 *
311
                 * @see mshop/common/manager/count/ansi
312
                 */
313

314
                /** mshop/common/manager/count/ansi
315
                 * Counts the number of records matched by the given criteria in the database
316
                 *
317
                 * Counts all records matched by the given criteria from the
318
                 * database. The records must be from one of the sites that are
319
                 * configured via the context item. If the current site is part of
320
                 * a tree of sites, the statement can count all records from the
321
                 * current site and the complete sub-tree of sites.
322
                 *
323
                 * As the records can normally be limited by criteria from sub-managers,
324
                 * their tables must be joined in the SQL context. This is done by
325
                 * using the "internaldeps" property from the definition of the ID
326
                 * column of the sub-managers. These internal dependencies specify
327
                 * the JOIN between the tables and the used columns for joining. The
328
                 * ":joins" placeholder is then replaced by the JOIN strings from
329
                 * the sub-managers.
330
                 *
331
                 * To limit the records matched, conditions can be added to the given
332
                 * criteria object. It can contain comparisons like column names that
333
                 * must match specific values which can be combined by AND, OR or NOT
334
                 * operators. The resulting string of SQL conditions replaces the
335
                 * ":cond" placeholder before the statement is sent to the database
336
                 * server.
337
                 *
338
                 * Both, the strings for ":joins" and for ":cond" are the same as for
339
                 * the "search" SQL statement.
340
                 *
341
                 * Contrary to the "search" statement, it doesn't return any records
342
                 * but instead the number of records that have been found. As counting
343
                 * thousands of records can be a long running task, the maximum number
344
                 * of counted records is limited for performance reasons.
345
                 *
346
                 * The SQL statement should conform to the ANSI standard to be
347
                 * compatible with most relational database systems. This also
348
                 * includes using double quotes for table and column names.
349
                 *
350
                 * @param string SQL statement for counting items
351
                 * @since 2023.10
352
                 * @see mshop/common/manager/insert/ansi
353
                 * @see mshop/common/manager/update/ansi
354
                 * @see mshop/common/manager/newid/ansi
355
                 * @see mshop/common/manager/delete/ansi
356
                 * @see mshop/common/manager/search/ansi
357
                 */
358
                $cfgPathCount = 'mshop/common/manager/count';
430✔
359

360
                $level = $this->getSiteMode();
430✔
361
                $required = [$this->getSearchKey()];
430✔
362
                $conn = $this->context()->db( $this->getResourceName() );
430✔
363

364
                $attrs = array_filter( $this->getSearchAttributes(), fn( $attr ) => $attr->getType() === 'json' );
430✔
365
                $attrs = array_column( $attrs, null, 'code' );
430✔
366

367
                $results = $this->searchItemsBase( $conn, $filter, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
430✔
368

369
                try {
370
                        return $this->fetch( $results, $ref, $this->prefix(), $attrs );
430✔
UNCOV
371
                } catch( \Exception $e ) {
×
UNCOV
372
                        $results->finish(); throw $e;
×
373
                }
374
        }
375

376

377
        /**
378
         * Starts a database transaction on the connection identified by the given name
379
         *
380
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
381
         */
382
        public function begin() : \Aimeos\MShop\Common\Manager\Iface
383
        {
384
                $this->context->db( $this->getResourceName() )->begin();
28✔
385
                return $this;
28✔
386
        }
387

388

389
        /**
390
         * Commits the running database transaction on the connection identified by the given name
391
         *
392
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
393
         */
394
        public function commit() : \Aimeos\MShop\Common\Manager\Iface
395
        {
396
                $this->context->db( $this->getResourceName() )->commit();
25✔
397
                return $this;
25✔
398
        }
399

400

401
        /**
402
         * Rolls back the running database transaction on the connection identified by the given name
403
         *
404
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
405
         */
406
        public function rollback() : \Aimeos\MShop\Common\Manager\Iface
407
        {
408
                $this->context->db( $this->getResourceName() )->rollback();
3✔
409
                return $this;
3✔
410
        }
411

412

413
        /**
414
         * Returns the context object.
415
         *
416
         * @return \Aimeos\MShop\ContextIface Context object
417
         */
418
        protected function context() : \Aimeos\MShop\ContextIface
419
        {
420
                return $this->context;
1,785✔
421
        }
422

423

424
        /**
425
         * Returns the site mode constant for inheritance/aggregation
426
         *
427
         * @return int Site mode constant (default: SITE_ALL for inheritance and aggregation)
428
         */
429
        protected function getSiteMode() : int
430
        {
431
                $level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
430✔
432
                return $this->context()->config()->get( $this->getConfigKey( 'sitemode' ), $level );
430✔
433
        }
434
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc