Passed
Pull Request — master (#19)
by
unknown
08:01 queued 04:49
created

CustomerObserver::formatDobDate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 6
c 2
b 0
f 0
dl 0
loc 14
rs 10
cc 2
nc 2
nop 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Customer\Observers\CustomerObserver
5
 *
6
 * PHP version 7
7
 *
8
 * @author    Tim Wagner <[email protected]>
9
 * @copyright 2018 TechDivision GmbH <[email protected]>
10
 * @license   https://opensource.org/licenses/MIT
11
 * @link      https://github.com/techdivision/import-customer
12
 * @link      http://www.techdivision.com
13
 */
14
15
namespace TechDivision\Import\Customer\Observers;
16
17
use TechDivision\Import\Utils\EntityTypeCodes;
18
use TechDivision\Import\Observers\StateDetectorInterface;
19
use TechDivision\Import\Customer\Utils\GenderKeys;
20
use TechDivision\Import\Customer\Utils\ColumnKeys;
21
use TechDivision\Import\Customer\Utils\MemberNames;
22
use TechDivision\Import\Customer\Services\CustomerBunchProcessorInterface;
23
24
/**
25
 * Observer that create's the customer itself.
26
 *
27
 * @author    Tim Wagner <[email protected]>
28
 * @copyright 2018 TechDivision GmbH <[email protected]>
29
 * @license   https://opensource.org/licenses/MIT
30
 * @link      https://github.com/techdivision/import-customer
31
 * @link      http://www.techdivision.com
32
 */
33
class CustomerObserver extends AbstractCustomerImportObserver
34
{
35
36
    /**
37
     * The customer bunch processor instance.
38
     *
39
     * @var \TechDivision\Import\Customer\Services\CustomerBunchProcessorInterface
40
     */
41
    protected $customerBunchProcessor;
42
43
    /**
44
     * The array with the available gender keys.
45
     *
46
     * @var array
47
     */
48
    protected $availableGenders = array(
49
        'Male'          => GenderKeys::GENDER_MALE,
50
        'Female'        => GenderKeys::GENDER_FEMALE,
51
        'Not Specified' => GenderKeys::GENDER_NOT_SPECIFIED
52
    );
53
54
    /**
55
     * Initializes the observer with the state detector instance.
56
     *
57
     * @param \TechDivision\Import\Customer\Services\CustomerBunchProcessorInterface $customerBunchProcessor The customer bunch processor instance
58
     * @param \TechDivision\Import\Observers\StateDetectorInterface                  $stateDetector          The state detector instance
59
     */
60
    public function __construct(
61
        CustomerBunchProcessorInterface $customerBunchProcessor,
62
        StateDetectorInterface $stateDetector = null
63
    ) {
64
65
        // set the customer processor and the raw entity loader
66
        $this->customerBunchProcessor = $customerBunchProcessor;
67
68
        // pass the state detector to the parent constructor
69
        parent::__construct($stateDetector);
70
    }
71
72
    /**
73
     * Return's the customer bunch processor instance.
74
     *
75
     * @return \TechDivision\Import\Customer\Services\CustomerBunchProcessorInterface The customer bunch processor instance
76
     */
77
    protected function getCustomerBunchProcessor()
78
    {
79
        return $this->customerBunchProcessor;
80
    }
81
82
    /**
83
     * Process the observer's business logic.
84
     *
85
     * @return void
86
     */
87
    protected function process()
88
    {
89
90
        // load email and website code
91
        $email = $this->getValue(ColumnKeys::EMAIL);
92
        $website = $this->getValue(ColumnKeys::WEBSITE);
93
94
        // query whether or not, we've found a new SKU => means we've found a new customer
95
        if ($this->hasBeenProcessed(array($email, $website))) {
96
            return;
97
        }
98
99
        // prepare the static entity values
100
        $customer = $this->initializeCustomer($this->prepareAttributes());
101
102
        // insert the entity and set the entity ID
103
        $this->setLastEntityId($this->persistCustomer($customer));
104
    }
105
106
    /**
107
     * Prepare the attributes of the entity that has to be persisted.
108
     *
109
     * @return array The prepared attributes
110
     */
111
    protected function prepareAttributes()
112
    {
113
114
        // initialize the customer values
115
        $email = $this->getValue(ColumnKeys::EMAIL);
116
        $groupId = $this->getValue(ColumnKeys::GROUP_ID);
117
        $storeId = $this->getValue(ColumnKeys::STORE_ID);
118
        $disableAutoGroupChange = $this->getValue(ColumnKeys::DISABLE_AUTO_GROUP_CHANGE);
119
        $prefix = $this->getValue(ColumnKeys::PREFIX);
120
        $firstname = $this->getValue(ColumnKeys::FIRSTNAME);
121
        $middlename = $this->getValue(ColumnKeys::MIDDLENAME);
122
        $lastname = $this->getValue(ColumnKeys::LASTNAME);
123
        $suffix = $this->getValue(ColumnKeys::SUFFIX);
124
        $passwordHash = $this->getValue(ColumnKeys::PASSWORD_HASH);
125
        $rpToken = $this->getValue(ColumnKeys::RP_TOKEN);
126
        $defaultShipping = $this->getValue(ColumnKeys::ADDRESS_DEFAULT_SHIPPING);
127
        $defaultBilling = $this->getValue(ColumnKeys::ADDRESS_DEFAULT_BILLING);
128
        $taxvat = $this->getValue(ColumnKeys::TAXVAT);
129
        $confirmation = $this->getValue(ColumnKeys::CONFIRMATION);
130
        $gender = $this->getGenderByValue($this->getValue(ColumnKeys::GENDER));
131
132
        // load the store id if a store code is present in the current row
133
        if (($storeCode = $this->getValue(ColumnKeys::STORE))) {
134
            $storeId = $this->getStoreIdByCode($storeCode);
135
        }
136
137
        // throw exception if neither the store id nor the store code are available
138
        if ($storeId === null) {
139
            throw new \Exception(
140
                sprintf(
141
                    'Expected value for either _store or store_id, none found in file %s on line %d',
142
                    $this->getFilename(),
143
                    $this->getLineNumber()
144
                )
145
            );
146
        }
147
148
        // load the customer's additional attributes
149
        $createdIn = $this->getValue(ColumnKeys::CREATED_IN);
150
        $isActive = 1;
151
        $failuresNum = 0;
152
        $firstFailure = null;
153
        $lockExpires = null;
154
155
        // prepare the date format for the created at/updated at dates
156
        $websiteId = $this->getStoreWebsiteIdByCode($this->getValue(ColumnKeys::WEBSITE));
157
        $incrementId = $this->getValue(ColumnKeys::INCREMENT_ID);
158
        $dob = $this->getValue(ColumnKeys::DOB, 'Y-m-d H:i:s', array($this, 'formatDobDate'));
159
        $createdAt = $this->getValue(ColumnKeys::CREATED_AT, date('Y-m-d H:i:s'), array($this, 'formatDate'));
160
        $updatedAt = $this->getValue(ColumnKeys::UPDATED_AT, date('Y-m-d H:i:s'), array($this, 'formatDate'));
161
        $rpTokenCreatedAt = $this->getValue(ColumnKeys::RP_TOKEN_CREATED_AT, null, array($this, 'formatDate'));
162
        $sessionCutoff = $this->getValue(ColumnKeys::SESSION_CUTOFF, null, array($this, 'formatDate'));
163
164
        // return the prepared customer
165
        return $this->initializeEntity(
166
            $this->loadRawEntity(
167
                array(
168
                    MemberNames::WEBSITE_ID                => $websiteId,
169
                    MemberNames::EMAIL                     => $email,
170
                    MemberNames::GROUP_ID                  => $groupId,
171
                    MemberNames::INCREMENT_ID              => $incrementId,
172
                    MemberNames::STORE_ID                  => $storeId,
173
                    MemberNames::CREATED_AT                => $createdAt,
174
                    MemberNames::UPDATED_AT                => $updatedAt,
175
                    MemberNames::IS_ACTIVE                 => $isActive,
176
                    MemberNames::DISABLE_AUTO_GROUP_CHANGE => $disableAutoGroupChange,
177
                    MemberNames::CREATED_IN                => $createdIn,
178
                    MemberNames::PREFIX                    => $prefix,
179
                    MemberNames::FIRSTNAME                 => $firstname,
180
                    MemberNames::MIDDLENAME                => $middlename,
181
                    MemberNames::LASTNAME                  => $lastname,
182
                    MemberNames::SUFFIX                    => $suffix,
183
                    MemberNames::DOB                       => $dob,
184
                    MemberNames::PASSWORD_HASH             => $passwordHash,
185
                    MemberNames::RP_TOKEN                  => $rpToken,
186
                    MemberNames::RP_TOKEN_CREATED_AT       => $rpTokenCreatedAt,
187
                    MemberNames::DEFAULT_BILLING           => $defaultBilling,
188
                    MemberNames::DEFAULT_SHIPPING          => $defaultShipping,
189
                    MemberNames::TAXVAT                    => $taxvat,
190
                    MemberNames::CONFIRMATION              => $confirmation,
191
                    MemberNames::GENDER                    => $gender,
192
                    MemberNames::FAILURES_NUM              => $failuresNum,
193
                    MemberNames::FIRST_FAILURE             => $firstFailure,
194
                    MemberNames::LOCK_EXPIRES              => $lockExpires,
195
                    MemberNames::SESSION_CUTOFF           => $sessionCutoff
196
                )
197
            )
198
        );
199
    }
200
201
    /**
202
     * Load's and return's a raw customer entity without primary key but the mandatory members only and nulled values.
203
     *
204
     * @param array $data An array with data that will be used to initialize the raw entity with
205
     *
206
     * @return array The initialized entity
207
     */
208
    protected function loadRawEntity(array $data = array())
209
    {
210
        return $this->getCustomerBunchProcessor()->loadRawEntity(EntityTypeCodes::CUSTOMER, $data);
211
    }
212
213
    /**
214
     * Initialize the customer with the passed attributes and returns an instance.
215
     *
216
     * @param array $attr The customer attributes
217
     *
218
     * @return array The initialized customer
219
     */
220
    protected function initializeCustomer(array $attr)
221
    {
222
223
        // load the customer with the passed SKU and merge it with the attributes
224
        if ($entity = $this->loadCustomerByEmailAndWebsiteId($attr[MemberNames::EMAIL], $attr[MemberNames::WEBSITE_ID])) {
225
            return $this->mergeEntity($entity, $attr);
226
        }
227
228
        // otherwise simply return the attributes
229
        return $attr;
230
    }
231
232
    /**
233
     * Return's the gender ID for the passed value.
234
     *
235
     * @param string $value The value to return the gender ID for
236
     *
237
     * @return integer The gender ID
238
     * @throws \Exception Is thrown, if the gender ID with the requested value is not available
239
     */
240
    protected function getGenderByValue($value)
241
    {
242
243
        // query whether or not, the requested gender ID is available
244
        if (isset($this->availableGenders[$value])) {
245
            return (integer) $this->availableGenders[$value];
246
        }
247
248
        // allow null values and empty strings
249
        if ($value === null || $value === '') {
250
            return null;
251
        }
252
253
        // throw an exception, if not
254
        throw new \Exception(
255
            $this->appendExceptionSuffix(
256
                sprintf('Found invalid gender %s', $value)
257
            )
258
        );
259
    }
260
261
    /**
262
     * Returns the store id for the specified store code.
263
     *
264
     * @param string $code The store code
265
     *
266
     * @return integer The store id
267
     */
268
    protected function getStoreIdByCode($code)
269
    {
270
        return $this->getSubject()->getStoreId($code);
271
    }
272
273
    /**
274
     * Return's the store website for the passed code.
275
     *
276
     * @param string $code The code of the store website to return the ID for
277
     *
278
     * @return integer The store website ID
279
     */
280
    protected function getStoreWebsiteIdByCode($code)
281
    {
282
        return $this->getSubject()->getStoreWebsiteIdByCode($code);
283
    }
284
285
    /**
286
     * Return's the customer with the passed email and website ID.
287
     *
288
     * @param string $email     The email of the customer to return
289
     * @param string $websiteId The website ID of the customer to return
290
     *
291
     * @return array|null The customer
292
     */
293
    protected function loadCustomerByEmailAndWebsiteId($email, $websiteId)
294
    {
295
        return $this->getCustomerBunchProcessor()->loadCustomerByEmailAndWebsiteId($email, $websiteId);
296
    }
297
298
    /**
299
     * Persist's the passed customer data and return's the ID.
300
     *
301
     * @param array $customer The customer data to persist
302
     *
303
     * @return string The ID of the persisted entity
304
     */
305
    protected function persistCustomer($customer)
306
    {
307
        return $this->getCustomerBunchProcessor()->persistCustomer($customer);
308
    }
309
310
    /**
311
     * Return's the attribute set of the customer that has to be created.
312
     *
313
     * @return array The attribute set
314
     */
315
    protected function getAttributeSet()
316
    {
317
        return $this->getSubject()->getAttributeSet();
318
    }
319
320
    /**
321
     * Set's the ID of the customer that has been created recently.
322
     *
323
     * @param string $lastEntityId The entity ID
324
     *
325
     * @return void
326
     */
327
    protected function setLastEntityId($lastEntityId)
328
    {
329
        $this->getSubject()->setLastEntityId($lastEntityId);
330
    }
331
332
    /**
333
     * @param string $value DOB value
334
     *
335
     * @return null|string
336
     */
337
    protected function formatDobDate($value)
338
    {
339
        // try to format the date according to the configured date format
340
        $formattedDate = $this->getSubject()->getDateConverter()->convert($value);
341
342
        $format = 'Y-m-d H:i:s';
343
        $dateTime = \DateTime::createFromFormat($format, $formattedDate);
344
345
        if (!$dateTime) {
0 ignored issues
show
introduced by
$dateTime is of type DateTime, thus it always evaluated to true.
Loading history...
346
            return null;
347
        }
348
349
        // return the formatted date
350
        return $formattedDate;
351
    }
352
}
353