1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Borfast\Socializr\Connectors; |
4
|
|
|
|
5
|
|
|
use OAuth\Common\Storage\Exception\TokenNotFoundException; |
6
|
|
|
use Borfast\Socializr\Exceptions\AuthorizationException; |
7
|
|
|
use Borfast\Socializr\Exceptions\LinkedinForbiddenException; |
8
|
|
|
use Borfast\Socializr\Exceptions\LinkedinPostingException; |
9
|
|
|
use Borfast\Socializr\Post; |
10
|
|
|
use Borfast\Socializr\Profile; |
11
|
|
|
use Borfast\Socializr\Response; |
12
|
|
|
use GuzzleHttp\Client as Guzzle; |
13
|
|
|
use GuzzleHttp\Exception\ClientException; |
14
|
|
|
|
15
|
|
|
class LinkedinGroup extends AbstractConnector |
16
|
|
|
{ |
17
|
|
|
public static $provider = 'linkedin'; |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* @param Post $post |
21
|
|
|
* @return Response |
22
|
|
|
* @throws LinkedinForbiddenException |
23
|
|
|
* @throws LinkedinPostingException |
24
|
|
|
*/ |
25
|
|
|
public function post(Post $post) |
26
|
|
|
{ |
27
|
|
|
$group_id = $post->options['group_id']; |
28
|
|
|
|
29
|
|
|
try { |
30
|
|
|
$token = $this->service->getStorage()->retrieveAccessToken('Linkedin')->getAccessToken(); |
31
|
|
|
} catch (TokenNotFoundException $e) { |
32
|
|
|
throw new AuthorizationException(); |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
$path = '/groups/'.$group_id.'/posts?format=json&oauth2_access_token='.$token; |
36
|
|
|
$params = [ |
37
|
|
|
'title' => $post->title, |
38
|
|
|
'summary' => '', |
39
|
|
|
'content' => [ |
40
|
|
|
'title' => $post->title . ' @', |
41
|
|
|
'submitted-url' => $post->url, |
42
|
|
|
'description' => $post->body, |
43
|
|
|
], |
44
|
|
|
]; |
45
|
|
|
|
46
|
|
|
// Add media files, if they were sent. |
47
|
|
|
if (isset($post->media) && array_key_exists(0, $post->media)) { |
48
|
|
|
$params['content']['submitted-image-url'] = $post->media[0]; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
$params = json_encode($params); |
52
|
|
|
|
53
|
|
|
$url = 'https://api.linkedin.com/v1'.$path; |
54
|
|
|
// Linkedin API requires the Content-Type header set to application/json |
55
|
|
|
$options = [ |
56
|
|
|
'headers' => ['Content-Type' => 'application/json'], |
57
|
|
|
'body' => $params |
58
|
|
|
]; |
59
|
|
|
|
60
|
|
|
$client = new Guzzle(); |
61
|
|
|
try { |
62
|
|
|
$result = $client->post($url, $options); |
63
|
|
|
} catch (ClientException $e) { |
64
|
|
|
if ($e->getCode() >= 400) { |
65
|
|
|
throw new LinkedinForbiddenException($e); |
66
|
|
|
} else { |
67
|
|
|
throw $e; |
68
|
|
|
} |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
if ($result->getStatusCode() > 300) { |
72
|
|
|
$msg = "Error posting to Linkedin group. Error code from Linkedin: %s. Error message from Linkedin: %s"; |
73
|
|
|
$msg = sprintf($msg, $result->status_code, json_decode($result->body)->message); |
74
|
|
|
throw new LinkedinPostingException($msg, $result->status_code); |
75
|
|
|
} |
76
|
|
|
|
77
|
|
|
$response = new Response; |
78
|
|
|
$response->setRawResponse($result); // This is already JSON. |
79
|
|
|
$response->setProvider(static::$provider); |
80
|
|
|
//$response->setPostId($result->getHeader('x-li-uuid')); |
|
|
|
|
81
|
|
|
|
82
|
|
|
// As amazing as it may sound, there's a three year old bug that LinkedIn |
83
|
|
|
// knows of but doesn't fix, which is simply the group posts URL is not |
84
|
|
|
// returned when we create the post, and when the post endpoint is queried |
85
|
|
|
// it returns a URL containing an incorrect domain: api.linkedin.com |
86
|
|
|
// instead of www.linkedin.com. They acknowledge this in the "Known Issues" |
87
|
|
|
// section of the groups API documentation and say the workaround is simple: |
88
|
|
|
// just swap the domains. Well, thanks for nothing. Would it be so hard for |
89
|
|
|
// them to return a public URL along with the response of the creation?... |
90
|
|
|
// So we need to make another API call to fetch the correct URL, because |
91
|
|
|
// it's not even possible to generate it manually. |
92
|
|
|
|
93
|
|
|
// Moderated groups don't return a 'location' header, so let's skip it if that's the case. |
94
|
|
|
$location = $result->getHeader('Location'); |
95
|
|
|
if (!empty($location)) { |
96
|
|
|
$url = $location . ':(id,site-group-post-url)?format=json&oauth2_access_token=' . $token; |
97
|
|
|
$result = $client->get($url); |
98
|
|
|
$json = $result->json(); |
99
|
|
|
|
100
|
|
|
$post_url = str_replace('api.linkedin.com/v1', 'www.linkedin.com', $json['siteGroupPostUrl']); |
101
|
|
|
$response->setPostUrl($post_url); |
102
|
|
|
} |
103
|
|
|
|
104
|
|
|
return $response; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
|
108
|
|
View Code Duplication |
public function getProfile() |
109
|
|
|
{ |
110
|
|
|
$path = '/people/~:(id,first-name,last-name,maiden-name,public-profile-url,formatted-name,num-connections,email-address,num-recommenders)?format=json'; |
111
|
|
|
$response = $this->service->request($path); |
112
|
|
|
$profile_json = json_decode($response, true); |
113
|
|
|
|
114
|
|
|
$mapping = [ |
115
|
|
|
'id' => 'id', |
116
|
|
|
'email' => 'emailAddress', |
117
|
|
|
'name' => 'formattedName', |
118
|
|
|
'first_name' => 'firstName', |
119
|
|
|
'middle_name' => 'maidenName', |
120
|
|
|
'last_name' => 'lastName', |
121
|
|
|
// 'username' => 'username', |
|
|
|
|
122
|
|
|
'link' => 'publicProfileUrl' |
123
|
|
|
]; |
124
|
|
|
|
125
|
|
|
$profile = Profile::create($mapping, $profile_json); |
126
|
|
|
$profile->provider = static::$provider; |
127
|
|
|
$profile->raw_response = $response; |
128
|
|
|
|
129
|
|
|
return $profile; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
public function getStats() |
133
|
|
|
{ |
134
|
|
|
$path = 'groups/'.$this->id.':(id,num-members)?format=json'; |
135
|
|
|
$response = json_decode($this->request($path)); |
136
|
|
|
|
137
|
|
|
return $response->numMembers; |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
|
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.
The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.
This check looks for comments that seem to be mostly valid code and reports them.