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

aimeos / aimeos-core / 7b21ec73-ce77-471a-ace6-832bad7c3dd8

11 Sep 2024 10:51AM UTC coverage: 92.207% (-0.08%) from 92.288%
7b21ec73-ce77-471a-ace6-832bad7c3dd8

push

circleci

aimeos
Simplified customer item constructor and used password object from context

18 of 19 new or added lines in 3 files covered. (94.74%)

9 existing lines in 1 file now uncovered.

9667 of 10484 relevant lines covered (92.21%)

72.51 hits per line

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

75.51
/src/MShop/Customer/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 Customer
8
 */
9

10

11
namespace Aimeos\MShop\Customer\Manager;
12

13

14
/**
15
 * Base class with common methods for all customer implementations.
16
 *
17
 * @package MShop
18
 * @subpackage Customer
19
 */
20
abstract class Base
21
        extends \Aimeos\MShop\Common\Manager\Base
22
{
23
        use \Aimeos\MShop\Common\Manager\ListsRef\Traits;
24
        use \Aimeos\MShop\Common\Manager\AddressRef\Traits;
25
        use \Aimeos\MShop\Common\Manager\PropertyRef\Traits;
26

27

28
        /* @deprecated 2025.01 Use $this->context()->password() instead */
29
        private ?\Aimeos\MShop\Common\Helper\Password\Iface $helper = null;
30

31

32
        /**
33
         * Initializes a new customer manager object using the given context object.
34
         *
35
         * @param \Aimeos\MShop\ContextIface $context Context object with required objects
36
         */
37
        public function __construct( \Aimeos\MShop\ContextIface $context )
38
        {
39
                parent::__construct( $context );
46✔
40

41
                /** mshop/customer/manager/resource
42
                 * Name of the database connection resource to use
43
                 *
44
                 * You can configure a different database connection for each data domain
45
                 * and if no such connection name exists, the "db" connection will be used.
46
                 * It's also possible to use the same database connection for different
47
                 * data domains by configuring the same connection name using this setting.
48
                 *
49
                 * @param string Database connection name
50
                 * @since 2023.04
51
                 */
52
                $this->setResourceName( $context->config()->get( 'mshop/customer/manager/resource', 'db-customer' ) );
46✔
53
        }
54

55

56
        /**
57
         * Counts the number items that are available for the values of the given key.
58
         *
59
         * @param \Aimeos\Base\Criteria\Iface $search Search criteria
60
         * @param array|string $key Search key or list of key to aggregate items for
61
         * @param string|null $value Search key for aggregating the value column
62
         * @param string|null $type Type of the aggregation, empty string for count or "sum" or "avg" (average)
63
         * @return \Aimeos\Map List of the search keys as key and the number of counted items as value
64
         */
65
        public function aggregate( \Aimeos\Base\Criteria\Iface $search, $key, string $value = null, string $type = null ) : \Aimeos\Map
66
        {
67
                /** mshop/customer/manager/aggregate/mysql
68
                 * Counts the number of records grouped by the values in the key column and matched by the given criteria
69
                 *
70
                 * @see mshop/customer/manager/aggregate/ansi
71
                 */
72

73
                /** mshop/customer/manager/aggregate/ansi
74
                 * Counts the number of records grouped by the values in the key column and matched by the given criteria
75
                 *
76
                 * Groups all records by the values in the key column and counts their
77
                 * occurence. The matched records can be limited by the given criteria
78
                 * from the customer database. The records must be from one of the sites
79
                 * that are configured via the context item. If the current site is part
80
                 * of a tree of sites, the statement can count all records from the
81
                 * current site and the complete sub-tree of sites.
82
                 *
83
                 * As the records can normally be limited by criteria from sub-managers,
84
                 * their tables must be joined in the SQL context. This is done by
85
                 * using the "internaldeps" property from the definition of the ID
86
                 * column of the sub-managers. These internal dependencies specify
87
                 * the JOIN between the tables and the used columns for joining. The
88
                 * ":joins" placeholder is then replaced by the JOIN strings from
89
                 * the sub-managers.
90
                 *
91
                 * To limit the records matched, conditions can be added to the given
92
                 * criteria object. It can contain comparisons like column names that
93
                 * must match specific values which can be combined by AND, OR or NOT
94
                 * operators. The resulting string of SQL conditions replaces the
95
                 * ":cond" placeholder before the statement is sent to the database
96
                 * server.
97
                 *
98
                 * This statement doesn't return any records. Instead, it returns pairs
99
                 * of the different values found in the key column together with the
100
                 * number of records that have been found for that key values.
101
                 *
102
                 * The SQL statement should conform to the ANSI standard to be
103
                 * compatible with most relational database systems. This also
104
                 * includes using double quotes for table and column names.
105
                 *
106
                 * @param string SQL statement for aggregating customer items
107
                 * @since 2021.04
108
                 * @see mshop/customer/manager/insert/ansi
109
                 * @see mshop/customer/manager/update/ansi
110
                 * @see mshop/customer/manager/newid/ansi
111
                 * @see mshop/customer/manager/delete/ansi
112
                 * @see mshop/customer/manager/search/ansi
113
                 * @see mshop/customer/manager/count/ansi
114
                 */
115

116
                $cfgkey = 'mshop/customer/manager/aggregate';
2✔
117
                return $this->aggregateBase( $search, $key, $cfgkey, ['customer'], $value, $type );
2✔
118
        }
119

120

121
        /**
122
         * Creates a filter object.
123
         *
124
         * @param bool|null $default Add default criteria or NULL for relaxed default criteria
125
         * @param bool $site TRUE for adding site criteria to limit items by the site of related items
126
         * @return \Aimeos\Base\Criteria\Iface Returns the filter object
127
         */
128
        public function filter( ?bool $default = false, bool $site = false ) : \Aimeos\Base\Criteria\Iface
129
        {
130
                return $this->filterBase( 'customer', $default );
34✔
131
        }
132

133

134
        /**
135
         * Returns the item specified by its code and domain/type if necessary
136
         *
137
         * @param string $code Code of the item
138
         * @param string[] $ref List of domains to fetch list items and referenced items for
139
         * @param string|null $domain Domain of the item if necessary to identify the item uniquely
140
         * @param string|null $type Type code of the item if necessary to identify the item uniquely
141
         * @param bool|null $default Add default criteria or NULL for relaxed default criteria
142
         * @return \Aimeos\MShop\Customer\Item\Iface Item object
143
         */
144
        public function find( string $code, array $ref = [], string $domain = null, string $type = null,
145
                ?bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
146
        {
147
                return $this->findBase( array( 'customer.code' => $code ), $ref, $default );
15✔
148
        }
149

150

151
        /**
152
         * Returns the customer item object specificed by its ID.
153
         *
154
         * @param string $id Unique customer ID referencing an existing customer
155
         * @param string[] $ref List of domains to fetch list items and referenced items for
156
         * @param bool|null $default Add default criteria or NULL for relaxed default criteria
157
         * @return \Aimeos\MShop\Customer\Item\Iface Returns the customer item of the given id
158
         * @throws \Aimeos\MShop\Exception If item couldn't be found
159
         */
160
        public function get( string $id, array $ref = [], ?bool $default = false ) : \Aimeos\MShop\Common\Item\Iface
161
        {
162
                return $this->getItemBase( 'customer.id', $id, $ref, $default );
5✔
163
        }
164

165

166
        /**
167
         * Adds the customer to the groups listed in the customer item
168
         *
169
         * @param \Aimeos\MShop\Customer\Item\Iface $item Customer item
170
         * @return \Aimeos\MShop\Customer\Item\Iface $item Modified customer item
171
         */
172
        protected function addGroups( \Aimeos\MShop\Customer\Item\Iface $item ): \Aimeos\MShop\Customer\Item\Iface
173
        {
174
                $pos = 0;
3✔
175
                $groupIds = [];
3✔
176

177
                $manager = $this->object()->getSubManager( 'lists' );
3✔
178
                $listItems = $item->getListItems( 'group', 'default', null, false );
3✔
179

180
                foreach( $item->getGroups() as $refId => $code )
3✔
181
                {
182
                        if( ( $litem = $item->getListItem( 'group', 'default', $refId, false ) ) !== null ) {
1✔
183
                                unset( $listItems[$litem->getId()], $listItems['__group_default_' . $refId] );
×
184
                        } else {
185
                                $litem = $manager->create()->setType( 'default' );
1✔
186
                        }
187

188
                        $item->addListItem( 'group', $litem->setRefId( $refId )->setPosition( $pos++ ) );
1✔
189
                }
190

191
                return $item->deleteListItems( $listItems );
3✔
192
        }
193

194

195
        /**
196
         * Creates a new customer item.
197
         *
198
         * @param array $values List of attributes for customer item
199
         * @param \Aimeos\MShop\Common\Item\Lists\Iface[] $listItems List of list items
200
         * @param \Aimeos\MShop\Common\Item\Iface[] $refItems List of referenced items
201
         * @param \Aimeos\MShop\Common\Item\Address\Iface[] $addrItems List of address items
202
         * @param \Aimeos\MShop\Common\Item\Property\Iface[] $propItems List of property items
203
         * @return \Aimeos\MShop\Customer\Item\Iface New customer item
204
         */
205
        protected function createItemBase( array $values = [], array $listItems = [], array $refItems = [],
206
                array $addrItems = [], array $propItems = [] ) : \Aimeos\MShop\Common\Item\Iface
207
        {
208
                $values['.listitems'] = $listItems;
32✔
209
                $values['.propitems'] = $propItems;
32✔
210
                $values['.addritems'] = $addrItems;
32✔
211

212
                $address = new \Aimeos\MShop\Common\Item\Address\Standard( 'customer.', $values );
32✔
213
                return new \Aimeos\MShop\Customer\Item\Standard( $address, 'customer.', $values, $this->context()->password() );
32✔
214
        }
215

216

217
        /**
218
         * Deletes items.
219
         *
220
         * @param \Aimeos\MShop\Common\Item\Iface|\Aimeos\Map|array|string $items List of item objects or IDs of the items
221
         * @param string $cfgpath Configuration path to the SQL statement
222
         * @param bool $siteid If siteid should be used in the statement
223
         * @param string $name Name of the ID column
224
         * @return \Aimeos\MShop\Common\Manager\Iface Manager object for chaining method calls
225
         */
226
        protected function deleteItemsBase( $items, string $cfgpath, bool $siteid = true,
227
                string $name = 'id' ) : \Aimeos\MShop\Common\Manager\Iface
228
        {
229
                if( map( $items )->isEmpty() ) {
3✔
230
                        return $this;
×
231
                }
232

233
                $search = $this->object()->filter();
3✔
234
                $search->setConditions( $search->compare( '==', $name, $items ) );
3✔
235

236
                $types = array( $name => \Aimeos\Base\DB\Statement\Base::PARAM_STR );
3✔
237
                $translations = array( $name => '"' . $name . '"' );
3✔
238

239
                $cond = $search->getConditionSource( $types, $translations );
3✔
240
                $sql = str_replace( ':cond', $cond, $this->getSqlConfig( $cfgpath ) );
3✔
241

242
                $context = $this->context();
3✔
243
                $conn = $context->db( $this->getResourceName() );
3✔
244

245
                $stmt = $conn->create( $sql );
3✔
246

247
                if( $siteid )
3✔
248
                {
249
                        $stmt->bind( 1, $context->locale()->getSiteId() . '%' );
3✔
250
                        $stmt->bind( 2, $this->getUser()?->getSiteId() );
3✔
251
                }
252

253
                $stmt->execute()->finish();
3✔
254

255
                return $this;
3✔
256
        }
257

258

259
        /**
260
         * Returns a password helper object based on the configuration.
261
         *
262
         * @return \Aimeos\MShop\Common\Helper\Password\Iface Password helper object
263
         * @throws \LogicException If the name is invalid or the class isn't found
264
         * @deprecated 2025.01 Use $this->context()->password() instead
265
         */
266
        protected function getPasswordHelper() : \Aimeos\MShop\Common\Helper\Password\Iface
267
        {
UNCOV
268
                if( $this->helper ) {
×
UNCOV
269
                        return $this->helper;
×
270
                }
271

UNCOV
272
                $config = $this->context()->config();
×
273

274
                /** mshop/customer/manager/password/name
275
                 * Last part of the name for building the password helper item
276
                 *
277
                 * The password helper encode given passwords and salts using the
278
                 * implemented hashing method in the required format. String format and
279
                 * hash algorithm needs to be the same when comparing the encoded
280
                 * password to the one provided by the user after login.
281
                 *
282
                 * @param string Name of the password helper implementation
283
                 * @since 2015.01
284
                 * @see mshop/customer/manager/salt
285
                 * @see mshop/customer/manager/password/options
286
                 */
UNCOV
287
                $name = $config->get( 'mshop/customer/manager/password/name', 'Standard' );
×
288

289
                /** mshop/customer/manager/password/options
290
                 * List of options used by the password helper classes
291
                 *
292
                 * Each hash method may need an arbitrary number of options specific
293
                 * for the hash method. This may include the number of iterations the
294
                 * method is applied or the separator between salt and password.
295
                 *
296
                 * @param string Associative list of key/value pairs
297
                 * @since 2015.01
298
                 * @see mshop/customer/manager/password/name
299
                 * @sse mshop/customer/manager/salt
300
                 */
UNCOV
301
                $options = $config->get( 'mshop/customer/manager/password/options', [] );
×
302

UNCOV
303
                if( ctype_alnum( $name ) === false ) {
×
304
                        throw new \LogicException( sprintf( 'Invalid characters in class name "%1$s"', $name ), 400 );
×
305
                }
306

UNCOV
307
                $classname = '\Aimeos\MShop\Common\Helper\Password\\' . $name;
×
UNCOV
308
                $interface = \Aimeos\MShop\Common\Helper\Password\Iface::class;
×
309

UNCOV
310
                return $this->helper = \Aimeos\Utils::create( $classname, [$options], $interface );
×
311
        }
312

313

314
        /**
315
         * Returns the currently authenticated user
316
         *
317
         * @return \Aimeos\MShop\Customer\Item\Iface|null Customer item or NULL if not available
318
         * @deprecated 2025.01 Use $this->context()->user() instead
319
         */
320
        protected function getUser() : ?\Aimeos\MShop\Customer\Item\Iface
321
        {
322
                return $this->context()->user();
3✔
323
        }
324
}
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