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

aimeos / aimeos-core / e67a5171-b485-4a8f-9441-93d8ff5aa19b

15 Aug 2024 11:37AM UTC coverage: 91.967% (+0.03%) from 91.933%
e67a5171-b485-4a8f-9441-93d8ff5aa19b

push

circleci

aimeos
Simplified order service manager

111 of 117 new or added lines in 4 files covered. (94.87%)

5 existing lines in 3 files now uncovered.

10246 of 11141 relevant lines covered (91.97%)

61.76 hits per line

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

98.15
/src/MShop/Order/Manager/Base.php
1
<?php
2

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

11

12
namespace Aimeos\MShop\Order\Manager;
13

14

15
/**
16
 * Basic methods and constants for order items (shopping basket).
17
 *
18
 * @package MShop
19
 * @subpackage Order
20
 */
21
abstract class Base extends \Aimeos\MShop\Common\Manager\Base
22
{
23
        /**
24
         * Returns a new and empty order item (shopping basket).
25
         *
26
         * @param \Aimeos\MShop\Price\Item\Iface $price Default price of the basket (usually 0.00)
27
         * @param \Aimeos\MShop\Locale\Item\Iface $locale Locale item containing the site, language and currency
28
         * @param array $values Associative list of key/value pairs containing, e.g. the order or user ID
29
         * @param \Aimeos\MShop\Order\Item\Product\Iface[] $products List of ordered product items
30
         * @param \Aimeos\MShop\Order\Item\Address\Iface[] $addresses List of order address items
31
         * @param \Aimeos\MShop\Order\Item\Service\Iface[] $services List of order serviceitems
32
         * @param \Aimeos\MShop\Order\Item\Product\Iface[] $coupons Associative list of coupon codes as keys and items as values
33
         * @param \Aimeos\MShop\Customer\Item\Iface|null $custItem Customer item object if requested
34
         * @return \Aimeos\MShop\Order\Item\Iface Order object
35
         */
36
        abstract protected function createItemBase( \Aimeos\MShop\Price\Item\Iface $price, \Aimeos\MShop\Locale\Item\Iface $locale,
37
                array $values = [], array $products = [], array $addresses = [], array $services = [], array $coupons = [],
38
                ?\Aimeos\MShop\Customer\Item\Iface $custItem = null ) : \Aimeos\MShop\Order\Item\Iface;
39

40

41
        /**
42
         * Returns the address item map for the given order IDs
43
         *
44
         * @param string[] $ids List of order IDs
45
         * @param array $ref List of referenced domains that should be fetched too
46
         * @return array Multi-dimensional associative list of order IDs as keys and order address type/item pairs as values
47
         */
48
        protected function getAddresses( array $ids, array $ref ) : array
49
        {
50
                $items = [];
34✔
51
                $manager = $this->object()->getSubManager( 'address' );
34✔
52

53
                $filter = $manager->filter()
34✔
54
                        ->add( 'order.address.parentid', '==', $ids )
34✔
55
                        ->order( ['order.address.type', 'order.address.position', 'order.address.id'] )
34✔
56
                        ->slice( 0, 0x7fffffff );
34✔
57

58
                foreach( $manager->search( $filter, $ref ) as $item ) {
34✔
59
                        $items[$item->getParentId()][] = $item;
32✔
60
                }
61

62
                return $items;
34✔
63
        }
64

65

66
        /**
67
         * Returns the coupon map for the given order IDs
68
         *
69
         * @param string[] $ids List of order IDs
70
         * @param array $products Associative list of IDs and order product ID/item pairs as values
71
         * @return array Multi-dimensional associative list of order IDs as keys and coupons with product items as values
72
         */
73
        protected function getCoupons( array $ids, array $products = [] ) : array
74
        {
75
                $map = $productMap = [];
28✔
76
                $manager = $this->object()->getSubManager( 'coupon' );
28✔
77

78
                foreach( $products as $id => $list )
28✔
79
                {
80
                        if( !isset( $productMap[$id] ) ) {
26✔
81
                                $productMap[$id] = [];
26✔
82
                        }
83

84
                        foreach( $list as $key => $product ) {
26✔
85
                                $productMap[$id][$product->getId()] = $product;
26✔
86
                        }
87
                }
88

89
                $filter = $manager->filter()
28✔
90
                        ->add( 'order.coupon.parentid', '==', $ids )
28✔
91
                        ->order( 'order.coupon.code' )
28✔
92
                        ->slice( 0, 0x7fffffff );
28✔
93

94
                foreach( $manager->search( $filter ) as $item )
28✔
95
                {
96
                        if( !isset( $map[$item->getParentId()][$item->getCode()] ) ) {
6✔
97
                                $map[$item->getParentId()][$item->getCode()] = [];
6✔
98
                        }
99

100
                        if( $item->getProductId() !== null && isset( $productMap[$item->getParentId()][$item->getProductId()] ) ) {
6✔
101
                                $map[$item->getParentId()][$item->getCode()][] = $productMap[$item->getParentId()][$item->getProductId()];
5✔
102
                        }
103
                }
104

105
                return $map;
28✔
106
        }
107

108

109
        /**
110
         * Retrieves the ordered products from the storage.
111
         *
112
         * @param string[] $ids List of order IDs
113
         * @param array $ref List of referenced domains that should be fetched too
114
         * @return array Multi-dimensional associative list of order IDs as keys and order product
115
         *        IDs/items pairs in reversed order as values
116
         */
117
        protected function getProducts( array $ids, array $ref ) : array
118
        {
119
                $map = $attributes = $subProducts = [];
40✔
120
                $manager = $this->object()->getSubManager( 'product' );
40✔
121
                $attrManager = $manager->getSubManager( 'attribute' );
40✔
122

123
                $filter = $manager->filter()
40✔
124
                        ->add( 'order.product.parentid', '==', $ids )
40✔
125
                        ->order( 'order.product.position' )
40✔
126
                        ->slice( 0, 0x7fffffff );
40✔
127
                $items = $manager->search( $filter, $ref )->reverse();
40✔
128

129
                $search = $attrManager->filter()
40✔
130
                        ->add( 'order.product.attribute.parentid', '==', $items->keys() )
40✔
131
                        ->order( 'order.product.attribute.id' )
40✔
132
                        ->slice( 0, 0x7fffffff );
40✔
133

134
                foreach( $attrManager->search( $search, $ref ) as $id => $attribute ) {
40✔
135
                        $attributes[$attribute->getParentId()][$id] = $attribute;
18✔
136
                }
137

138
                foreach( $items as $id => $item )
40✔
139
                {
140
                        if( isset( $attributes[$id] ) ) {
38✔
141
                                $item->setAttributeItems( $attributes[$id] );
18✔
142
                        }
143

144
                        if( $item->getOrderProductId() === null )
38✔
145
                        {
146
                                ksort( $subProducts ); // bring the array into the right order because it's reversed
38✔
147
                                $item->setProducts( $subProducts );
38✔
148
                                $map[$item->getParentId()][$item->getPosition()] = $item;
38✔
149

150
                                $subProducts = [];
38✔
151
                        }
152
                        else
153
                        {        // in case it's a sub-product
154
                                $subProducts[$item->getPosition()] = $item;
20✔
155
                        }
156
                }
157

158
                foreach( $map as $key => $list ) {
40✔
159
                        ksort( $map[$key] );
38✔
160
                }
161

162
                return $map;
40✔
163
        }
164

165

166
        /**
167
         * Retrieves the order services from the storage.
168
         *
169
         * @param string[] $ids List of order IDs
170
         * @param array $ref List of referenced domains that should be fetched too
171
         * @return array Multi-dimensional associative list of order IDs as keys and service type/items pairs as values
172
         */
173
        protected function getServices( array $ids, array $ref ) : array
174
        {
175
                $map = [];
35✔
176
                $manager = $this->object()->getSubManager( 'service' );
35✔
177

178
                $filter = $manager->filter()
35✔
179
                        ->add( 'order.service.parentid', '==', $ids )
35✔
180
                        ->order( ['order.service.type', 'order.service.position', 'order.service.id'] )
35✔
181
                        ->slice( 0, 0x7fffffff );
35✔
182

183
                foreach( $manager->search( $filter, $ref ) as $item ) {
35✔
184
                        $map[$item->getParentId()][] = $item;
33✔
185
                }
186

187
                return $map;
35✔
188
        }
189

190

191
        /**
192
         * Saves the addresses of the order to the storage.
193
         *
194
         * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing address items
195
         * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
196
         */
197
        protected function saveAddresses( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
198
        {
199
                $addresses = $basket->getAddresses()->flat( 1 );
10✔
200

201
                foreach( $addresses as $address )
10✔
202
                {
203
                        if( $address->getParentId() != $basket->getId() ) {
5✔
204
                                $address->setId( null ); // create new item if copied
5✔
205
                        }
206

207
                        $address->setParentId( $basket->getId() );
5✔
208
                }
209

210
                $this->object()->getSubManager( 'address' )->save( $addresses );
10✔
211

212
                return $this;
10✔
213
        }
214

215

216
        /**
217
         * Saves the coupons of the order to the storage.
218
         *
219
         * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing coupon items
220
         * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
221
         */
222
        protected function saveCoupons( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
223
        {
224
                $manager = $this->object()->getSubManager( 'coupon' );
10✔
225
                $filter = $manager->filter()->add( 'order.coupon.parentid', '==', $basket->getId() )->slice( 0, 0x7fffffff );
10✔
226
                $items = $manager->search( $filter )->groupBy( 'order.coupon.code' );
10✔
227

228
                foreach( $basket->getCoupons() as $code => $products )
10✔
229
                {
230
                        if( empty( $products ) )
3✔
231
                        {
232
                                $item = !empty( $items[$code] ) ? current( $items[$code] ) : $manager->create()->setParentId( $basket->getId() );
1✔
233
                                $manager->save( $item->setCode( $code ) );
1✔
234
                                continue;
1✔
235
                        }
236

237
                        foreach( $products as $product )
2✔
238
                        {
239
                                foreach( $items[$code] ?? [] as $prodItem )
2✔
240
                                {
241
                                        if( $product->getId() === $prodItem->getId() ) {
1✔
242
                                                continue 2;
×
243
                                        }
244
                                }
245

246
                                $manager->save( $manager->create()->setParentId( $basket->getId() )->setCode( $code )->setProductId( $product->getId() ) );
2✔
247
                        }
248
                }
249

250
                return $this;
10✔
251
        }
252

253

254
        /**
255
         * Saves the ordered products to the storage.
256
         *
257
         * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing ordered products or bundles
258
         * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
259
         */
260
        protected function saveProducts( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
261
        {
262
                $products = $basket->getProducts();
10✔
263
                $pos = (int) $products->merge( $products->getProducts()->flat( 1 ) )->max( 'order.product.position' );
10✔
264

265
                foreach( $products as $product )
10✔
266
                {
267
                        if( $product->getParentId() != $basket->getId() ) {
5✔
268
                                $product->setId( null ); // create new item if copied
5✔
269
                        }
270

271
                        if( !$product->getPosition() ) {
5✔
272
                                $product->setPosition( ++$pos );
5✔
273
                        }
274

275
                        $product->setParentId( $basket->getId() );
5✔
276

277
                        foreach( $product->getProducts() as $subProduct )
5✔
278
                        {
279
                                if( $subProduct->getParentId() != $basket->getId() ) {
1✔
280
                                        $subProduct->setId( null ); // create new item if copied
1✔
281
                                }
282

283
                                if( !$subProduct->getPosition() ) {
1✔
284
                                        $subProduct->setPosition( ++$pos );
1✔
285
                                }
286

287
                                $subProduct->setParentId( $basket->getId() );
1✔
288
                        }
289
                }
290

291
                $this->object()->getSubManager( 'product' )->save( $products );
10✔
292

293
                return $this;
10✔
294
        }
295

296

297
        /**
298
         * Saves the services of the order to the storage.
299
         *
300
         * @param \Aimeos\MShop\Order\Item\Iface $basket Basket containing service items
301
         * @return \Aimeos\MShop\Order\Manager\Iface Manager object for chaining method calls
302
         */
303
        protected function saveServices( \Aimeos\MShop\Order\Item\Iface $basket ) : \Aimeos\MShop\Order\Manager\Iface
304
        {
305
                $services = $basket->getServices()->flat( 1 );
10✔
306
                $pos = (int) $services->max( 'order.service.position' );
10✔
307

308
                foreach( $services as $service )
10✔
309
                {
310
                        if( $service->getParentId() != $basket->getId() ) {
5✔
311
                                $service->setId( null ); // create new item if copied
5✔
312
                        }
313

314
                        if( !$service->getPosition() ) {
5✔
NEW
315
                                $service->setPosition( ++$pos );
×
316
                        }
317

318
                        $service->setParentId( $basket->getId() );
5✔
319
                }
320

321
                $this->object()->getSubManager( 'service' )->save( $services );
10✔
322

323
                return $this;
10✔
324
        }
325
}
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

© 2025 Coveralls, Inc