Issues (38)

Services/AzineMergedBusinessNetworksProvider.php (6 issues)

1
<?php
2
3
namespace Azine\HybridAuthBundle\Services;
4
5
use Azine\HybridAuthBundle\Entity\UserContact;
6
use Symfony\Component\HttpFoundation\Session\Session;
7
8
class AzineMergedBusinessNetworksProvider
9
{
10
    /**
11
     * @var AzineHybridAuth
12
     */
13
    private $hybridAuth;
14
15
    /**
16
     * @var array
17
     */
18
    private $contacts;
19
20
    /**
21
     * @var Session
22
     */
23
    private $session;
24
25
    /**
26
     * @var array of provider ids
27
     */
28
    private $providers;
29
30
    /**
31
     * @var array of provider ids that are loaded already
32
     */
33
    private $loadedProviders;
34
35
    /**
36
     * @var ContactSorter
37
     */
38
    private $sorter;
39
40
    /**
41
     * @var ContactMerger
42
     */
43
    private $merger;
44
45
    /**
46
     * @var GenderGuesser
47
     */
48
    private $genderGuesser;
49
50
    /**
51
     * @var string
52
     */
53
    const CONTACTS_SESSION_NAME = 'hybrid_auth_contacts';
54
    const LOADED_PROVIDERS_NAME = 'hybrid_auth_loaded_providers';
55
56
    /**
57
     * Get the contacts from all configured providers.
58
     *
59
     * @param AzineHybridAuth $hybridAuth
60
     * @param Session         $session
61
     * @param array           $providers
62 1
     */
63 1
    public function __construct(AzineHybridAuth $hybridAuth, Session $session, ContactSorter $sorter, ContactMerger $merger, GenderGuesser $genderGuesser, ContactFilter $contactFilter, array $providers)
64 1
    {
65 1
        $this->hybridAuth = $hybridAuth;
66 1
        $this->sorter = $sorter;
67 1
        $this->merger = $merger;
68 1
        $this->contacts = $session->get(self::CONTACTS_SESSION_NAME, array());
69 1
        $this->loadedProviders = $session->get(self::LOADED_PROVIDERS_NAME, array());
70 1
        $this->providers = array_keys($providers);
71 1
        $this->session = $session;
72 1
        $this->genderGuesser = $genderGuesser;
73
        $this->contactFilter = $contactFilter;
0 ignored issues
show
Bug Best Practice introduced by
The property contactFilter does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
74
    }
75
76
    /**
77
     * Get user-profiles from linked-in.
78
     *
79
     * @param int   $pageSize
80
     * @param int   $offset
81 1
     * @param array $filterParams
82
     *
83
     * @return array
84 1
     */
85
    public function getContactProfiles($pageSize = 50, $offset = 0, $filterParams = array())
86
    {
87
        // check if the contacts are loaded already
88
        if (sizeof($this->providers) != sizeof($this->loadedProviders)) {
89 1
            $this->getAllContacts();
90
        }
91
92 1
        // filter according to the $filterParams
93 1
        $contacts = $this->contactFilter->filter($this->contacts, $filterParams);
94
95
        // return one page
96
        $contacts = array_slice($contacts, $offset, $pageSize, true);
97
98
        return $contacts;
99
    }
100
101
    /**
102
     * Fetch all contacts from the networks.
103
     */
104
    private function getAllContacts()
105
    {
106
        $newContactsCount = 0;
107
        foreach ($this->providers as $provider) {
108
            $connected = $this->hybridAuth->getProvider(null, $provider, false)->isConnected();
109
            if ($connected && (!array_key_exists($provider, $this->loadedProviders) || 0 == sizeof($this->loadedProviders[$provider]))) {
110
                $newContacts = $this->getUserContactsFor($provider);
111
                $this->loadedProviders[$provider] = $newContacts;
112
                $this->session->set(self::LOADED_PROVIDERS_NAME, $this->loadedProviders);
113
                $this->session->save();
114
                $newContactsCount += sizeof($newContacts);
115
            }
116
        }
117
118
        if ($newContactsCount > 0) {
119
            // merge the old and new contacts
120
            $this->contacts = $this->merger->merge($this->loadedProviders);
121
122
            // sort all contacts
123
            usort($this->contacts, array($this->sorter, 'compare'));
124
125
            $this->session->set(self::CONTACTS_SESSION_NAME, $this->contacts);
126
            $this->session->save();
127
        }
128
    }
129
130
    /**
131
     * Get ALL contacts of the current user.
132
     *
133
     * @param $provider
134
     *
135
     * @return array
136
     *
137
     * @throws \Exception
138
     */
139
    public function getUserContactsFor($provider)
140
    {
141
        if ('LinkedIn' == $provider) {
142
            return $this->getLinkedInContacts();
143
        }
144
145
        $userContacts = array();
146
        foreach ($this->hybridAuth->getProvider(null, $provider)->getUserContacts() as $next) {
147
            $nextContact = new UserContact($provider);
148
            $nextContact->identifier = $next->identifier;
149
            $nextContact->profileURL = $next->profileURL;
150
            $nextContact->firstName = $next->firstName;
0 ignored issues
show
The property firstName does not seem to exist on Hybridauth\User\Contact.
Loading history...
151
            $nextContact->lastName = $next->lastName;
0 ignored issues
show
The property lastName does not seem to exist on Hybridauth\User\Contact.
Loading history...
152
            $nextContact->displayName = $nextContact->firstName.' '.$nextContact->lastName;
153
            $nextContact->description = $next->description;
154
            $nextContact->email = $next->email;
155
        }
156
157
        return $userContacts;
158
    }
159
160
    /**
161
     * Get ALL linkedin contacts of the current user.
162
     *
163
     * @throws \Exception
164
     *
165
     * @return array of UserContact
166
     */
167
    public function getLinkedInContacts()
168
    {
169
        $api = $this->hybridAuth->getLinkedInApi();
170
        $fetchSize = 500;
171
        $fetchMore = true;
172
        $fetchOffset = 0;
173
        $users = array();
174
175
        try {
176
            while ($fetchMore) {
177
                $response = $api->profile("~/connections:(id,first-name,last-name,picture-url,public-profile-url,summary,headline,specialities)?start=$fetchOffset&count=$fetchSize");
178
                $connectionsXml = new \SimpleXMLElement($response['linkedin']);
179
                foreach ($connectionsXml->person as $person) {
180
                    $users[] = $person;
181
                }
182
                $fetchMore = $fetchSize == sizeof($connectionsXml->person);
183
                $fetchOffset = $fetchOffset + $fetchSize;
184
            }
185
        } catch (\LinkedInException $e) {
0 ignored issues
show
The type LinkedInException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
186
            throw new \Exception("User contacts request failed! {$this->providerId} returned an error.", $e->getCode(), $e);
0 ignored issues
show
The property providerId does not exist on Azine\HybridAuthBundle\S...usinessNetworksProvider. Did you mean providers?
Loading history...
187
        }
188
189
        $contacts = array();
190
        foreach ($users as $connection) {
191
            $contacts[] = $this->createUserContactFromLinkedInProfile($connection);
192
        }
193
194
        return $contacts;
195
    }
196
197
    /**
198
     * Get the basic profile of the current users contact with the given user id.
199
     *
200
     * @param string $provider
201
     * @param string $contactId
202
     *
203
     * @return UserContact
204
     */
205
    public function getUserContactBasicProfile($provider, $contactId)
206
    {
207
        if (!array_key_exists($provider, $this->loadedProviders)) {
208
            $this->loadedProviders[$provider] = $this->getUserContactsFor($provider);
209
            $this->session->set(self::LOADED_PROVIDERS_NAME, $this->loadedProviders);
210
            $this->session->save();
211
        }
212
213
        foreach ($this->loadedProviders[$provider] as $userContact) {
214
            if ($userContact->identifier == $contactId) {
215
                return $userContact;
216
            }
217
        }
218
219
        return null;
220
    }
221
222
    /**
223
     * Get the basic profile of the user with the given profileUrl.
224
     *
225
     * @param string $profileUrl
226
     *
227
     * @throws \Exception
228
     *
229
     * @return UserContact
230
     */
231
    public function getUserProfileByUrl($profileUrl)
232
    {
233
        $matches = array();
234
        preg_match('/https?:\/\/.{0,5}(linkedin)(\.ch|\.com).*/', $profileUrl, $matches);
235
        $provider = $matches[1];
236
        if (false !== strpos($provider, 'linkedin')) {
237
            $profileUrl = urlencode($profileUrl);
238
            try {
239
                $response = $this->hybridAuth->getLinkedInApi()->connections("url=$profileUrl:(id,first-name,last-name,picture-url,public-profile-url,summary,headline,specialities,email-address)");
240
            } catch (\LinkedInException $e) {
241
                throw new \Exception('User profile by url request failed! linkedin returned an error.', $e->getCode(), $e);
242
            }
243
            $connectionsXml = new \SimpleXMLElement($response['linkedin']);
244
245
            return $this->createUserContactFromLinkedInProfile($connectionsXml);
246
        }
247
    }
248
249
    /**
250
     * @param $linkedinProfile
251
     *
252
     * @return UserContact
253
     */
254
    private function createUserContactFromLinkedInProfile($linkedinProfile)
255
    {
256
        $newContact = new UserContact('LinkedIn');
257
        $newContact->identifier = (string) $linkedinProfile->id;
258
        $newContact->firstName = (string) $linkedinProfile->{'first-name'};
259
        $newContact->lastName = (string) $linkedinProfile->{'last-name'};
260
        $newContact->displayName = (string) $linkedinProfile->{'first-name'}.' '.$linkedinProfile->{'last-name'};
261
        $newContact->profileURL = (string) $linkedinProfile->{'public-profile-url'};
262
        if (null == $newContact->profileURL) {
263
            $newContact->profileURL = (string) $linkedinProfile->{'site-standard-profile-request'};
264
        }
265
        $newContact->photoURL = (string) $linkedinProfile->{'picture-url'};
266
        $newContact->description = (string) $linkedinProfile->{'summary'};
267
        $newContact->description .= '' == $newContact->description ? (string) $linkedinProfile->{'specialities'} : "\n".(string) $linkedinProfile->{'specialities'};
268
        if ($linkedinProfile->{'email-address'}) {
269
            $newContact->email = (string) $linkedinProfile->{'email-address'};
270
        }
271
        $newContact->gender = $this->genderGuesser->gender($newContact->firstName, 5);
0 ignored issues
show
$newContact->firstName of type string is incompatible with the type string expected by parameter $firstName of Azine\HybridAuthBundle\S...GenderGuesser::gender(). ( Ignorable by Annotation )

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

271
        $newContact->gender = $this->genderGuesser->gender(/** @scrutinizer ignore-type */ $newContact->firstName, 5);
Loading history...
272
        $headline = (string) $linkedinProfile->{'headline'};
273
        $newContact->headline = str_replace(' at ', ' @ ', $headline);
274
275
        return $newContact;
276
    }
277
}
278