Issues (20)

Provider/Provider.php (2 issues)

1
<?php
2
/**
3
 * Copyright © 2019 O2TI. All rights reserved.
4
 * See LICENSE.txt for license details.
5
 */
6
7
namespace O2TI\SocialLogin\Provider;
8
9
use Exception;
10
use Hybridauth\HybridauthFactory;
11
use Hybridauth\User\Profile as SocialProfile;
12
use Magento\Customer\Api\AccountManagementInterface;
13
use Magento\Customer\Api\CustomerRepositoryInterface;
14
use Magento\Customer\Api\Data\CustomerInterfaceFactory;
15
use Magento\Customer\Model\Account\Redirect as AccountRedirect;
16
use Magento\Customer\Model\Customer;
17
use Magento\Customer\Model\CustomerFactory;
18
use Magento\Customer\Model\ResourceModel\Customer as CustomerResource;
19
use Magento\Customer\Model\Session as CustomerSession;
20
use Magento\Customer\Model\Url as CustomerUrl;
21
use Magento\Framework\App\Config\ScopeConfigInterface;
22
use Magento\Framework\App\ObjectManager;
23
use Magento\Framework\Exception\LocalizedException;
24
use Magento\Framework\Message\ManagerInterface;
25
use Magento\Framework\Session\SessionManagerInterface;
26
use Magento\Framework\Stdlib\Cookie\CookieMetadataFactory;
27
use Magento\Framework\Stdlib\CookieManagerInterface;
28
use Magento\Framework\UrlInterface;
29
use Magento\Store\Model\ScopeInterface;
30
use Magento\Store\Model\StoreManagerInterface;
31
32
/**
33
 * Provider section.
34
 *
35
 * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
36
 */
37
class Provider
38
{
39
    public const CONFIG_PATH_SOCIAL_LOGIN_ENABLED = 'social_login/general/enabled';
40
    public const CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_ENABLED = 'social_login/general/%s/enabled';
41
    public const CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_KEY = 'social_login/general/%s/api_key';
42
    public const CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_SECRET = 'social_login/general/%s/api_secret';
43
    public const COOKIE_NAME = 'login_redirect';
44
45
    /**
46
     * The providers we currently support.
47
     */
48
    public const PROVIDERS = [
49
        'facebook',
50
        'google',
51
        'WindowsLive',
52
    ];
53
54
    /**
55
     * @var HybridauthFactory
56
     */
57
    private $hybridauthFactory;
58
59
    /**
60
     * @var UrlInterface
61
     */
62
    private $url;
63
64
    /**
65
     * @var AccountManagementInterface
66
     */
67
    protected $accountManagement;
68
69
    /**
70
     * @var CustomerUrl
71
     */
72
    protected $customerUrl;
73
74
    /**
75
     * @var CustomerInterfaceFactory
76
     */
77
    protected $customerDataFactory;
78
79
    /**
80
     * @var CustomerFactory
81
     */
82
    private $customerFactory;
83
84
    /**
85
     * @var CustomerResource
86
     */
87
    private $customerResource;
88
89
    /**
90
     * @var CustomerSession
91
     */
92
    private $customerSession;
93
94
    /**
95
     * @var StoreManagerInterface
96
     */
97
    private $storeManager;
98
99
    /**
100
     * @var ScopeConfigInterface
101
     */
102
    private $scopeConfig;
103
104
    /**
105
     * @var CookieManagerInterface
106
     */
107
    private $cookieManager;
108
109
    /**
110
     * @var CookieMetadataFactory
111
     */
112
    private $cookieMetadataFactory;
113
114
    /**
115
     * @var SessionManagerInterface
116
     */
117
    private $sessionManager;
118
119
    /**
120
     * @var CustomerRepositoryInterface
121
     */
122
    protected $customerRepository;
123
124
    /**
125
     * @var ManagerInterface
126
     */
127
    private $messageManager;
128
129
    /**
130
     * @var AccountRedirect
131
     */
132
    protected $accountRedirect;
133
134
    /**
135
     * @param HybridauthFactory           $hybridauthFactory
136
     * @param UrlInterface                $url
137
     * @param AccountManagementInterface  $accountManagement
138
     * @param CustomerUrl                 $customerUrl
139
     * @param CustomerInterfaceFactory    $customerDataFactory
140
     * @param CustomerFactory             $customerFactory
141
     * @param CustomerResource            $customerResource
142
     * @param CustomerSession|null        $customerSession
143
     * @param StoreManagerInterface       $storeManager
144
     * @param ScopeConfigInterface        $scopeConfig
145
     * @param CookieManagerInterface      $cookieManager
146
     * @param CookieMetadataFactory       $cookieMetadataFactory
147
     * @param SessionManagerInterface     $sessionManager
148
     * @param CustomerRepositoryInterface $customerRepository
149
     * @param ManagerInterface            $messageManager
150
     * @param AccountRedirect             $accountRedirect
151
     */
152
    public function __construct(
153
        HybridauthFactory $hybridauthFactory,
154
        UrlInterface $url,
155
        AccountManagementInterface $accountManagement,
156
        CustomerUrl $customerUrl,
157
        CustomerInterfaceFactory $customerDataFactory,
158
        CustomerFactory $customerFactory,
159
        CustomerResource $customerResource,
160
        ?CustomerSession $customerSession = null,
161
        StoreManagerInterface $storeManager,
162
        ScopeConfigInterface $scopeConfig,
163
        CookieManagerInterface $cookieManager = null,
164
        CookieMetadataFactory $cookieMetadataFactory = null,
165
        SessionManagerInterface $sessionManager,
166
        CustomerRepositoryInterface $customerRepository,
167
        ManagerInterface $messageManager,
168
        AccountRedirect $accountRedirect
169
    ) {
170
        $this->hybridauthFactory = $hybridauthFactory;
171
        $this->url = $url;
172
        $this->accountManagement = $accountManagement;
173
        $this->customerUrl = $customerUrl;
174
        $this->customerDataFactory = $customerDataFactory;
175
        $this->customerFactory = $customerFactory;
176
        $this->customerResource = $customerResource;
177
        $this->customerSession = $customerSession ?? ObjectManager::getInstance()->get(CustomerSession::class);
178
        $this->storeManager = $storeManager;
179
        $this->scopeConfig = $scopeConfig;
180
        $this->cookieManager = $cookieManager ?:
181
            ObjectManager::getInstance()->get(CookieManagerInterface::class);
182
        $this->cookieMetadataFactory = $cookieMetadataFactory ?:
183
            ObjectManager::getInstance()->get(CookieMetadataFactory::class);
184
        $this->sessionManager = $sessionManager;
185
        $this->customerRepository = $customerRepository;
186
        $this->messageManager = $messageManager;
187
        $this->accountRedirect = $accountRedirect ?: ObjectManager::getInstance()->get(AccountRedirect::class);
188
    }
189
190
    /**
191
     * Implements Config Module.
192
     *
193
     * @param string $provider
194
     *
195
     * @return array
196
     */
197
    private function getProvidersConfig(string $provider): array
198
    {
199
        $config = [];
200
        $config[$provider] = [
201
            'enabled' => (bool) $this->scopeConfig->getValue(
202
                sprintf(self::CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_ENABLED, $provider),
203
                ScopeInterface::SCOPE_STORE
204
            ),
205
            'keys' => [
206
                'key' => $this->scopeConfig->getValue(
207
                    sprintf(self::CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_KEY, $provider),
208
                    ScopeInterface::SCOPE_STORE
209
                ),
210
                'secret' => $this->scopeConfig->getValue(
211
                    sprintf(self::CONFIG_PATH_SOCIAL_LOGIN_PROVIDER_SECRET, $provider),
212
                    ScopeInterface::SCOPE_STORE
213
                ),
214
            ],
215
        ];
216
217
        return $config;
218
    }
219
220
    /**
221
     * Generate Url Endpoint.
222
     *
223
     * @param string $provider
224
     *
225
     * @return string
226
     */
227
    private function getEndpoint(string $provider): string
228
    {
229
        $params = [
230
            '_secure'  => true,
231
            'provider' => $provider,
232
        ];
233
234
        return $this->url->getUrl('sociallogin/endpoint/index', $params);
235
    }
236
237
    /**
238
     * Gets customer data for a hybrid auth profile.
239
     *
240
     * @param SocialProfile $profile
241
     *
242
     * @return CustomerFactory
243
     */
244
    private function getCustomerData(SocialProfile $profile)
245
    {
246
        $customerData = [];
247
        foreach (['firstName', 'lastName', 'email'] as $field) {
248
            $data = $profile->{$field};
249
            $customerData[strtolower($field)] = $data !== null ? $data : '-';
250
        }
251
252
        $customer = $this->customerDataFactory->create();
253
        $customer->setEmail($customerData['email']);
254
        $customer->setFirstname($customerData['firstname']);
255
        $customer->setLastname($customerData['lastname']);
256
        $storeId = $this->storeManager->getStore()->getId();
257
        $customer->setStoreId($storeId);
258
        $websiteId = $this->storeManager->getStore($customer->getStoreId())->getWebsiteId();
259
        $customer->setWebsiteId($websiteId);
260
261
        return $customer;
262
    }
263
264
    /**
265
     * Set Customer.
266
     *
267
     * @param SocialProfile $socialProfile
268
     *
269
     * @return CustomerFactory
270
     */
271
    private function setCustomerData(SocialProfile $socialProfile)
272
    {
273
        $websiteId = $this->storeManager->getWebsite()->getId();
274
        $customer = $this->customerFactory->create();
275
        $customer->setWebsiteId($websiteId);
276
        if ($socialProfile->email) {
277
            $customer->loadByEmail($socialProfile->email);
278
            if (!$customer->getId()) {
279
                $customer = $this->getCustomerData($socialProfile);
280
                $customer = $this->createNewAccount($customer);
281
            }
282
        }
283
284
        return $customer;
285
    }
286
287
    /**
288
     * Create New Account.
289
     *
290
     * @param CustomerFactory $customer
291
     *
292
     * @return CustomerFactory
293
     */
294
    public function createNewAccount($customer)
295
    {
296
        try {
297
            $customer = $this->accountManagement
298
                ->createAccount($customer);
299
300
            $confirmationStatus = $this->accountManagement->getConfirmationStatus($customer->getId());
301
            if ($confirmationStatus === AccountManagementInterface::ACCOUNT_CONFIRMATION_REQUIRED) {
302
                $this->messageManager->addComplexSuccessMessage(
303
                    'checkoutConfirmAccountSuccessMessage',
304
                    [
305
                        'url' => $this->customerUrl->getEmailConfirmationUrl($customer->getEmail()),
306
                    ]
307
                );
308
            } else {
309
                $this->customerSession->setCustomerDataAsLoggedIn($customer);
310
            }
311
            if ($this->cookieManager->getCookie('mage-cache-sessid')) {
312
                $metadata = $this->cookieMetadataFactory->createCookieMetadata();
313
                $metadata->setPath('/');
314
                $this->cookieManager->deleteCookie('mage-cache-sessid', $metadata);
315
            }
316
        } catch (\Exception $exc) {
317
            $this->messageManager->addError(__('Unable to create account.'));
318
            $this->messageManager->addError(__($exc->getMessage()));
319
        }
320
321
        return $customer;
322
    }
323
324
    /**
325
     * Login account.
326
     *
327
     * @param string $provider
328
     *
329
     * @throws LocalizedException
330
     *
331
     * @return void
332
     */
333
    public function login(string $provider): void
334
    {
335
        $hybridAuth = $this->hybridauthFactory->create([
336
            'config' => [
337
                'callback'  => $this->getEndpoint($provider),
338
                'providers' => $this->getProvidersConfig($provider),
339
            ],
340
        ]);
341
        $authenticate = $hybridAuth->authenticate($provider);
342
        if ($authenticate->isConnected()) {
343
            $socialProfile = $authenticate->getUserProfile();
344
            $customer = $this->setCustomerData($socialProfile);
345
            $this->customerSession->setCustomerDataAsLoggedIn($customer);
346
347
            if ($this->cookieManager->getCookie('mage-cache-sessid')) {
348
                $metadata = $this->cookieMetadataFactory->createCookieMetadata();
349
                $metadata->setPath('/');
350
                $this->cookieManager->deleteCookie('mage-cache-sessid', $metadata);
351
            }
352
        }
353
    }
354
355
    /**
356
     * Set Autenticate And Referer.
357
     *
358
     * @param string      $provider
359
     * @param int|null    $isSecure
360
     * @param string|null $referer
361
     *
362
     * @return array
363
     */
364
    public function setAutenticateAndReferer(string $provider, int $isSecure = 1, string $referer = null): array
0 ignored issues
show
The parameter $isSecure is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

364
    public function setAutenticateAndReferer(string $provider, /** @scrutinizer ignore-unused */ int $isSecure = 1, string $referer = null): array

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
365
    {
366
        if ($referer) {
367
            $this->accountRedirect->setRedirectCookie($referer);
368
        }
369
370
        $redirect = $this->accountRedirect->getRedirectCookie();
371
372
        $response['redirectUrl'] = $redirect;
373
374
        $hybridAuth = $this->hybridauthFactory->create([
375
            'config' => [
376
                'callback'  => $this->getEndpoint($provider),
377
                'providers' => $this->getProvidersConfig($provider),
378
            ],
379
        ]);
380
381
        try {
382
            $authenticate = $hybridAuth->authenticate($provider);
383
        } catch (Exception $e) {
384
            $this->messageManager->addError(__('Unable to login, try another way.'));
385
386
            return $response;
387
        }
388
389
        if ($authenticate->isConnected()) {
390
            $socialProfile = $authenticate->getUserProfile();
391
            $customer = $this->setCustomerData($socialProfile);
392
            if ($customer->getId()) {
393
                $this->customerSession->getCustomerFormData(true);
394
                $customerId = $this->customerSession->getCustomerId();
0 ignored issues
show
The assignment to $customerId is dead and can be removed.
Loading history...
395
                $customerDataObject = $this->customerRepository->getById($customer->getId());
396
397
                $this->customerSession->setCustomerDataAsLoggedIn($customerDataObject);
398
399
                if ($this->cookieManager->getCookie('mage-cache-sessid')) {
400
                    $metadata = $this->cookieMetadataFactory->createCookieMetadata();
401
                    $metadata->setPath('/');
402
                    $this->cookieManager->deleteCookie('mage-cache-sessid', $metadata);
403
                }
404
405
                return $response;
406
            }
407
408
            $this->messageManager->addError(__('Unable to login, try another way.'));
409
410
            return $response;
411
        }
412
    }
413
}
414