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

aimeos / aimeos-core / 63d67b00-e0e2-403b-b3fc-7e74cb9c3a94

11 Jun 2024 05:58AM UTC coverage: 91.668% (+0.05%) from 91.623%
63d67b00-e0e2-403b-b3fc-7e74cb9c3a94

push

circleci

aimeos
Simplified implementing list managers

160 of 162 new or added lines in 3 files covered. (98.77%)

6 existing lines in 3 files now uncovered.

11090 of 12098 relevant lines covered (91.67%)

54.82 hits per line

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

94.29
/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 ) {
5✔
UNCOV
54
                        $this->object()->getSubManager( $domain )->clear( $siteids );
×
55
                }
56

57
                return $this->clearBase( $siteids, $this->getConfigKey( 'delete' ) );
5✔
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\Attribute\Item\Iface New attribute item object
66
         */
67
        public function create( array $values = [] ) : \Aimeos\MShop\Common\Item\Iface
68
        {
69
                $values['siteid'] = $values['siteid'] ?? $this->context()->locale()->getSiteId();
5✔
70
                return new \Aimeos\MShop\Common\Item\Base( '', $values );
5✔
71
        }
72

73

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

85

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

98

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

113

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

125

126
        /**
127
         * Returns the attributes that can be used for searching.
128
         *
129
         * @param bool $withsub Return also attributes of sub-managers if true
130
         * @return \Aimeos\Base\Criteria\Attribute\Iface[] List of attribute items
131
         */
132
        public function getSearchAttributes( bool $withsub = true ) : array
133
        {
134
                return array_replace( $this->createAttributes( [
3✔
135
                        'id' => [
3✔
136
                                'label' => 'ID',
3✔
137
                                'type' => 'int',
3✔
138
                                'public' => false,
3✔
139
                        ],
3✔
140
                        'siteid' => [
3✔
141
                                'label' => 'Site ID',
3✔
142
                                'public' => false,
3✔
143
                        ],
3✔
144
                        'ctime' => [
3✔
145
                                'label' => 'Create date/time',
3✔
146
                                'type' => 'datetime',
3✔
147
                                'public' => false,
3✔
148
                        ],
3✔
149
                        'mtime' => [
3✔
150
                                'label' => 'Modification date/time',
3✔
151
                                'type' => 'datetime',
3✔
152
                                'public' => false,
3✔
153
                        ],
3✔
154
                        'editor' => [
3✔
155
                                'label' => 'Editor',
3✔
156
                                'public' => false,
3✔
157
                        ],
3✔
158
                ] ), $this->getSaveAttributes() );
3✔
159
        }
160

161

162
        /**
163
         * Returns a new manager for attribute extensions
164
         *
165
         * @param string $manager Name of the sub manager type in lower case
166
         * @param string|null $name Name of the implementation, will be from configuration (or Default) if null
167
         * @return \Aimeos\MShop\Common\Manager\Iface Manager for different extensions, e.g Type, List's etc.
168
         */
169
        public function getSubManager( string $manager, string $name = null ) : \Aimeos\MShop\Common\Manager\Iface
170
        {
UNCOV
171
                return $this->getSubManagerBase( $this->getDomain(), $manager, $name );
×
172
        }
173

174

175
        /**
176
         * Iterates over all matched items and returns the found ones
177
         *
178
         * @param \Aimeos\MShop\Common\Cursor\Iface $cursor Cursor object with filter, domains and cursor
179
         * @param string[] $ref List of domains whose items should be fetched too
180
         * @return \Aimeos\Map|null List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
181
         */
182
        public function iterate( \Aimeos\MShop\Common\Cursor\Iface $cursor, array $ref = [] ) : ?\Aimeos\Map
183
        {
184
                if( $cursor->value() === '' ) {
3✔
UNCOV
185
                        return null;
×
186
                }
187

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

192
                $filter = $cursor->filter()->add( $first->getCode(), '>', (int) $cursor->value() )->order( $first->getCode() );
3✔
193
                $items = $this->search( $filter, $ref );
3✔
194
                $cursor->setValue( $items->lastKey() ?: '' );
3✔
195

196
                return !$items->isEmpty() ? $items : null;
3✔
197
        }
198

199

200
        /**
201
         * Adds or updates an item object or a list of them.
202
         *
203
         * @param \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface[]|\Aimeos\MShop\Common\Item\Iface $items Item or list of items whose data should be saved
204
         * @param bool $fetch True if the new ID should be returned in the item
205
         * @return \Aimeos\Map|\Aimeos\MShop\Common\Item\Iface Saved item or items
206
         */
207
        public function save( $items, bool $fetch = true )
208
        {
209
                foreach( map( $items ) as $item )
112✔
210
                {
211
                        if( method_exists( $this, 'saveItem' ) ) {
112✔
212
                                $this->saveItem( $item, $fetch );
108✔
213
                        } else {
214
                                $this->saveBase( $item, $fetch );
4✔
215
                        }
216
                }
217

218
                return is_array( $items ) ? map( $items ) : $items;
111✔
219
        }
220

221

222
        /**
223
         * Searches for all items matching the given critera.
224
         *
225
         * @param \Aimeos\Base\Criteria\Iface $filter Criteria object with conditions, sortations, etc.
226
         * @param string[] $ref List of domains to fetch list items and referenced items for
227
         * @param int &$total Number of items that are available in total
228
         * @return \Aimeos\Map List of items implementing \Aimeos\MShop\Common\Item\Iface with ids as keys
229
         */
230
        public function search( \Aimeos\Base\Criteria\Iface $filter, array $ref = [], int &$total = null ) : \Aimeos\Map
231
        {
232
                /** mshop/common/manager/search/mysql
233
                 * Retrieves the records matched by the given criteria in the database
234
                 *
235
                 * @see mshop/common/manager/search/ansi
236
                 */
237

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

289
                /** mshop/common/manager/count/mysql
290
                 * Counts the number of records matched by the given criteria in the database
291
                 *
292
                 * @see mshop/common/manager/count/ansi
293
                 */
294

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

342
                $items = [];
3✔
343
                $level = $this->getSiteMode();
3✔
344
                $required = [$this->getSearchKey()];
3✔
345
                $conn = $this->context()->db( $this->getResourceName() );
3✔
346

347
                $results = $this->searchItemsBase( $conn, $filter, $cfgPathSearch, $cfgPathCount, $required, $total, $level );
3✔
348

349
                while( $row = $results->fetch() )
3✔
350
                {
351
                        if( $item = $this->applyFilter( $this->create( $row ) ) ) {
3✔
352
                                $items[$row['id']] = $item;
3✔
353
                        }
354
                }
355

356
                return map( $items );
3✔
357
        }
358

359

360
        /**
361
         * Starts a database transaction on the connection identified by the given name
362
         *
363
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
364
         */
365
        public function begin() : \Aimeos\MShop\Common\Manager\Iface
366
        {
367
                $this->context->db( $this->getResourceName() )->begin();
28✔
368
                return $this;
28✔
369
        }
370

371

372
        /**
373
         * Commits the running database transaction on the connection identified by the given name
374
         *
375
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
376
         */
377
        public function commit() : \Aimeos\MShop\Common\Manager\Iface
378
        {
379
                $this->context->db( $this->getResourceName() )->commit();
25✔
380
                return $this;
25✔
381
        }
382

383

384
        /**
385
         * Rolls back the running database transaction on the connection identified by the given name
386
         *
387
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
388
         */
389
        public function rollback() : \Aimeos\MShop\Common\Manager\Iface
390
        {
391
                $this->context->db( $this->getResourceName() )->rollback();
3✔
392
                return $this;
3✔
393
        }
394

395

396
        /**
397
         * Returns the context object.
398
         *
399
         * @return \Aimeos\MShop\ContextIface Context object
400
         */
401
        protected function context() : \Aimeos\MShop\ContextIface
402
        {
403
                return $this->context;
1,785✔
404
        }
405

406

407
        /**
408
         * Returns the site mode constant for inheritance/aggregation
409
         *
410
         * @return int Site mode constant (default: SITE_ALL for inheritance and aggregation)
411
         */
412
        protected function getSiteMode() : int
413
        {
414
                $level = \Aimeos\MShop\Locale\Manager\Base::SITE_ALL;
3✔
415
                return $this->context()->config()->get( $this->getConfigKey( 'sitemode' ), $level );
3✔
416
        }
417
}
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