FacebookConnection   A
last analyzed

Complexity

Total Complexity 13

Size/Duplication

Total Lines 150
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 65
c 2
b 0
f 0
dl 0
loc 150
rs 10
wmc 13

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 1
A grantNewAccessToken() 0 21 3
A revokeAccess() 0 23 4
A getSelf() 0 29 4
A getGrantUrl() 0 7 1
1
<?php
2
/**
3
 * @author Tharanga Kothalawala <[email protected]>
4
 * @date 30-12-2018
5
 */
6
7
namespace TSK\SSO\ThirdParty\Facebook;
8
9
use TSK\SSO\Storage\ThirdPartyStorageRepository;
10
use TSK\SSO\ThirdParty;
11
use TSK\SSO\ThirdParty\CommonAccessToken;
12
use TSK\SSO\ThirdParty\Exception\NoThirdPartyEmailFoundException;
13
use TSK\SSO\ThirdParty\Exception\ThirdPartyConnectionFailedException;
14
use TSK\SSO\ThirdParty\ThirdPartyUser;
15
use TSK\SSO\ThirdParty\VendorConnection;
16
use Facebook\Exceptions\FacebookResponseException;
17
use Facebook\Exceptions\FacebookSDKException;
18
use Facebook\Facebook;
19
20
/**
21
 * @codeCoverageIgnore
22
 * @package TSK\SSO\ThirdParty\Facebook
23
 * @see https://developers.facebook.com/docs/php/api/5.0.0
24
 */
25
class FacebookConnection implements VendorConnection
26
{
27
    /**
28
     * @var FacebookApiConfiguration
29
     */
30
    private $facebookApiConfiguration;
31
32
    /**
33
     * @var ThirdPartyStorageRepository
34
     */
35
    private $storageRepository;
36
37
    /**
38
     * @var Facebook
39
     */
40
    private $facebook;
41
42
    /**
43
     * @param FacebookApiConfiguration $facebookApiConfiguration
44
     * @param ThirdPartyStorageRepository $storageRepository
45
     */
46
    public function __construct(
47
        FacebookApiConfiguration $facebookApiConfiguration,
48
        ThirdPartyStorageRepository $storageRepository
49
    ) {
50
        $this->facebookApiConfiguration = $facebookApiConfiguration;
51
        $this->storageRepository = $storageRepository;
52
        $this->facebook = new Facebook(array(
53
            'app_id' => $this->facebookApiConfiguration->appId(),
54
            'app_secret' => $this->facebookApiConfiguration->appSecret(),
55
            'default_graph_version' => $this->facebookApiConfiguration->apiVersion(),
56
        ));
57
    }
58
59
    /**
60
     * Use this to get a link to redirect a user to the facebook login page.
61
     *
62
     * @return string
63
     */
64
    public function getGrantUrl()
65
    {
66
        $params = array('req_perms' => $this->facebookApiConfiguration->appPermissions());
67
68
        $helper = $this->facebook->getRedirectLoginHelper();
69
70
        return $helper->getLoginUrl($this->facebookApiConfiguration->redirectUrl(), $params);
71
    }
72
73
    /**
74
     * Grants a new access token
75
     *
76
     * @return CommonAccessToken
77
     * @throws ThirdPartyConnectionFailedException
78
     */
79
    public function grantNewAccessToken()
80
    {
81
        $helper = $this->facebook->getRedirectLoginHelper();
82
83
        try {
84
            $accessToken = $helper->getAccessToken($this->facebookApiConfiguration->redirectUrl());
85
            $oAuth2Client = $this->facebook->getOAuth2Client();
86
            $accessToken = $oAuth2Client->getLongLivedAccessToken($accessToken);
87
88
            return new CommonAccessToken($accessToken->getValue(), ThirdParty::FACEBOOK);
89
        } catch (FacebookResponseException $ex) {
90
            throw new ThirdPartyConnectionFailedException(
91
                'Graph returned an error: ' . $ex->getMessage(),
92
                $ex->getCode(),
93
                $ex
94
            );
95
        } catch (FacebookSDKException $ex) {
96
            throw new ThirdPartyConnectionFailedException(
97
                'Facebook SDK returned an error: ' . $ex->getMessage(),
98
                $ex->getCode(),
99
                $ex
100
            );
101
        }
102
    }
103
104
    /**
105
     * Use this to retrieve the current user's third party user data using there existing granted access token
106
     *
107
     * @param CommonAccessToken $accessToken
108
     * @return ThirdPartyUser
109
     * @throws NoThirdPartyEmailFoundException
110
     * @throws ThirdPartyConnectionFailedException
111
     */
112
    public function getSelf(CommonAccessToken $accessToken)
113
    {
114
        try {
115
            $response = $this->facebook->get('/me?fields=id,first_name,last_name,email,gender', $accessToken->token());
116
            $graphUser = $response->getGraphUser();
117
118
            $thirdPartyEmail = $graphUser->getEmail();
119
            if (empty($thirdPartyEmail)) {
120
                throw new NoThirdPartyEmailFoundException('An email address cannot be found from vendor');
121
            }
122
123
            return new ThirdPartyUser(
124
                $graphUser->getId(),
125
                sprintf('%s %s', $graphUser->getFirstName(), $graphUser->getLastName()),
126
                $thirdPartyEmail,
127
                "http://graph.facebook.com/{$graphUser->getId()}/picture",
128
                $graphUser->getGender()
129
            );
130
        } catch (FacebookResponseException $ex) {
131
            throw new ThirdPartyConnectionFailedException(
132
                'Graph returned an error: ' . $ex->getMessage(),
133
                $ex->getCode(),
134
                $ex
135
            );
136
        } catch (FacebookSDKException $ex) {
137
            throw new ThirdPartyConnectionFailedException(
138
                'Facebook SDK returned an error: ' . $ex->getMessage(),
139
                $ex->getCode(),
140
                $ex
141
            );
142
        }
143
    }
144
145
    /**
146
     * Use this to revoke the access to the third party data.
147
     * This will completely remove the access from the vendor side.
148
     *
149
     * @param CommonAccessToken $accessToken
150
     * @return bool
151
     */
152
    public function revokeAccess(CommonAccessToken $accessToken)
153
    {
154
        $mappedUser = $this->storageRepository->getUser($accessToken->email(), ThirdParty::FACEBOOK);
155
        if (is_null($mappedUser)) {
156
            return false;
157
        }
158
159
        $vendorData = $mappedUser->decodedVendorData();
160
        if (empty($vendorData[ThirdPartyUser::ID])) {
161
            return false;
162
        }
163
164
        try {
165
            $this->facebook->delete(
166
                sprintf('/%s/permissions', $vendorData[ThirdPartyUser::ID]),
167
                array(),
168
                $accessToken->token()
169
            );
170
        } catch (FacebookResponseException $ex) {
171
            return false;
172
        }
173
174
        return true;
175
    }
176
}
177