├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── README.md
├── composer.json
├── phpunit.xml
├── src
├── Blog.php
├── Connectors
│ ├── AbstractConnector.php
│ ├── ConnectorFactory.php
│ ├── ConnectorInterface.php
│ ├── Facebook.php
│ ├── FacebookGroup.php
│ ├── FacebookPage.php
│ ├── Linkedin.php
│ ├── LinkedinGroup.php
│ ├── LinkedinPage.php
│ ├── Tumblr.php
│ ├── TumblrBlog.php
│ └── Twitter.php
├── Exceptions
│ ├── AuthorizationException.php
│ ├── CSRFException.php
│ ├── DuplicatePostException.php
│ ├── ExpiredTokenException.php
│ ├── GenericPostingException.php
│ ├── InvalidConfigurationException.php
│ ├── InvalidProviderException.php
│ ├── LinkedinForbiddenException.php
│ ├── LinkedinPostingException.php
│ └── TumblrPostingException.php
├── Group.php
├── Page.php
├── Post.php
├── Profile.php
├── Response.php
└── Stats.php
└── tests
└── Socializr
└── Connectors
└── ConnectorFactoryTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | /vendor
2 | composer.phar
3 | composer.lock
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.6
5 | - 7.1
6 |
7 | install:
8 | - composer self-update
9 | - composer install --prefer-source --no-interaction --dev
10 |
11 | script: vendor/bin/phpunit
12 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) [year] [fullname]
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/borfast/socializr)
2 | [](https://scrutinizer-ci.com/g/borfast/socializr/?branch=master)
3 |
4 | HERE BE DRAGONS!
5 |
6 | This is being updated in a hurry and the code is ugly, so don't expect to be
7 | able to use this easily for your own project, because for now it's not meant to
8 | be used in anything other than the project I'm working on.
9 |
10 | This is a very simple PHP library for posting to several social networks, started out
11 | of frustration for not finding anything like it besides Hybridauth, which
12 | doesn't really suite my needs or quality requirements.
13 |
14 | For now it only supports Facebook, Twitter and LinkedIn. More networks will come soon.
15 |
16 | Built in a hurry (very few tests, few comments) because its meant for a product
17 | that has been delayed due to non-stop issues with Hybridauth. I will eventually
18 | improve this.
19 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "borfast/socializr",
3 | "description": "Simple PHP library for posting to several social networks.",
4 | "type": "library",
5 | "license": "MIT",
6 | "authors": [
7 | {
8 | "name": "Raúl Santos",
9 | "homepage": "https://github.com/borfast/socializr"
10 | }
11 | ],
12 | "require": {
13 | "php": ">=5.4",
14 | "lusitanian/oauth": "dev-patch-1",
15 | "guzzlehttp/guzzle": "~4"
16 | },
17 | "repositories": [
18 | {
19 | "type": "vcs",
20 | "url": "git@github.com:milicevic79/PHPoAuthLib.git"
21 | }
22 | ],
23 | "require-dev": {
24 | "phpunit/phpunit": "~4",
25 | "mockery/mockery": "dev-master"
26 | },
27 | "autoload": {
28 | "psr-4": {
29 | "Borfast\\Socializr\\": "src"
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 | ./tests/
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Blog.php:
--------------------------------------------------------------------------------
1 | 'key_in_attributes_array']
25 | *
26 | * @param array $mapping
27 | * @param array $attributes
28 | * @return static
29 | */
30 | public static function create(array $mapping, array $attributes)
31 | {
32 | $blog = new Blog;
33 |
34 | array_walk($mapping, function (&$name, $key) use (&$blog, &$attributes) {
35 | $blog->$key = (isset($attributes[$name])) ? $attributes[$name] : null;
36 | });
37 |
38 | return $blog;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Connectors/AbstractConnector.php:
--------------------------------------------------------------------------------
1 | config = $config;
30 | $this->service = $service;
31 | $this->options = $options;
32 | $this->id = $id;
33 | static::$provider = $service->service();
34 | }
35 |
36 |
37 | public function request($path, $method = 'GET', $params = [], $headers = [])
38 | {
39 | if (empty($params)) {
40 | $params = null;
41 | }
42 |
43 | try {
44 | $result = $this->service->request($path, $method, $params, $headers);
45 | } catch (OauthExpiredTokenException $e) {
46 | throw new ExpiredTokenException();
47 | } catch (TokenNotFoundException $e) {
48 | throw new AuthorizationException();
49 | }
50 |
51 | return $result;
52 | }
53 |
54 |
55 | /**
56 | * The method that initiates the provider authentication process.
57 | * It returns the provider's authentication/login page, which in turn
58 | * will redirect back to us. We don't do the redirect ourselves because that
59 | * means changing the application workflow and we don't want to get in the
60 | * way of how people do things.
61 | *
62 | * @todo Use pluggable\swappable CSRF token storage.
63 | */
64 | public function getAuthorizationUri(array $params = [])
65 | {
66 | // Check if this provider uses an CSRF token at all.
67 | if (!empty($this->config['csrf_token_name'])) {
68 | // Generate a random anti-CSRF token.
69 | $csrf_token = base64_encode(openssl_random_pseudo_bytes(32));
70 |
71 | // Write our token in session so we can check it after auth.
72 | // // TODO: This could be improved and make the session storage
73 | // pluggable. Is it worth the trouble, though?
74 | session_start();
75 | $_SESSION['socializr_csrf_token'] = $csrf_token;
76 | session_write_close();
77 |
78 | // Add the CSRF token to the request.
79 | $csrf_token_name = $this->config['csrf_token_name'];
80 | $params = array_merge($params, [$csrf_token_name => $csrf_token]);
81 | }
82 |
83 | $url = $this->service->getAuthorizationUri($params);
84 | return $url;
85 | }
86 |
87 |
88 | /**
89 | * For when the OAuth token expires and we need to refresh it.
90 | */
91 | public function refreshAccessToken()
92 | {
93 | try {
94 | $token = $this->service->getStorage()->retrieveAccessToken(static::$provider);
95 | } catch (TokenNotFoundException $e) {
96 | throw new AuthorizationException();
97 | }
98 | $this->service->refreshAccessToken($token);
99 | }
100 |
101 |
102 | /**
103 | * Check that the CSRF token
104 | */
105 | public function checkCsrf(array $get)
106 | {
107 | // Check if this provider uses an CSRF token at all.
108 | if (!empty($this->config['csrf_token_name'])) {
109 |
110 | session_start();
111 |
112 | // If we don't have a token and should have one, crash and burn.
113 | if (!isset($_SESSION['socializr_csrf_token'])) {
114 | throw new CSRFException('No CSRF token stored. Possible CSRF attack.', 1);
115 | }
116 |
117 | $stored_token = $_SESSION['socializr_csrf_token'];
118 | session_write_close();
119 |
120 | // Now get the token from the URL
121 | $csrf_token_name = $this->config['csrf_token_name'];
122 | $received_token = $get[$csrf_token_name];
123 |
124 | // Finally check that the stored token and the received token match.
125 | if (strcmp($stored_token, $received_token) != 0) {
126 | throw new CSRFException('Verification code mismatch. Possible CSRF attack.', 1);
127 | }
128 | }
129 | }
130 |
131 |
132 | public function getSessionData()
133 | {
134 | try {
135 | return $this->service->getStorage()->retrieveAccessToken(static::$provider)->getAccessToken();
136 | } catch (TokenNotFoundException $e) {
137 | throw new AuthorizationException();
138 | }
139 | }
140 |
141 |
142 | public function get($path, $params = [])
143 | {
144 | $response = json_decode(
145 | $this->service->request($path, 'GET', $params),
146 | true
147 | );
148 |
149 | return $response;
150 | }
151 |
152 |
153 | /**
154 | * The method that sets the OAuth token for the current provider. It must be
155 | * called after the authorize() method. Retrieves the auth token from the
156 | * provider's response and store it.
157 | *
158 | * @params array $params The URL params. Each Connector knows how to get the
159 | * token for its specific provider.
160 | */
161 | public function storeOauthToken($params)
162 | {
163 | $this->service->requestAccessToken($params['code']);
164 | }
165 |
166 |
167 | public function getUid()
168 | {
169 | if (is_null($this->id)) {
170 | $profile = $this->getProfile();
171 | $this->id = $profile->id;
172 | }
173 |
174 | return $this->id;
175 | }
176 |
177 |
178 | // These should be implementation-specific.
179 | public function getProfile()
180 | {
181 | throw new \Exception('Trying to get a Profile from a generic provider. This probably means you are trying to get a type of data that does not make sense for the connector you are using. For example, trying to get a Facebook Profile from a FacebookPage connector.');
182 | }
183 |
184 | public function getPage()
185 | {
186 | throw new \Exception('Trying to get a Page from a generic provider. This probably means you are trying to get a type of data that does not make sense for the connector you are using. For example, trying to get a Facebook Page from a FacebookGroup connector.');
187 | }
188 |
189 | public function getPages()
190 | {
191 | throw new \Exception('Trying to get Pages from a generic provider. This probably means you are trying to get a type of data that does not make sense for the connector you are using.');
192 | }
193 |
194 | public function getGroup()
195 | {
196 | throw new \Exception('Trying to get a Group from a generic provider. This probably means you are trying to get a type of data that does not make sense for the connector you are using. For example, trying to get a Facebook Group from a FacebookPage connector.');
197 | }
198 |
199 | public function getGroups()
200 | {
201 | throw new \Exception('Trying to get Groups from a generic provider. This probably means you are trying to get a type of data that does not make sense for the connector you are using.');
202 | }
203 |
204 | abstract public function post(Post $post);
205 | abstract public function getStats();
206 | }
207 |
--------------------------------------------------------------------------------
/src/Connectors/ConnectorFactory.php:
--------------------------------------------------------------------------------
1 | config = $config;
41 |
42 | if (!array_key_exists('providers', $config)) {
43 | throw new InvalidConfigurationException;
44 | }
45 | }
46 |
47 |
48 | /**
49 | * Creates a Connector object for the given provider type. The $id parameter
50 | * may be null but should only be used like that when getting
51 | *
52 | * @param string $provider The provider type you want.
53 | * @param TokenStorageInterface $storage The storage for PHPoAuthLib.
54 | * @param array $options
55 | * @param string $id The ID we're connecting to.
56 | * @param null|ClientInterface $http_client The HTTP client for PHPoAuthLib.
57 | * @param null|ServiceFactory $service_factory The PHPoAuthLib service factory.
58 | * @param null|CredentialsInterface $credentials The credentials for PHPoAuthLib.
59 | * @return ConnectorInterface An instance of the requested connector type.
60 | * @throws InvalidProviderException
61 | */
62 | public function createConnector(
63 | $provider,
64 | TokenStorageInterface $storage,
65 | array $options = [],
66 | $id = null,
67 | ClientInterface $http_client = null,
68 | ServiceFactory $service_factory = null,
69 | CredentialsInterface $credentials = null
70 | ) {
71 | // Only allow configured providers.
72 | if (!array_key_exists($provider, $this->config['providers'])) {
73 | throw new InvalidProviderException($provider);
74 | }
75 |
76 | // Default to CurlClient (why isn't this the default? :( )
77 | if (is_null($http_client)) {
78 | $http_client = new CurlClient;
79 | }
80 |
81 | // Just if we want to be lazy and not pass this as an argument.
82 | if (is_null($service_factory)) {
83 | $service_factory = new ServiceFactory;
84 | }
85 |
86 | // Simplify config access for this provider.
87 | $config = $this->getFlatConfig($provider);
88 |
89 |
90 | // We're already getting the credentials via $this->config, we might not
91 | // want to always pass them as an argument.
92 | if (is_null($credentials)) {
93 | $credentials = new Credentials(
94 | $config['consumer_key'],
95 | $config['consumer_secret'],
96 | $config['callback']
97 | );
98 | }
99 |
100 | // Let's make use of CurlClient.
101 | $service_factory->setHttpClient($http_client);
102 |
103 | // Temporary (or so I hope) hack to overcome PHPoAuthLib not being ready
104 | // for Facebook's Graph API 1.0 deprecation.
105 |
106 | // If this is Facebook, let's specify we want API v2.2
107 | // $api_version = null;
108 | // if (strtolower($provider) == 'facebook') {
109 | // $api_version = '2.2';
110 | // }
111 | $uri = null;
112 | if (in_array($provider, ['Facebook', 'FacebookGroup', 'FacebookPage'])) {
113 | $uri = new Uri('https://graph.facebook.com/v2.8/');
114 | }
115 |
116 | // Finally, create the service already!
117 | $service = $service_factory->createService(
118 | $config['service'],
119 | $credentials,
120 | $storage,
121 | $config['scopes'],
122 | $uri
123 | //$api_version
124 | );
125 |
126 |
127 | $connector_class = '\\Borfast\\Socializr\\Connectors\\'.$provider;
128 | $connector = new $connector_class($config, $service, $options, $id);
129 |
130 | return $connector;
131 | }
132 |
133 |
134 | /**
135 | * Gets a config array for the given provider, taking care of a few checks
136 | * to make sure it has the needed data.
137 | * @param string $provider The provider type we want the config for.
138 | * @return array The config for the requested provider type.
139 | */
140 | protected function getFlatConfig($provider)
141 | {
142 | $config = $this->config['providers'][$provider];
143 |
144 | /*
145 | * Make sure we will create the correct PHPoAuthLib service. Each
146 | * configured provider can specify which service to use. If none is
147 | * specified, then the provider name is used.
148 | */
149 | if (empty($config['service'])) {
150 | $config['service'] = $provider;
151 | }
152 |
153 | // Cater for the possibility of having one single general callback URL.
154 | if (empty($config['callback'])) {
155 | $config['callback'] = $this->config['callback'];
156 | }
157 |
158 | // Cater for the possibility of no scope being defined
159 | if (empty($config['scopes'])) {
160 | $config['scopes'] = [];
161 | }
162 |
163 | // Make it possible to define the scopes as a comma separated string
164 | // instead of an array.
165 | if (!is_array($config['scopes'])) {
166 | $config['scopes'] = explode(', ', $config['scopes']);
167 | }
168 |
169 | return $config;
170 | }
171 | }
172 |
--------------------------------------------------------------------------------
/src/Connectors/ConnectorInterface.php:
--------------------------------------------------------------------------------
1 | title;
71 | $msg .= "\n\n";
72 | $msg .= $post->body;
73 | $msg = trim($msg);
74 |
75 | if (empty($post->media)) {
76 | $path = '/'.$this->getProfile()->id.'/feed';
77 |
78 | $params = [
79 | // 'caption' => $post->title,
80 | 'description' => '',
81 | 'link' => $post->url,
82 | 'message' => $msg
83 | ];
84 | } else {
85 | $path = '/'.$this->getProfile()->id.'/photos';
86 |
87 | $msg .= "\n";
88 | $msg .= $post->url;
89 |
90 | $params = [
91 | 'url' => $post->media[0],
92 | 'caption' => $msg
93 | ];
94 | }
95 |
96 | $method = 'POST';
97 |
98 | $result = $this->request($path, $method, $params);
99 |
100 | $json_result = json_decode($result, true);
101 |
102 | // If there's no ID, the post didn't go through
103 | if (!isset($json_result['id'])) {
104 | $msg = "Unknown error posting to Facebook profile.";
105 | throw new GenericPostingException($msg, 1);
106 | }
107 |
108 | $response = new Response;
109 | $response->setRawResponse($result); // This is already JSON.
110 | $response->setProvider('Facebook');
111 | $response->setPostId($json_result['id']);
112 |
113 | return $response;
114 | }
115 |
116 | public function getProfile()
117 | {
118 | if (is_null($this->profile)) {
119 | $path = '/me';
120 | $result = $this->request($path);
121 | $json_result = json_decode($result, true);
122 |
123 | $mapping = [
124 | 'id' => 'id',
125 | 'email' => 'email',
126 | 'name' => 'name',
127 | 'first_name' => 'first_name',
128 | 'middle_name' => 'middle_name',
129 | 'last_name' => 'last_name',
130 | 'username' => 'username',
131 | // 'username' => 'email', // Facebook Graph API 2.0 doesn't have username
132 | 'link' => 'link'
133 | ];
134 |
135 | $this->profile = Profile::create($mapping, $json_result);
136 | $this->profile->provider = static::$provider;
137 | $this->profile->raw_response = $result;
138 | }
139 |
140 | return $this->profile;
141 | }
142 |
143 | public function getPermissions()
144 | {
145 | $profile = $this->getProfile();
146 |
147 | $path = '/'.$profile->id.'/permissions';
148 | return $this->request($path);
149 | }
150 |
151 | public function getStats()
152 | {
153 | return $this->getFriendsCount();
154 | }
155 |
156 | public function getPages()
157 | {
158 | $profile = $this->getProfile();
159 |
160 | $path = '/'.$profile->id.'/accounts?fields=name,picture,access_token,id,can_post,likes,link,username';
161 | $result = $this->request($path);
162 | $json_result = json_decode($result, true);
163 |
164 | $pages = [];
165 |
166 | $mapping = [
167 | 'id' => 'id',
168 | 'name' => 'name',
169 | 'link' => 'link',
170 | 'can_post' => 'can_post',
171 | 'access_token' => 'access_token'
172 | ];
173 |
174 | // Make the page IDs available as the array keys
175 | if (!empty($json_result['data'])) {
176 | foreach ($json_result['data'] as $page) {
177 | $pages[$page['id']] = Page::create($mapping, $page);
178 | $pages[$page['id']]->picture = $page['picture']['data']['url'];
179 | $pages[$page['id']]->provider = static::$provider;
180 | $pages[$page['id']]->raw_response = $result;
181 | }
182 | }
183 |
184 | return $pages;
185 | }
186 |
187 | public function getGroups()
188 | {
189 | $profile = $this->getProfile();
190 |
191 | $path = '/'.$profile->id.'/groups?fields=id,name,icon';
192 | $result = $this->request($path);
193 | $json_result = json_decode($result, true);
194 |
195 | $groups = [];
196 |
197 | $mapping = [
198 | 'id' => 'id',
199 | 'name' => 'name',
200 | 'picture' => 'icon'
201 | ];
202 |
203 | // Make the group IDs available as the array keys
204 | if (!empty($json_result['data'])) {
205 | foreach ($json_result['data'] as $group) {
206 | $groups[$group['id']] = Group::create($mapping, $group);
207 | $groups[$group['id']]->picture = $group['icon'];
208 | $groups[$group['id']]->link = 'https://www.facebook.com/groups/' . $group['id'];
209 | $groups[$group['id']]->can_post = true;
210 | $groups[$group['id']]->provider = static::$provider;
211 | $groups[$group['id']]->raw_response = $result;
212 | }
213 | }
214 |
215 | return $groups;
216 | }
217 |
218 | /****************************************************
219 | *
220 | * From here on these are Facebook-specific methods.
221 | *
222 | ***************************************************/
223 | public function getFriendsCount()
224 | {
225 | $path = '/'.$this->getProfile()->id.'/friends';
226 | $result = $this->request($path);
227 |
228 | $response = json_decode($result);
229 |
230 | if (property_exists($response, 'summary')) {
231 | $response = $response->summary->total_count;
232 | } else {
233 | $response = '-';
234 | }
235 |
236 | return $response;
237 | }
238 | }
239 |
--------------------------------------------------------------------------------
/src/Connectors/FacebookGroup.php:
--------------------------------------------------------------------------------
1 | getGroup();
20 |
21 | if (empty($post->media)) {
22 | $path = '/'.$group->id.'/feed';
23 |
24 | $msg = $post->title;
25 | $msg .= "\n\n";
26 | $msg .= $post->body;
27 | $msg = trim($msg);
28 |
29 | $params = [
30 | // 'caption' => $post->title,
31 | 'description' => '',
32 | 'link' => $post->url,
33 | 'message' => $msg
34 | ];
35 | } else {
36 | $path = '/'.$group->id.'/photos';
37 |
38 | $msg = $post->title;
39 | $msg .= "\n\n";
40 | $msg .= $post->body;
41 | $msg .= "\n";
42 | $msg .= $post->url;
43 |
44 | $params = [
45 | 'url' => $post->media[0],
46 | 'caption' => $msg
47 | ];
48 | }
49 |
50 | $method = 'POST';
51 |
52 | $result = $this->request($path, $method, $params);
53 | $json_result = json_decode($result, true);
54 |
55 | // If there's no ID, the post didn't go through
56 | if (!isset($json_result['id'])) {
57 | $msg = "Unknown error posting to Facebook group.";
58 | throw new GenericPostingException($msg, 1);
59 | }
60 |
61 | $response = new Response;
62 | $response->setRawResponse($result); // This is already JSON.
63 | $response->setProvider('Facebook');
64 | $response->setPostId($json_result['id']);
65 |
66 | return $response;
67 | }
68 |
69 | public function getGroup()
70 | {
71 | if (is_null($this->group)) {
72 | $path = '/' . $this->id . '?fields=id,name,icon';
73 | $result = $this->request($path);
74 | $json_result = json_decode($result, true);
75 |
76 | $mapping = [
77 | 'id' => 'id',
78 | 'name' => 'name',
79 | 'picture' => 'icon'
80 | ];
81 |
82 | $this->group = Group::create($mapping, $json_result);
83 | $this->group->picture = $json_result['icon'];
84 | $this->group->link = 'https://www.facebook.com/groups/' . $json_result['id'];
85 | $this->group->can_post = true;
86 | $this->group->provider = static::$provider;
87 | $this->group->raw_response = $result;
88 | }
89 |
90 | return $this->group;
91 | }
92 |
93 | /**
94 | * Get the number of memebers this group has.
95 | */
96 | public function getStats()
97 | {
98 | return $this->getMembersCount();
99 | }
100 |
101 |
102 | /***************************************************************************
103 | *
104 | * From here on these are FacebookGroup-specific methods that should not be
105 | * accessed from other classes.
106 | *
107 | **************************************************************************/
108 |
109 | protected function getMembersCount()
110 | {
111 | $group = $this->getGroup();
112 |
113 | $path = '/'.$group->id.'/members';
114 | $result = $this->request($path);
115 |
116 | $response = json_decode($result);
117 | $response = count($response->data);
118 |
119 | return $response;
120 | }
121 |
122 | }
123 |
--------------------------------------------------------------------------------
/src/Connectors/FacebookPage.php:
--------------------------------------------------------------------------------
1 | getPage();
18 |
19 | if (empty($post->media)) {
20 | $path = '/'.$page->id.'/feed';
21 | $access_token = $post->options['page_access_token'];
22 |
23 | $msg = $post->title;
24 | $msg .= "\n\n";
25 | $msg .= $post->body;
26 | $msg = trim($msg);
27 |
28 | $params = [
29 | // 'caption' => $post->title,
30 | 'description' => '',
31 | 'link' => $post->url,
32 | 'message' => $msg,
33 | 'access_token' => $access_token
34 | ];
35 | } else {
36 | $path = '/'.$page->id.'/photos';
37 |
38 | $msg = $post->title;
39 | $msg .= "\n\n";
40 | $msg .= $post->body;
41 | $msg .= "\n";
42 | $msg .= $post->url;
43 |
44 | $params = [
45 | 'url' => $post->media[0],
46 | 'caption' => $msg
47 | ];
48 | }
49 |
50 | $method = 'POST';
51 |
52 | $result = $this->request($path, $method, $params);
53 | $json_result = json_decode($result, true);
54 |
55 | // If there's no ID, the post didn't go through
56 | if (!isset($json_result['id'])) {
57 | $msg = "Unknown error posting to Facebook page.";
58 | throw new GenericPostingException($msg, 1);
59 | }
60 |
61 | $response = new Response;
62 | $response->setRawResponse($result);
63 | $response->setProvider('Facebook');
64 | $response->setPostId($json_result['id']);
65 |
66 | return $response;
67 | }
68 |
69 | public function getPage()
70 | {
71 | if (is_null($this->page)) {
72 | $path = '/'.$this->id.'?fields=id,name,picture,access_token,can_post,likes,fan_count,link,username';
73 | $result = $this->request($path);
74 | $json_result = json_decode($result, true);
75 |
76 | $mapping = [
77 | 'id' => 'id',
78 | 'name' => 'name',
79 | 'link' => 'link',
80 | 'can_post' => 'can_post',
81 | 'access_token' => 'access_token',
82 | 'likes' => 'likes',
83 | 'fan_count' => 'fan_count'
84 | ];
85 |
86 | $this->page = Page::create($mapping, $json_result);
87 | $this->page->provider = static::$provider;
88 | $this->page->raw_response = $result;
89 | }
90 |
91 | return $this->page;
92 | }
93 |
94 |
95 | /**
96 | * Get the number of likes this page has.
97 | */
98 | public function getStats()
99 | {
100 | return $this->getLikesCount();
101 | }
102 |
103 |
104 | /***************************************************************************
105 | *
106 | * From here on these are FacebookPage-specific methods that should not be
107 | * accessed from other classes.
108 | *
109 | **************************************************************************/
110 |
111 | protected function getLikesCount()
112 | {
113 | return $this->getPage()->fan_count;
114 | }
115 |
116 |
117 | public function addTab($page_id, $page_access_token, $app_id, array $params = [])
118 | {
119 | $path = '/'.$page_id.'/tabs';
120 | $method = 'POST';
121 | $static_params = [
122 | 'app_id' => $app_id,
123 | 'access_token' => $page_access_token
124 | ];
125 |
126 | $params = array_merge($static_params, $params);
127 |
128 | $response = $this->request($path, $method, $params);
129 | $response = json_decode($response);
130 |
131 | return $response;
132 | }
133 |
134 |
135 | public function getTabs($page_id, $page_access_token, $app_id)
136 | {
137 | $path = '/'.$page_id.'/tabs';
138 | $path .= '?access_token='.$page_access_token;
139 | $method = 'GET';
140 |
141 | $response = $this->request($path, $method);
142 | $response = json_decode($response);
143 |
144 | return $response;
145 | }
146 |
147 |
148 | public function getTab($page_id, $page_access_token, $app_id)
149 | {
150 | $path = '/'.$page_id.'/tabs/app_'.$app_id;
151 | $path .= '?access_token='.$page_access_token;
152 | $method = 'GET';
153 |
154 | $response = $this->request($path, $method);
155 | $response = json_decode($response);
156 |
157 | return $response;
158 | }
159 |
160 |
161 | public function updateTab($page_id, $page_access_token, $app_id, array $params)
162 | {
163 | $path = '/'.$page_id.'/tabs/app_'.$app_id;
164 | $method = 'POST';
165 | $params['access_token'] = $page_access_token;
166 |
167 | $response = $this->request($path, $method, $params);
168 | $response = json_decode($response);
169 |
170 | return $response;
171 | }
172 |
173 |
174 | public function removeTab($page_id, $page_access_token, $app_id)
175 | {
176 | $path = '/'.$page_id.'/tabs/app_'.$app_id;
177 | $path .= '?access_token='.$page_access_token;
178 | $method = 'DELETE';
179 | $params = [
180 | 'app_id' => $app_id,
181 | 'access_token' => $page_access_token
182 | ];
183 |
184 | $response = $this->request($path, $method, $params);
185 | $response = json_decode($response);
186 |
187 | return $response;
188 | }
189 | }
190 |
--------------------------------------------------------------------------------
/src/Connectors/Linkedin.php:
--------------------------------------------------------------------------------
1 | [
53 | 'code' => 'anyone'
54 | ],
55 | 'comment' => '',
56 | 'content' => [
57 | 'title' => $post->title,
58 | 'submitted-url' => $post->url,
59 | 'description' => $post->body,
60 | ]
61 | ];
62 |
63 | if (!empty($post->media)) {
64 | $params['content']['submitted-image-url'] = $post->media[0];
65 | }
66 |
67 | $params = json_encode($params);
68 |
69 | $result = $this->request($path, $method, $params);
70 |
71 | $response = new Response;
72 | $response->setRawResponse($result); // This is already JSON.
73 | $response->setProvider(static::$provider);
74 | $result_json = json_decode($result);
75 | $response->setPostId($result_json->updateKey);
76 | $response->setPostUrl($result_json->updateUrl);
77 |
78 | return $response;
79 | }
80 |
81 |
82 | public function getProfile()
83 | {
84 | $path = '/people/~:(id,first-name,last-name,maiden-name,public-profile-url,formatted-name,num-connections,email-address,num-recommenders)?format=json';
85 | $result = $this->request($path);
86 | $json_result = json_decode($result, true);
87 |
88 | $mapping = [
89 | 'id' => 'id',
90 | 'email' => 'emailAddress',
91 | 'name' => 'formattedName',
92 | 'first_name' => 'firstName',
93 | 'middle_name' => 'maidenName',
94 | 'last_name' => 'lastName',
95 | // 'username' => 'username',
96 | 'link' => 'publicProfileUrl',
97 | 'likes' => 'numConnections'
98 | ];
99 |
100 | $profile = Profile::create($mapping, $json_result);
101 | $profile->provider = static::$provider;
102 | $profile->raw_response = $result;
103 |
104 | return $profile;
105 | }
106 |
107 | public function getStats()
108 | {
109 | $profile = $this->getProfile();
110 |
111 | return $profile->likes;
112 | }
113 |
114 | public function getPermissions()
115 | {
116 | return null;
117 | }
118 |
119 | public function getPages()
120 | {
121 | $path = '/companies:(id,name,universal-name,square-logo-url,num-followers)?is-company-admin=true&format=json';
122 | $result = $this->request($path);
123 | $json_result = json_decode($result, true);
124 |
125 | $pages = [];
126 |
127 | $mapping = [
128 | 'id' => 'id',
129 | 'name' => 'name',
130 | 'picture' => 'squareLogoUrl',
131 | 'link' => 'publicProfileUrl'
132 | ];
133 |
134 | // Make th epage IDs available as the array keys and get their picture
135 | if (!empty($json_result['values'])) {
136 | foreach ($json_result['values'] as $company) {
137 | $pages[$company['id']] = Page::create($mapping, $company);
138 | $pages[$company['id']]->link = 'http://www.linkedin.com/company/'.$company['universalName'];
139 | $pages[$company['id']]->provider = static::$provider;
140 | $pages[$company['id']]->raw_response = $result;
141 | }
142 | }
143 |
144 | return $pages;
145 | }
146 |
147 |
148 | public function getGroups()
149 | {
150 | $path = '/people/~/group-memberships:(group:(id,name,site-group-url,small-logo-url,num-members,relation-to-viewer))?&format=json&count=999';
151 | $response = $this->request($path);
152 | $groups = json_decode($response, true);
153 |
154 | $group_pages = [];
155 |
156 | $mapping = [
157 | 'id' => 'id',
158 | 'name' => 'name',
159 | 'picture' => 'smallLogoUrl',
160 | 'link' => 'siteGroupUrl'
161 | ];
162 |
163 | // Make the page IDs available as the array keys and get their picture
164 | if (!empty($groups['values'])) {
165 | foreach ($groups['values'] as $group) {
166 | $group_pages[$group['_key']] = Group::create($mapping, $group['group']);
167 | $group_pages[$group['_key']]->provider = static::$provider;
168 | $group_pages[$group['_key']]->raw_response = $response;
169 |
170 | // Let's check if our user can post to this group.
171 | // Thank you for this wonder, LinkedIn! It's so fun parsing infinitely nested arrays...
172 | $actions = $group['group']['relationToViewer']['availableActions']['values'];
173 | array_walk($actions, function ($value) use ($group, $group_pages) {
174 | if ($value['code'] === 'add-post') {
175 | $group_pages[$group['_key']]->can_post = true;
176 | }
177 | });
178 | }
179 | }
180 |
181 | return $group_pages;
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/Connectors/LinkedinGroup.php:
--------------------------------------------------------------------------------
1 | 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 | 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 |
--------------------------------------------------------------------------------
/src/Connectors/LinkedinPage.php:
--------------------------------------------------------------------------------
1 | options['page_id'];
21 | $path = '/companies/'.$page_id.'/shares?format=json';
22 | $method = 'POST';
23 | $params = [
24 | 'visibility' => [
25 | 'code' => 'anyone'
26 | ],
27 | 'comment' => '',
28 | 'content' => [
29 | 'title' => $post->title,
30 | 'submitted-url' => $post->url,
31 | 'description' => $post->body,
32 | ],
33 | ];
34 |
35 | if (!empty($post->media)) {
36 | $params['content']['submitted-image-url'] = $post->media[0];
37 | }
38 |
39 | $params = json_encode($params);
40 |
41 | // Linkedin API requires the Content-Type header set to application/json
42 | $header = ['Content-Type' => 'application/json'];
43 | $result = $this->request($path, $method, $params, $header);
44 |
45 | // The response comes in JSON
46 | $json_result = json_decode($result, true);
47 |
48 | if (isset($json_result['status']) && $json_result['status'] != 200) {
49 | $msg = "Error posting to Linkedin page. Error code from Linkedin: %s. Error message from Linkedin: %s";
50 | $msg = sprintf($msg, $json_result['errorCode'], $json_result['message']);
51 |
52 | if ($json_result['status'] == '401') {
53 | throw new ExpiredTokenException($msg);
54 | } else {
55 | throw new GenericPostingException($msg, $json_result['status']);
56 | }
57 | }
58 |
59 | $response = new Response;
60 | $response->setRawResponse(json_encode($result));
61 | $response->setProvider(static::$provider);
62 | $result_json = json_decode($result);
63 | $response->setPostId($result_json->updateKey);
64 | $response->setPostUrl($result_json->updateUrl);
65 |
66 | return $response;
67 | }
68 |
69 |
70 | public function getProfile()
71 | {
72 | $path = '/people/~:(id,first-name,last-name,maiden-name,public-profile-url,formatted-name,num-connections,email-address,num-recommenders)?format=json';
73 | $response = $this->service->request($path);
74 | $profile_json = json_decode($response, true);
75 |
76 | $mapping = [
77 | 'id' => 'id',
78 | 'email' => 'emailAddress',
79 | 'name' => 'formattedName',
80 | 'first_name' => 'firstName',
81 | 'middle_name' => 'maidenName',
82 | 'last_name' => 'lastName',
83 | // 'username' => 'username',
84 | 'link' => 'publicProfileUrl'
85 | ];
86 |
87 | $profile = Profile::create($mapping, $profile_json);
88 | $profile->provider = static::$provider;
89 | $profile->raw_response = $response;
90 |
91 | return $profile;
92 | }
93 |
94 | public function getStats()
95 | {
96 | $path = 'companies/'.$this->id.':(id,num-followers)?format=json';
97 | $response = json_decode($this->request($path));
98 |
99 | return $response->numFollowers;
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/Connectors/Tumblr.php:
--------------------------------------------------------------------------------
1 | service->requestRequestToken();
32 | $extra = ['oauth_token' => $token->getRequestToken()];
33 | return parent::getAuthorizationUri($extra);
34 | }
35 |
36 |
37 | /**
38 | * Retrieve the auth token from the provider's response and store it.
39 | */
40 | public function storeOauthToken($params)
41 | {
42 | try {
43 | $token = $this->service->getStorage()->retrieveAccessToken('Tumblr');
44 | } catch (TokenNotFoundException $e) {
45 | throw new AuthorizationException();
46 | }
47 | $this->service->requestAccessToken($params['oauth_token'], $params['oauth_verifier'], $token->getRequestTokenSecret());
48 | }
49 |
50 | public function getProfile()
51 | {
52 | $path = 'user/info';
53 | $result = $this->request($path);
54 | $profile_json = json_decode($result, true);
55 |
56 | $mapping = [
57 | 'id' => 'name',
58 | 'name' => 'name',
59 | 'username' => 'name',
60 | 'likes' => 'likes'
61 | ];
62 |
63 | $profile = Profile::create($mapping, $profile_json['response']['user']);
64 | $profile->provider = static::$provider;
65 | $profile->raw_response = $result;
66 | $profile->link = 'https://www.tumblr.com';
67 |
68 | return $profile;
69 | }
70 |
71 |
72 | public function getBlogs()
73 | {
74 | $path = 'user/info';
75 | $result = $this->request($path);
76 | $profile_json = json_decode($result, true);
77 |
78 | $mapping = [
79 | 'id' => 'name',
80 | 'link' => 'url',
81 | 'title' => 'title',
82 | 'name' => 'name',
83 | 'description' => 'description',
84 | 'ask' => 'ask',
85 | 'ask_anon' => 'ask_anon',
86 | ];
87 |
88 | $blogs = [];
89 |
90 | foreach ($profile_json['response']['user']['blogs'] as $blog) {
91 | $blogs[$blog['name']] = Blog::create($mapping, $blog);
92 | }
93 |
94 | return $blogs;
95 | }
96 |
97 |
98 | public function getPermissions()
99 | {
100 | return null;
101 | }
102 |
103 | public function getStats()
104 | {
105 | $profile = $this->getProfile();
106 |
107 | return $profile->likes;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/Connectors/TumblrBlog.php:
--------------------------------------------------------------------------------
1 | meta->status;
23 |
24 | if ($status < 200 || $status > 299) {
25 | $msg = $json_result->meta->msg;
26 |
27 | if ($status == 400) {
28 | $media_error_messages = [
29 | "Error uploading photo.",
30 | "Nice image, but we don't support that format. Try resaving it as a gif, jpg, or png.",
31 | ];
32 |
33 | foreach ($media_error_messages as $media_error_message) {
34 | if (strpos($json_result->response->errors[0], $media_error_message) !== false) {
35 | $msg .= ': ' . $media_error_message;
36 | }
37 | }
38 | }
39 |
40 | throw new TumblrPostingException($msg, $status);
41 | }
42 |
43 | return $result;
44 | }
45 |
46 |
47 | public function post(Post $post)
48 | {
49 | $path = 'blog/'.$this->options['base_hostname'].'/post';
50 | $method = 'POST';
51 |
52 | $params = [];
53 | if (!empty($post->tags)) {
54 | $params['tags'] = $post->tags;
55 | }
56 |
57 |
58 | if (empty($post->media)) {
59 | $body = '
' . $post->body . '
';
60 | $body .= '' . $post->url . '';
61 |
62 | $params['type'] = 'text';
63 | $params['title'] = $post->title;
64 | $params['body'] = $body;
65 | } else {
66 | $caption = '' . $post->title . '
';
67 | $caption .= '' . $post->body . '
';
68 | $caption .= '' . $post->url . '';
69 |
70 | $params['type'] = 'photo';
71 | $params['caption'] = $caption;
72 | $params['source'] = $post->media[0];
73 | }
74 |
75 | $result = $this->request($path, $method, $params);
76 |
77 | $response = new Response;
78 | $response->setRawResponse(json_encode($result));
79 | $result_json = json_decode($result);
80 | $response->setProvider('Tumblr');
81 | $response->setPostId($result_json->response->id);
82 |
83 | return $response;
84 | }
85 |
86 | public function getBlog()
87 | {
88 | $api_key = $this->config['consumer_key'];
89 | $path = 'blog/'.$this->options['base_hostname'].'/info?api_key='.$api_key;
90 | $result = $this->request($path);
91 | $json_result = json_decode($result, true);
92 |
93 | $mapping = [
94 | 'id' => 'name',
95 | 'link' => 'url',
96 | 'title' => 'title',
97 | 'name' => 'name',
98 | 'description' => 'description',
99 | 'ask' => 'ask',
100 | 'ask_anon' => 'ask_anon',
101 | 'followers' => 'followers'
102 | ];
103 |
104 | $blog = Blog::create($mapping, $json_result['response']['blog']);
105 |
106 | return $blog;
107 | }
108 |
109 |
110 | public function getPermissions()
111 | {
112 | return null;
113 | }
114 |
115 | public function getStats()
116 | {
117 | $profile = $this->getBlog();
118 |
119 | return $profile->followers;
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/src/Connectors/Twitter.php:
--------------------------------------------------------------------------------
1 | $post->body
68 | ];
69 |
70 | if (!empty($post->media)) {
71 | $params['media_ids'] = implode(',', $post->media);
72 | }
73 |
74 | $result = $this->request($path, $method, $params);
75 |
76 | $response = new Response;
77 | $response->setRawResponse(json_encode($result));
78 | $result_json = json_decode($result);
79 | $response->setProvider('Twitter');
80 | $response->setPostId($result_json->id_str);
81 |
82 | return $response;
83 | }
84 |
85 |
86 | public function postMedia($media)
87 | {
88 | $path = 'https://upload.twitter.com/1.1/media/upload.json';
89 | $method = 'POST';
90 | $params = [
91 | 'media' => $media
92 | ];
93 |
94 | $result = $this->request($path, $method, $params);
95 | $json_result = json_decode($result, true);
96 |
97 | return $json_result;
98 | }
99 |
100 |
101 | /**
102 | * Twitter needs an extra step for authentication before providing an
103 | * authorization URL.
104 | *
105 | * @author Raúl Santos
106 | */
107 | public function getAuthorizationUri(array $params = [])
108 | {
109 | $token = $this->service->requestRequestToken();
110 | $extra = ['oauth_token' => $token->getRequestToken()];
111 | return parent::getAuthorizationUri($extra);
112 | }
113 |
114 |
115 | /**
116 | * Retrieve the auth token from the provider's response and store it.
117 | */
118 | public function storeOauthToken($params)
119 | {
120 | try {
121 | $token = $this->service->getStorage()->retrieveAccessToken('Twitter');
122 | } catch (TokenNotFoundException $e) {
123 | throw new AuthorizationException();
124 | }
125 | $result = $this->service->requestAccessToken($params['oauth_token'], $params['oauth_verifier'], $token->getRequestTokenSecret());
126 |
127 | $extra_params = $result->getExtraParams();
128 | $this->user_id = $extra_params['user_id'];
129 | $this->screen_name = $extra_params['screen_name'];
130 | }
131 |
132 | public function getProfile()
133 | {
134 | $path = '/account/verify_credentials.json?skip_status=1';
135 | $result = $this->request($path);
136 | $profile_json = json_decode($result, true);
137 |
138 | $mapping = [
139 | 'id' => 'id_str',
140 | // 'email' => 'email',
141 | 'name' => 'name',
142 | 'first_name' => 'first_name',
143 | 'middle_name' => 'middle_name',
144 | 'last_name' => 'last_name',
145 | 'username' => 'screen_name',
146 | 'link' => 'link'
147 | ];
148 |
149 | $profile = Profile::create($mapping, $profile_json);
150 | $profile->provider = static::$provider;
151 | $profile->raw_response = $result;
152 | $profile->link = 'https://twitter.com/'.$profile_json['screen_name'];
153 |
154 | return $profile;
155 | }
156 |
157 | public function getPermissions()
158 | {
159 | return null;
160 | }
161 |
162 | public function getStats()
163 | {
164 | $path = '/followers/ids.json?user_id='.$this->id;
165 | $response = $this->request($path);
166 | $response = json_decode($response);
167 | $response = count($response->ids);
168 | return $response;
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/src/Exceptions/AuthorizationException.php:
--------------------------------------------------------------------------------
1 | message = sprintf($this->message, $provider);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Exceptions/LinkedinForbiddenException.php:
--------------------------------------------------------------------------------
1 | getMessage(), $parent->getCode(), $parent);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Exceptions/LinkedinPostingException.php:
--------------------------------------------------------------------------------
1 | 'id',
24 | * 'email' => 'email',
25 | * 'name' => 'name',
26 | * 'first_name' => 'first_name',
27 | * 'middle_name' => 'middle_name',
28 | * 'last_name' => 'last_name',
29 | * 'username' => 'username',
30 | * 'link' => 'link'
31 | * ];
32 | * The keys are the name of the Group object attributes, while the values
33 | * are the key of that attribute in the $attributes array. Like so:
34 | * ['group_object_attribute' => 'key_in_attributes_array']
35 | *
36 | * @author Raúl Santos
37 | */
38 | public static function create(array $mapping, array $attributes)
39 | {
40 | $group = new Group;
41 |
42 | foreach ($mapping as $key => $name) {
43 | $group->$key = (isset($attributes[$name])) ? $attributes[$name] : null;
44 | }
45 |
46 | return $group;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/Page.php:
--------------------------------------------------------------------------------
1 | 'id',
26 | * 'email' => 'email',
27 | * 'name' => 'name',
28 | * 'first_name' => 'first_name',
29 | * 'middle_name' => 'middle_name',
30 | * 'last_name' => 'last_name',
31 | * 'username' => 'username',
32 | * 'link' => 'link'
33 | * ];
34 | * The keys are the name of the Page object attributes, while the values
35 | * are the key of that attribute in the $attributes array. Like so:
36 | * ['page_object_attribute' => 'key_in_attributes_array']
37 | *
38 | * @author Raúl Santos
39 | */
40 | public static function create(array $mapping, array $attributes)
41 | {
42 | $page = new Page;
43 |
44 | foreach ($mapping as $key => $name) {
45 | $page->$key = (isset($attributes[$name])) ? $attributes[$name] : null;
46 | }
47 |
48 | return $page;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Post.php:
--------------------------------------------------------------------------------
1 | 'id',
28 | * 'email' => 'email',
29 | * 'name' => 'name',
30 | * 'first_name' => 'first_name',
31 | * 'middle_name' => 'middle_name',
32 | * 'last_name' => 'last_name',
33 | * 'username' => 'username',
34 | * 'link' => 'link'
35 | * ];
36 | *
37 | * The keys are the name of the Profile object attributes, while the values
38 | * are the key of that attribute in the $attributes array. Like so:
39 | * ['profile_object_attribute' => 'key_in_attributes_array']
40 | *
41 | * @param array $mapping
42 | * @param array $attributes
43 | * @return static
44 | */
45 | public static function create(array $mapping, array $attributes)
46 | {
47 | $profile = new Profile;
48 |
49 | array_walk($mapping, function (&$name, $key) use (&$profile, &$attributes) {
50 | $profile->$key = (isset($attributes[$name])) ? $attributes[$name] : null;
51 | });
52 |
53 | return $profile;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Response.php:
--------------------------------------------------------------------------------
1 | raw_response = $raw_response;
16 | return $this;
17 | }
18 |
19 | public function setProvider($provider)
20 | {
21 | $this->provider = $provider;
22 | return $this;
23 | }
24 |
25 | public function setPostId($post_id)
26 | {
27 | $this->post_id = $post_id;
28 | return $this;
29 | }
30 |
31 | public function setPostUrl($post_url)
32 | {
33 | $this->post_url = $post_url;
34 | return $this;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Stats.php:
--------------------------------------------------------------------------------
1 | config = [
14 | 'callback' => 'blah',
15 | 'providers' => [
16 | 'Twitter' => [
17 | 'consumer_key' => 'aaa',
18 | 'consumer_secret' => 'bbb',
19 | 'service' => 'Twitter',
20 | ],
21 | 'Facebook' => [
22 | 'consumer_key' => 'aaa',
23 | 'consumer_secret' => 'bbb',
24 | 'scopes' => 'email, publish_stream, manage_pages, publish_actions',
25 | 'service' => 'Facebook',
26 | ],
27 | 'Linkedin' => [
28 | 'consumer_key' => 'aaa',
29 | 'consumer_secret' => 'bbb',
30 | 'scopes' => 'r_fullprofile, r_emailaddress, rw_nus, rw_company_admin, r_network, rw_groups',
31 | 'csrf_token_name' => 'state',
32 | 'service' => 'Linkedin',
33 | ],
34 | 'Google' => [
35 | 'consumer_key' => 'aaa',
36 | 'consumer_secret' => 'bbb',
37 | 'public_api_key' => 'ccc', // Google-specific
38 | 'service' => 'Google',
39 | ],
40 | ]
41 | ];
42 |
43 | $this->config['providers']['FacebookPage'] = $this->config['providers']['Facebook'];
44 | $this->config['providers']['LinkedinPage'] = $this->config['providers']['Linkedin'];
45 | $this->config['providers']['LinkedinGroup'] = $this->config['providers']['Linkedin'];
46 |
47 | $this->id = 'foo';
48 |
49 | $this->mock_storage = m::mock("OAuth\\Common\\Storage\\TokenStorageInterface");
50 | $this->factory = new ConnectorFactory($this->config);
51 | }
52 |
53 |
54 | public function tearDown()
55 | {
56 | m::close();
57 | }
58 |
59 |
60 | public function testEmptyArrayConfigThrowsException()
61 | {
62 | $this->setExpectedException('Borfast\\Socializr\\Exceptions\\InvalidConfigurationException');
63 |
64 | $factory = new ConnectorFactory([]);
65 | }
66 |
67 |
68 | public function testCreateTwitterConnectorReturnsCorrectClass()
69 | {
70 | $connector = $this->factory->createConnector(
71 | 'Twitter',
72 | $this->mock_storage,
73 | [],
74 | $this->id
75 | );
76 |
77 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\Twitter", $connector);
78 | }
79 |
80 |
81 | public function testCreateFacebookConnectorReturnsCorrectClass()
82 | {
83 | $connector = $this->factory->createConnector(
84 | 'Facebook',
85 | $this->mock_storage,
86 | [],
87 | $this->id
88 | );
89 |
90 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\Facebook", $connector);
91 | }
92 |
93 |
94 | public function testCreateFacebookPageConnectorReturnsCorrectClass()
95 | {
96 | $connector = $this->factory->createConnector(
97 | 'FacebookPage',
98 | $this->mock_storage,
99 | [],
100 | $this->id
101 | );
102 |
103 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\FacebookPage", $connector);
104 | }
105 |
106 |
107 | public function testCreateLinkedinConnectorReturnsCorrectClass()
108 | {
109 | $connector = $this->factory->createConnector(
110 | 'Linkedin',
111 | $this->mock_storage,
112 | [],
113 | $this->id
114 | );
115 |
116 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\Linkedin", $connector);
117 | }
118 |
119 |
120 | public function testCreateLinkedinPageConnectorReturnsCorrectClass()
121 | {
122 | $connector = $this->factory->createConnector(
123 | 'LinkedinPage',
124 | $this->mock_storage,
125 | [],
126 | $this->id
127 | );
128 |
129 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\LinkedinPage", $connector);
130 | }
131 |
132 |
133 | public function testCreateLinkedinGroupConnectorReturnsCorrectClass()
134 | {
135 | $connector = $this->factory->createConnector(
136 | 'LinkedinGroup',
137 | $this->mock_storage,
138 | [],
139 | $this->id
140 | );
141 |
142 | $this->assertInstanceOf("\\Borfast\\Socializr\\Connectors\\LinkedinGroup", $connector);
143 | }
144 |
145 |
146 | public function testCreateInvalidConnectorThrowsException()
147 | {
148 | $this->setExpectedException("Borfast\\Socializr\\Exceptions\\InvalidProviderException");
149 |
150 | $connector = $this->factory->createConnector(
151 | 'invalid',
152 | $this->mock_storage,
153 | [],
154 | $this->id
155 | );
156 | }
157 | }
158 |
--------------------------------------------------------------------------------