forked from qwerty/milfs
2724 lines
91 KiB
PHP
2724 lines
91 KiB
PHP
|
<?php
|
||
|
// http://code.google.com/p/simple-linkedinphp/
|
||
|
// 3.2.0 - November 29, 2011
|
||
|
// hacked into the code to handel new scope (r_basicprofile+r_emailaddress) - until Paul update linkedinphp library!
|
||
|
// Facyla note 20131219 : this in fact should not be hacked, as Linkedin lets developpers define the wanted scope
|
||
|
// in Linkedin application settings, when creating the (required) application and API access
|
||
|
|
||
|
/**
|
||
|
* This file defines the 'LinkedIn' class. This class is designed to be a
|
||
|
* simple, stand-alone implementation of the LinkedIn API functions.
|
||
|
*
|
||
|
* COPYRIGHT:
|
||
|
*
|
||
|
* Copyright (C) 2011, fiftyMission Inc.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||
|
* copy of this software and associated documentation files (the "Software"),
|
||
|
* to deal in the Software without restriction, including without limitation
|
||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||
|
* Software is furnished to do so, subject to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice shall be included in
|
||
|
* all copies or substantial portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||
|
* IN THE SOFTWARE.
|
||
|
*
|
||
|
* SOURCE CODE LOCATION:
|
||
|
*
|
||
|
* http://code.google.com/p/simple-linkedinphp/
|
||
|
*
|
||
|
* REQUIREMENTS:
|
||
|
*
|
||
|
* 1. You must have cURL installed on the server and available to PHP.
|
||
|
* 2. You must be running PHP 5+.
|
||
|
*
|
||
|
* QUICK START:
|
||
|
*
|
||
|
* There are two files needed to enable LinkedIn API functionality from PHP; the
|
||
|
* stand-alone OAuth library, and this LinkedIn class. The latest version of
|
||
|
* the stand-alone OAuth library can be found on Google Code:
|
||
|
*
|
||
|
* http://code.google.com/p/oauth/
|
||
|
*
|
||
|
* Install these two files on your server in a location that is accessible to
|
||
|
* the scripts you wish to use them in. Make sure to change the file
|
||
|
* permissions such that your web server can read the files.
|
||
|
*
|
||
|
* Next, make sure the path to the OAuth library is correct (you can change this
|
||
|
* as needed, depending on your file organization scheme, etc).
|
||
|
*
|
||
|
* Finally, test the class by attempting to connect to LinkedIn using the
|
||
|
* associated demo.php page, also located at the Google Code location
|
||
|
* referenced above.
|
||
|
*
|
||
|
* RESOURCES:
|
||
|
*
|
||
|
* REST API Documentation: http://developer.linkedin.com/rest
|
||
|
*
|
||
|
* @version 3.2.0 - November 8, 2011
|
||
|
* @author Paul Mennega <paul@fiftymission.net>
|
||
|
* @copyright Copyright 2011, fiftyMission Inc.
|
||
|
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* 'LinkedInException' class declaration.
|
||
|
*
|
||
|
* This class extends the base 'Exception' class.
|
||
|
*
|
||
|
* @access public
|
||
|
* @package classpackage
|
||
|
*/
|
||
|
class LinkedInException extends Exception {}
|
||
|
|
||
|
/**
|
||
|
* 'LinkedIn' class declaration.
|
||
|
*
|
||
|
* This class provides generalized LinkedIn oauth functionality.
|
||
|
*
|
||
|
* @access public
|
||
|
* @package classpackage
|
||
|
*/
|
||
|
class LinkedIn {
|
||
|
// api/oauth settings
|
||
|
const _API_OAUTH_REALM = 'http://api.linkedin.com';
|
||
|
const _API_OAUTH_VERSION = '1.0';
|
||
|
|
||
|
// the default response format from LinkedIn
|
||
|
const _DEFAULT_RESPONSE_FORMAT = 'xml';
|
||
|
|
||
|
// helper constants used to standardize LinkedIn <-> API communication. See demo page for usage.
|
||
|
const _GET_RESPONSE = 'lResponse';
|
||
|
const _GET_TYPE = 'lType';
|
||
|
|
||
|
// Invitation API constants.
|
||
|
const _INV_SUBJECT = 'Invitation to connect';
|
||
|
const _INV_BODY_LENGTH = 200;
|
||
|
|
||
|
// API methods
|
||
|
const _METHOD_TOKENS = 'POST';
|
||
|
|
||
|
// Network API constants.
|
||
|
const _NETWORK_LENGTH = 1000;
|
||
|
const _NETWORK_HTML = '<a>';
|
||
|
|
||
|
// response format type constants, see http://developer.linkedin.com/docs/DOC-1203
|
||
|
const _RESPONSE_JSON = 'JSON';
|
||
|
const _RESPONSE_JSONP = 'JSONP';
|
||
|
const _RESPONSE_XML = 'XML';
|
||
|
|
||
|
// Share API constants
|
||
|
const _SHARE_COMMENT_LENGTH = 700;
|
||
|
const _SHARE_CONTENT_TITLE_LENGTH = 200;
|
||
|
const _SHARE_CONTENT_DESC_LENGTH = 400;
|
||
|
|
||
|
// LinkedIn API end-points
|
||
|
const _URL_ACCESS = 'https://api.linkedin.com/uas/oauth/accessToken';
|
||
|
const _URL_API = 'https://api.linkedin.com';
|
||
|
const _URL_AUTH = 'https://www.linkedin.com/uas/oauth/authenticate?oauth_token=';
|
||
|
const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken';
|
||
|
// const _URL_REQUEST = 'https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress+rw_nus+r_network';
|
||
|
const _URL_REVOKE = 'https://api.linkedin.com/uas/oauth/invalidateToken';
|
||
|
|
||
|
// Library version
|
||
|
const _VERSION = '3.2.0';
|
||
|
|
||
|
// oauth properties
|
||
|
protected $callback;
|
||
|
protected $token = null;
|
||
|
|
||
|
// application properties
|
||
|
protected $application_key,
|
||
|
$application_secret;
|
||
|
|
||
|
// the format of the data to return
|
||
|
protected $response_format = self::_DEFAULT_RESPONSE_FORMAT;
|
||
|
|
||
|
// last request fields
|
||
|
public $last_request_headers,
|
||
|
$last_request_url;
|
||
|
|
||
|
/**
|
||
|
* Create a LinkedIn object, used for OAuth-based authentication and
|
||
|
* communication with the LinkedIn API.
|
||
|
*
|
||
|
* @param arr $config
|
||
|
* The 'start-up' object properties:
|
||
|
* - appKey => The application's API key
|
||
|
* - appSecret => The application's secret key
|
||
|
* - callbackUrl => [OPTIONAL] the callback URL
|
||
|
*
|
||
|
* @return obj
|
||
|
* A new LinkedIn object.
|
||
|
*/
|
||
|
public function __construct($config) {
|
||
|
if(!is_array($config)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->__construct(): bad data passed, $config must be of type array.');
|
||
|
}
|
||
|
$this->setApplicationKey($config['appKey']);
|
||
|
$this->setApplicationSecret($config['appSecret']);
|
||
|
$this->setCallbackUrl($config['callbackUrl']);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* The class destructor.
|
||
|
*
|
||
|
* Explicitly clears LinkedIn object from memory upon destruction.
|
||
|
*/
|
||
|
public function __destruct() {
|
||
|
unset($this);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Bookmark a job.
|
||
|
*
|
||
|
* Calling this method causes the current user to add a bookmark for the
|
||
|
* specified job:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1323
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* Job ID you want to bookmark.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function bookmarkJob($jid) {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->bookmarkJob(): bad data passed, $jid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/job-bookmarks';
|
||
|
$response = $this->fetch('POST', $query, '<job-bookmark><job><id>' . trim($jid) . '</id></job></job-bookmark>');
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get list of jobs you have bookmarked.
|
||
|
*
|
||
|
* Returns a list of jobs the current user has bookmarked, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1323
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function bookmarkedJobs() {
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/job-bookmarks';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Custom addition to make code compatible with PHP 5.2
|
||
|
*/
|
||
|
private function intWalker($value, $key) {
|
||
|
if(!is_int($value)) {
|
||
|
throw new LinkedInException('LinkedIn->checkResponse(): $http_code_required must be an integer or an array of integer values');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Used to check whether a response LinkedIn object has the required http_code or not and
|
||
|
* returns an appropriate LinkedIn object.
|
||
|
*
|
||
|
* @param var $http_code_required
|
||
|
* The required http response from LinkedIn, passed in either as an integer,
|
||
|
* or an array of integers representing the expected values.
|
||
|
* @param arr $response
|
||
|
* An array containing a LinkedIn response.
|
||
|
*
|
||
|
* @return boolean
|
||
|
* true or false depending on if the passed LinkedIn response matches the expected response.
|
||
|
*/
|
||
|
private function checkResponse($http_code_required, $response) {
|
||
|
// check passed data
|
||
|
if(is_array($http_code_required)) {
|
||
|
array_walk($http_code_required, array($this, 'intWalker'));
|
||
|
} else {
|
||
|
if(!is_int($http_code_required)) {
|
||
|
throw new LinkedInException('LinkedIn->checkResponse(): $http_code_required must be an integer or an array of integer values');
|
||
|
} else {
|
||
|
$http_code_required = array($http_code_required);
|
||
|
}
|
||
|
}
|
||
|
if(!is_array($response)) {
|
||
|
throw new LinkedInException('LinkedIn->checkResponse(): $response must be an array');
|
||
|
}
|
||
|
|
||
|
// check for a match
|
||
|
if(in_array($response['info']['http_code'], $http_code_required)) {
|
||
|
// response found
|
||
|
$response['success'] = true;
|
||
|
} else {
|
||
|
// response not found
|
||
|
$response['success'] = false;
|
||
|
$response['error'] = 'HTTP response from LinkedIn end-point was not code ' . implode(', ', $http_code_required);
|
||
|
}
|
||
|
return $response;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Close a job.
|
||
|
*
|
||
|
* Calling this method causes the passed job to be closed, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1151
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* Job ID you want to close.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function closeJob($jid) {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->closeJob(): bad data passed, $jid must be of string value.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/jobs/partner-job-id=' . trim($jid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Share comment posting method.
|
||
|
*
|
||
|
* Post a comment on an existing connections shared content. API details can
|
||
|
* be found here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $uid
|
||
|
* The LinkedIn update ID.
|
||
|
* @param str $comment
|
||
|
* The share comment to be posted.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function comment($uid, $comment) {
|
||
|
// check passed data
|
||
|
if(!is_string($uid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->comment(): bad data passed, $uid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($comment)) {
|
||
|
// nothing/non-string passed, raise an exception
|
||
|
throw new LinkedInException('LinkedIn->comment(): bad data passed, $comment must be a non-zero length string.');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Share comment rules:
|
||
|
*
|
||
|
* 1) No HTML permitted.
|
||
|
* 2) Comment cannot be longer than 700 characters.
|
||
|
*/
|
||
|
$comment = substr(trim(htmlspecialchars(strip_tags($comment))), 0, self::_SHARE_COMMENT_LENGTH);
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<update-comment>
|
||
|
<comment>' . $comment . '</comment>
|
||
|
</update-comment>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates/key=' . $uid . '/update-comments';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Share comment retrieval.
|
||
|
*
|
||
|
* Return all comments associated with a given network update:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $uid
|
||
|
* The LinkedIn update ID.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function comments($uid) {
|
||
|
// check passed data
|
||
|
if(!is_string($uid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->comments(): bad data passed, $uid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates/key=' . $uid . '/update-comments';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Company profile retrieval function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests company profile data
|
||
|
* from the LinkedIn Company Profile API. See the official documentation for
|
||
|
* $options 'field selector' formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1014
|
||
|
* http://developer.linkedin.com/docs/DOC-1259
|
||
|
*
|
||
|
* @param str $options
|
||
|
* Data retrieval options.
|
||
|
* @param bool $by_email
|
||
|
* [OPTIONAL] Search by email domain?
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function company($options, $by_email = false) {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->company(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
if(!is_bool($by_email)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->company(): bad data passed, $by_email must be of type boolean.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/companies' . ($by_email ? '' : '/') . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Company products and their associated recommendations.
|
||
|
*
|
||
|
* The product data type contains details about a company's product or
|
||
|
* service, including recommendations from LinkedIn members, and replies from
|
||
|
* company representatives.
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1327
|
||
|
*
|
||
|
* @param str $cid
|
||
|
* Company ID you want the product for.
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function companyProducts($cid, $options = '') {
|
||
|
// check passed data
|
||
|
if(!is_string($cid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->companyProducts(): bad data passed, $cid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->companyProducts(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/companies/' . trim($cid) . '/products' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Connection retrieval function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests connection-related data
|
||
|
* from the Linkedin Connections API. See the official documentation for
|
||
|
* $options 'field selector' formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1014
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function connections($options = '~/connections') {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->connections(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This creates a post in the specified group with the specified title and specified summary.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
* @param str $title
|
||
|
* The title of the post. This must be non-empty.
|
||
|
* @param str $summary
|
||
|
* [OPTIONAL] The content or summary of the post. This can be empty.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function createPost($gid, $title, $summary = '') {
|
||
|
if(!is_string($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->createPost(): bad data passed, $gid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($title) || empty($title)) {
|
||
|
throw new LinkedInException('LinkedIn->createPost(): bad data passed, $title must be a non-empty string.');
|
||
|
}
|
||
|
if(!is_string($summary)) {
|
||
|
throw new LinkedInException('LinkedIn->createPost(): bad data passed, $summary must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct the XML
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<post>
|
||
|
<title>'. $title . '</title>
|
||
|
<summary>' . $summary . '</summary>
|
||
|
</post>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/groups/' . trim($gid) . '/posts';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This deletes the specified post if you are the owner or moderator that post.
|
||
|
* Otherwise, it just flags the post as inappropriate.
|
||
|
*
|
||
|
* https://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function deletePost($pid) {
|
||
|
if(!is_string($pid)) {
|
||
|
throw new LinkedInException('LinkedIn->deletePost(): bad data passed, $pid must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . trim($pid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Edit a job.
|
||
|
*
|
||
|
* Calling this method causes the passed job to be edited, with the passed
|
||
|
* XML instructing which fields to change, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1154
|
||
|
* http://developer.linkedin.com/docs/DOC-1142
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* Job ID you want to renew.
|
||
|
* @param str $xml
|
||
|
* The XML containing the job fields to edit.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function editJob($jid, $xml) {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->editJob(): bad data passed, $jid must be of string value.');
|
||
|
}
|
||
|
if(is_string($xml)) {
|
||
|
$xml = trim(stripslashes($xml));
|
||
|
} else {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->editJob(): bad data passed, $xml must be of string value.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/jobs/partner-job-id=' . trim($jid);
|
||
|
$response = $this->fetch('PUT', $query, $xml);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* General data send/request method.
|
||
|
*
|
||
|
* @param str $method
|
||
|
* The data communication method.
|
||
|
* @param str $url
|
||
|
* The Linkedin API endpoint to connect with.
|
||
|
* @param str $data
|
||
|
* [OPTIONAL] The data to send to LinkedIn.
|
||
|
* @param arr $parameters
|
||
|
* [OPTIONAL] Addition OAuth parameters to send to LinkedIn.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing:
|
||
|
*
|
||
|
* array(
|
||
|
* 'info' => Connection information,
|
||
|
* 'linkedin' => LinkedIn response,
|
||
|
* 'oauth' => The OAuth request string that was sent to LinkedIn
|
||
|
* )
|
||
|
*/
|
||
|
protected function fetch($method, $url, $data = null, $parameters = array()) {
|
||
|
// check for cURL
|
||
|
if(!extension_loaded('curl')) {
|
||
|
// cURL not present
|
||
|
throw new LinkedInException('LinkedIn->fetch(): PHP cURL extension does not appear to be loaded/present.');
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
// generate OAuth values
|
||
|
$oauth_consumer = new OAuthConsumer($this->getApplicationKey(), $this->getApplicationSecret(), $this->getCallbackUrl());
|
||
|
$oauth_token = $this->getToken();
|
||
|
$oauth_token = (!is_null($oauth_token)) ? new OAuthToken($oauth_token['oauth_token'], $oauth_token['oauth_token_secret']) : null;
|
||
|
$defaults = array(
|
||
|
'oauth_version' => self::_API_OAUTH_VERSION
|
||
|
);
|
||
|
$parameters = array_merge($defaults, $parameters);
|
||
|
|
||
|
// generate OAuth request
|
||
|
$oauth_req = OAuthRequest::from_consumer_and_token($oauth_consumer, $oauth_token, $method, $url, $parameters);
|
||
|
$oauth_req->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $oauth_consumer, $oauth_token);
|
||
|
|
||
|
// start cURL, checking for a successful initiation
|
||
|
if(!$handle = curl_init()) {
|
||
|
// cURL failed to start
|
||
|
throw new LinkedInException('LinkedIn->fetch(): cURL did not initialize properly.');
|
||
|
}
|
||
|
|
||
|
// set cURL options, based on parameters passed
|
||
|
curl_setopt($handle, CURLOPT_CUSTOMREQUEST, $method);
|
||
|
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
|
||
|
curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);
|
||
|
curl_setopt($handle, CURLOPT_URL, $url);
|
||
|
curl_setopt($handle, CURLOPT_VERBOSE, false);
|
||
|
|
||
|
// Restrict the request timeout to 5 seconds. Linkedin is sometimes very
|
||
|
// slow and we don't want to trigger a PHP timeout on our end.
|
||
|
curl_setopt($handle, CURLOPT_TIMEOUT, 5);
|
||
|
|
||
|
if ( isset ( Hybrid_Auth::$config["proxy"] ) ) {
|
||
|
curl_setopt($handle, CURLOPT_PROXY, Hybrid_Auth::$config["proxy"]);
|
||
|
}
|
||
|
|
||
|
// configure the header we are sending to LinkedIn - http://developer.linkedin.com/docs/DOC-1203
|
||
|
$header = array($oauth_req->to_header(self::_API_OAUTH_REALM));
|
||
|
if(is_null($data)) {
|
||
|
// not sending data, identify the content type
|
||
|
$header[] = 'Content-Type: text/plain; charset=UTF-8';
|
||
|
switch($this->getResponseFormat()) {
|
||
|
case self::_RESPONSE_JSON:
|
||
|
$header[] = 'x-li-format: json';
|
||
|
break;
|
||
|
case self::_RESPONSE_JSONP:
|
||
|
$header[] = 'x-li-format: jsonp';
|
||
|
break;
|
||
|
}
|
||
|
} else {
|
||
|
$header[] = 'Content-Type: text/xml; charset=UTF-8';
|
||
|
curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
|
||
|
}
|
||
|
curl_setopt($handle, CURLOPT_HTTPHEADER, $header);
|
||
|
|
||
|
// set the last url, headers
|
||
|
$this->last_request_url = $url;
|
||
|
$this->last_request_headers = $header;
|
||
|
|
||
|
// gather the response
|
||
|
$return_data['linkedin'] = curl_exec($handle);
|
||
|
if( $return_data['linkedin'] === false ) {
|
||
|
Hybrid_Logger::error( "LinkedIn::fetch(). curl_exec error: ", curl_error($handle) );
|
||
|
}
|
||
|
$return_data['info'] = curl_getinfo($handle);
|
||
|
$return_data['oauth']['header'] = $oauth_req->to_header(self::_API_OAUTH_REALM);
|
||
|
$return_data['oauth']['string'] = $oauth_req->base_string;
|
||
|
|
||
|
// check for throttling
|
||
|
if(self::isThrottled($return_data['linkedin'])) {
|
||
|
throw new LinkedInException('LinkedIn->fetch(): throttling limit for this user/application has been reached for LinkedIn resource - ' . $url);
|
||
|
}
|
||
|
|
||
|
//TODO - add check for NO response (http_code = 0) from cURL
|
||
|
|
||
|
// close cURL connection
|
||
|
curl_close($handle);
|
||
|
|
||
|
// no exceptions thrown, return the data
|
||
|
return $return_data;
|
||
|
} catch(OAuthException $e) {
|
||
|
// oauth exception raised
|
||
|
throw new LinkedInException('OAuth exception caught: ' . $e->getMessage());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This flags a specified post as specified by type.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
* @param str $type
|
||
|
* The type to flag the post as.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function flagPost($pid, $type) {
|
||
|
if(!is_string($pid)) {
|
||
|
throw new LinkedInException('LinkedIn->flagPost(): bad data passed, $pid must be of type string');
|
||
|
}
|
||
|
if(!is_string($type)) {
|
||
|
throw new LinkedInException('LinkedIn->flagPost(): bad data passed, $like must be of type string');
|
||
|
}
|
||
|
//Constructing the xml
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>';
|
||
|
switch($type) {
|
||
|
case 'promotion':
|
||
|
$data .= '<code>promotion</code>';
|
||
|
break;
|
||
|
case 'job':
|
||
|
$data .= '<code>job</code>';
|
||
|
break;
|
||
|
default:
|
||
|
throw new LinkedInException('LinkedIn->flagPost(): invalid value for $type, must be one of: "promotion", "job"');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . $pid . '/category/code';
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Follow a company.
|
||
|
*
|
||
|
* Calling this method causes the current user to start following the
|
||
|
* specified company, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1324
|
||
|
*
|
||
|
* @param str $cid
|
||
|
* Company ID you want to follow.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function followCompany($cid) {
|
||
|
// check passed data
|
||
|
if(!is_string($cid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->followCompany(): bad data passed, $cid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/following/companies';
|
||
|
$response = $this->fetch('POST', $query, '<company><id>' . trim($cid) . '</id></company>');
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Follows/Unfollows the specified post.
|
||
|
*
|
||
|
* https://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
* @param bool $follow
|
||
|
* Determines whether to follow or unfollow the post. true = follow, false = unfollow
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
|
||
|
public function followPost($pid, $follow) {
|
||
|
if(!is_string($pid)) {
|
||
|
throw new LinkedInException('LinkedIn->followPost(): bad data passed, $pid must be of type string');
|
||
|
}
|
||
|
if(!($follow === true || $follow === false)) {
|
||
|
throw new LinkedInException('LinkedIn->followPost(): bad data passed, $follow must be of type boolean');
|
||
|
}
|
||
|
|
||
|
// construct the XML
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<is-following>'. (($follow) ? 'true' : 'false'). '</is-following>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . trim($pid) . '/relation-to-viewer/is-following';
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get list of companies you follow.
|
||
|
*
|
||
|
* Returns a list of companies the current user is currently following, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1324
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function followedCompanies() {
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/following/companies';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the application_key property.
|
||
|
*
|
||
|
* @return str
|
||
|
* The application key.
|
||
|
*/
|
||
|
public function getApplicationKey() {
|
||
|
return $this->application_key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the application_secret property.
|
||
|
*
|
||
|
* @return str
|
||
|
* The application secret.
|
||
|
*/
|
||
|
public function getApplicationSecret() {
|
||
|
return $this->application_secret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the callback property.
|
||
|
*
|
||
|
* @return str
|
||
|
* The callback url.
|
||
|
*/
|
||
|
public function getCallbackUrl() {
|
||
|
return $this->callback;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the response_format property.
|
||
|
*
|
||
|
* @return str
|
||
|
* The response format.
|
||
|
*/
|
||
|
public function getResponseFormat() {
|
||
|
return $this->response_format;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Get the token_access property.
|
||
|
*
|
||
|
* @return arr
|
||
|
* The access token.
|
||
|
*/
|
||
|
public function getToken() {
|
||
|
return $this->token;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* [DEPRECATED] Get the token_access property.
|
||
|
*
|
||
|
* @return arr
|
||
|
* The access token.
|
||
|
*/
|
||
|
public function getTokenAccess() {
|
||
|
return $this->getToken();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
*
|
||
|
* Get information about a specific group.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Field selectors for the group.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
|
||
|
public function group($gid, $options = '') {
|
||
|
if(!is_string($gid)){
|
||
|
throw new LinkedInException('LinkedIn->group(): bad data passed, $gid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
throw new LinkedInException('LinkedIn->group(): bad data passed, $options must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/groups/' . trim($gid) . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This returns all the groups the user is a member of.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Field selectors for the groups.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function groupMemberships($options = '') {
|
||
|
if(!is_string($options)) {
|
||
|
throw new LinkedInException('LinkedIn->groupMemberships(): bad data passed, $options must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/group-memberships' . trim($options) . '?membership-state=member';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This gets a specified post made within a group.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Field selectors for the post.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function groupPost($pid, $options = '') {
|
||
|
if(!is_string($pid)) {
|
||
|
throw new LinkedInException('LinkedIn->groupPost(): bad data passed, $pid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
throw new LinkedInException('LinkedIn->groupPost(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . trim($pid) . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This returns all the comments made on the specified post within a group.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Field selectors for the post comments.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function groupPostComments($pid, $options = ''){
|
||
|
if(!is_string($pid)){
|
||
|
throw new LinkedInException('LinkedIn->groupPostComments(): bad data passed, $pid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
throw new LinkedInException('LinkedIn->groupPostComments(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . trim($pid) . '/comments' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This returns all the posts within a group.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function groupPosts($gid, $options = '') {
|
||
|
if(!is_string($gid)){
|
||
|
throw new LinkedInException('LinkedIn->groupPosts(): bad data passed, $gid must be of type string');
|
||
|
}
|
||
|
if(!is_string($options)){
|
||
|
throw new LinkedInException('LinkedIn->groupPosts(): bad data passed, $options must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/groups/' . trim($gid) .'/posts' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This returns the group settings of the specified group
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Field selectors for the group.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function groupSettings($gid, $options = '') {
|
||
|
if(!is_string($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->groupSettings(): bad data passed, $gid must be of type string');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
throw new LinkedInException('LinkedIn->groupSettings(): bad data passed, $options must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/group-memberships/' . trim($gid) . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Send connection invitations.
|
||
|
*
|
||
|
* Send an invitation to connect to your network, either by email address or
|
||
|
* by LinkedIn ID. Details on the API here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1012
|
||
|
*
|
||
|
* @param str $method
|
||
|
* The invitation method to process.
|
||
|
* @param str $recipient
|
||
|
* The email/id to send the invitation to.
|
||
|
* @param str $subject
|
||
|
* The subject of the invitation to send.
|
||
|
* @param str $body
|
||
|
* The body of the invitation to send.
|
||
|
* @param str $type
|
||
|
* [OPTIONAL] The invitation request type (only friend is supported at this time by the Invite API).
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function invite($method, $recipient, $subject, $body, $type = 'friend') {
|
||
|
/**
|
||
|
* Clean up the passed data per these rules:
|
||
|
*
|
||
|
* 1) Message must be sent to one recipient (only a single recipient permitted for the Invitation API)
|
||
|
* 2) No HTML permitted
|
||
|
* 3) 200 characters max in the invitation subject
|
||
|
* 4) Only able to connect as a friend at this point
|
||
|
*/
|
||
|
// check passed data
|
||
|
if(empty($recipient)) {
|
||
|
throw new LinkedInException('LinkedIn->invite(): you must provide an invitation recipient.');
|
||
|
}
|
||
|
switch($method) {
|
||
|
case 'email':
|
||
|
if(is_array($recipient)) {
|
||
|
$recipient = array_map('trim', $recipient);
|
||
|
} else {
|
||
|
// bad format for recipient for email method
|
||
|
throw new LinkedInException('LinkedIn->invite(): invitation recipient email/name array is malformed.');
|
||
|
}
|
||
|
break;
|
||
|
case 'id':
|
||
|
$recipient = trim($recipient);
|
||
|
if(!self::isId($recipient)) {
|
||
|
// bad format for recipient for id method
|
||
|
throw new LinkedInException('LinkedIn->invite(): invitation recipient ID does not match LinkedIn format.');
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
throw new LinkedInException('LinkedIn->invite(): bad invitation method, must be one of: email, id.');
|
||
|
break;
|
||
|
}
|
||
|
if(!empty($subject)) {
|
||
|
$subject = trim(htmlspecialchars(strip_tags(stripslashes($subject))));
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->invite(): message subject is empty.');
|
||
|
}
|
||
|
if(!empty($body)) {
|
||
|
$body = trim(htmlspecialchars(strip_tags(stripslashes($body))));
|
||
|
if(strlen($body) > self::_INV_BODY_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->invite(): message body length is too long - max length is ' . self::_INV_BODY_LENGTH . ' characters.');
|
||
|
}
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->invite(): message body is empty.');
|
||
|
}
|
||
|
switch($type) {
|
||
|
case 'friend':
|
||
|
break;
|
||
|
default:
|
||
|
throw new LinkedInException('LinkedIn->invite(): bad invitation type, must be one of: friend.');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// construct the xml data
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<mailbox-item>
|
||
|
<recipients>
|
||
|
<recipient>';
|
||
|
switch($method) {
|
||
|
case 'email':
|
||
|
// email-based invitation
|
||
|
$data .= '<person path="/people/email=' . $recipient['email'] . '">
|
||
|
<first-name>' . htmlspecialchars($recipient['first-name']) . '</first-name>
|
||
|
<last-name>' . htmlspecialchars($recipient['last-name']) . '</last-name>
|
||
|
</person>';
|
||
|
break;
|
||
|
case 'id':
|
||
|
// id-based invitation
|
||
|
$data .= '<person path="/people/id=' . $recipient . '"/>';
|
||
|
break;
|
||
|
}
|
||
|
$data .= ' </recipient>
|
||
|
</recipients>
|
||
|
<subject>' . $subject . '</subject>
|
||
|
<body>' . $body . '</body>
|
||
|
<item-content>
|
||
|
<invitation-request>
|
||
|
<connect-type>';
|
||
|
switch($type) {
|
||
|
case 'friend':
|
||
|
$data .= 'friend';
|
||
|
break;
|
||
|
}
|
||
|
$data .= ' </connect-type>';
|
||
|
switch($method) {
|
||
|
case 'id':
|
||
|
// id-based invitation, we need to get the authorization information
|
||
|
$query = 'id=' . $recipient . ':(api-standard-profile-request)';
|
||
|
$response = self::profile($query);
|
||
|
if($response['info']['http_code'] == 200) {
|
||
|
$response['linkedin'] = self::xmlToarray($response['linkedin']);
|
||
|
if($response['linkedin'] === false) {
|
||
|
// bad XML data
|
||
|
throw new LinkedInException('LinkedIn->invite(): LinkedIn returned bad XML data.');
|
||
|
}
|
||
|
$authentication = explode(':', $response['linkedin']['person']['children']['api-standard-profile-request']['children']['headers']['children']['http-header']['children']['value']['content']);
|
||
|
|
||
|
// complete the xml
|
||
|
$data .= '<authorization>
|
||
|
<name>' . $authentication[0] . '</name>
|
||
|
<value>' . $authentication[1] . '</value>
|
||
|
</authorization>';
|
||
|
} else {
|
||
|
// bad response from the profile request, not a valid ID?
|
||
|
throw new LinkedInException('LinkedIn->invite(): could not send invitation, LinkedIn says: ' . print_r($response['linkedin'], true));
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
$data .= ' </invitation-request>
|
||
|
</item-content>
|
||
|
</mailbox-item>';
|
||
|
|
||
|
// send request
|
||
|
$query = self::_URL_API . '/v1/people/~/mailbox';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* LinkedIn ID validation.
|
||
|
*
|
||
|
* Checks the passed string $id to see if it has a valid LinkedIn ID format,
|
||
|
* which is, as of October 15th, 2010:
|
||
|
*
|
||
|
* 10 alpha-numeric mixed-case characters, plus underscores and dashes.
|
||
|
*
|
||
|
* @param str $id
|
||
|
* A possible LinkedIn ID.
|
||
|
*
|
||
|
* @return bool
|
||
|
* true/false depending on valid ID format determination.
|
||
|
*/
|
||
|
public static function isId($id) {
|
||
|
// check passed data
|
||
|
if(!is_string($id)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->isId(): bad data passed, $id must be of type string.');
|
||
|
}
|
||
|
|
||
|
$pattern = '/^[a-z0-9_\-]{10}$/i';
|
||
|
if($match = preg_match($pattern, $id)) {
|
||
|
// we have a match
|
||
|
$return_data = true;
|
||
|
} else {
|
||
|
// no match
|
||
|
$return_data = false;
|
||
|
}
|
||
|
return $return_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Throttling check.
|
||
|
*
|
||
|
* Checks the passed LinkedIn response to see if we have hit a throttling
|
||
|
* limit:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1112
|
||
|
*
|
||
|
* @param arr $response
|
||
|
* The LinkedIn response.
|
||
|
*
|
||
|
* @return bool
|
||
|
* true/false depending on content of response.
|
||
|
*/
|
||
|
public static function isThrottled($response) {
|
||
|
$return_data = false;
|
||
|
|
||
|
// check the variable
|
||
|
if(!empty($response) && is_string($response)) {
|
||
|
// we have an array and have a properly formatted LinkedIn response
|
||
|
|
||
|
// store the response in a temp variable
|
||
|
$temp_response = self::xmlToarray($response);
|
||
|
if($temp_response !== false) {
|
||
|
// check to see if we have an error
|
||
|
if(array_key_exists('error', $temp_response) && ($temp_response['error']['children']['status']['content'] == 403) && preg_match('/throttle/i', $temp_response['error']['children']['message']['content'])) {
|
||
|
// we have an error, it is 403 and we have hit a throttle limit
|
||
|
$return_data = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return $return_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Job posting detail info retrieval function.
|
||
|
*
|
||
|
* The Jobs API returns detailed information about job postings on LinkedIn.
|
||
|
* Find the job summary, description, location, and apply our professional graph
|
||
|
* to present the relationship between the current member and the job poster or
|
||
|
* hiring manager.
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1322
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* ID of the job you want to look up.
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function job($jid, $options = '') {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->job(): bad data passed, $jid must be of type string.');
|
||
|
}
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->job(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/jobs/' . trim($jid) . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Join the specified group, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function joinGroup($gid) {
|
||
|
if(!is_string($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->joinGroup(): bad data passed, $gid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// constructing the XML
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<group-membership>
|
||
|
<membership-state>
|
||
|
<code>member</code>
|
||
|
</membership-state>
|
||
|
</group-membership>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/group-memberships/' . trim($gid);
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 or 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(array(200, 201), $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the last request header from the previous call to the
|
||
|
* LinkedIn API.
|
||
|
*
|
||
|
* @returns str
|
||
|
* The header, in string format.
|
||
|
*/
|
||
|
public function lastRequestHeader() {
|
||
|
return $this->last_request_headers;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the last request url from the previous call to the
|
||
|
* LinkedIn API.
|
||
|
*
|
||
|
* @returns str
|
||
|
* The url, in string format.
|
||
|
*/
|
||
|
public function lastRequestUrl() {
|
||
|
return $this->last_request_url;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Leave the specified group, per:.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function leaveGroup($gid){
|
||
|
if(!is_string($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->leaveGroup(): bad data passed, $gid must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/group-memberships/' .trim($gid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Like another user's network update, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $uid
|
||
|
* The LinkedIn update ID.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function like($uid) {
|
||
|
// check passed data
|
||
|
if(!is_string($uid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->like(): bad data passed, $uid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct the XML
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<is-liked>true</is-liked>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates/key=' . $uid . '/is-liked';
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Likes/unlikes the specified post, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $pid
|
||
|
* The post id.
|
||
|
* @param bool $like
|
||
|
* Determines whether to like or unlike. true = like, false = unlike.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function likePost($pid, $like) {
|
||
|
if(!is_string($pid)) {
|
||
|
throw new LinkedInException ('LinkedIn->likePost(): bad data passed, $pid must be of type string');
|
||
|
}
|
||
|
if(!($like === true || $like === false)) {
|
||
|
throw new LinkedInException('LinkedIn->likePost(): bad data passed, $like must be of type boolean');
|
||
|
}
|
||
|
|
||
|
// construct the XML
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<is-liked>'.(($like) ? 'true': 'false').'</is-liked>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/posts/' . trim($pid) . '/relation-to-viewer/is-liked';
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieve network update likes.
|
||
|
*
|
||
|
* Return all likes associated with a given network update:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $uid
|
||
|
* The LinkedIn update ID.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function likes($uid) {
|
||
|
// check passed data
|
||
|
if(!is_string($uid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->likes(): bad data passed, $uid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates/key=' . $uid . '/likes';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Connection messaging method.
|
||
|
*
|
||
|
* Send a message to your network connection(s), optionally copying yourself.
|
||
|
* Full details from LinkedIn on this functionality can be found here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1044
|
||
|
*
|
||
|
* @param arr $recipients
|
||
|
* The connection(s) to send the message to.
|
||
|
* @param str $subject
|
||
|
* The subject of the message to send.
|
||
|
* @param str $body
|
||
|
* The body of the message to send.
|
||
|
* @param bool $copy_self
|
||
|
* [OPTIONAL] Also update the teathered Twitter account.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function message($recipients, $subject, $body, $copy_self = false) {
|
||
|
/**
|
||
|
* Clean up the passed data per these rules:
|
||
|
*
|
||
|
* 1) Message must be sent to at least one recipient
|
||
|
* 2) No HTML permitted
|
||
|
*/
|
||
|
if(!empty($subject) && is_string($subject)) {
|
||
|
$subject = trim(strip_tags(stripslashes($subject)));
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->message(): bad data passed, $subject must be of type string.');
|
||
|
}
|
||
|
if(!empty($body) && is_string($body)) {
|
||
|
$body = trim(strip_tags(stripslashes($body)));
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->message(): bad data passed, $body must be of type string.');
|
||
|
}
|
||
|
if(!is_array($recipients) || count($recipients) < 1) {
|
||
|
// no recipients, and/or bad data
|
||
|
throw new LinkedInException('LinkedIn->message(): at least one message recipient required.');
|
||
|
}
|
||
|
|
||
|
// construct the xml data
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<mailbox-item>
|
||
|
<recipients>';
|
||
|
$data .= ($copy_self) ? '<recipient><person path="/people/~"/></recipient>' : '';
|
||
|
for($i = 0; $i < count($recipients); $i++) {
|
||
|
if(is_string($recipients[$i])) {
|
||
|
$data .= '<recipient><person path="/people/' . trim($recipients[$i]) . '"/></recipient>';
|
||
|
} else {
|
||
|
throw new LinkedInException ('LinkedIn->message(): bad data passed, $recipients must be an array of type string.');
|
||
|
}
|
||
|
}
|
||
|
$data .= ' </recipients>
|
||
|
<subject>' . htmlspecialchars($subject) . '</subject>
|
||
|
<body>' . htmlspecialchars($body) . '</body>
|
||
|
</mailbox-item>';
|
||
|
|
||
|
// send request
|
||
|
$query = self::_URL_API . '/v1/people/~/mailbox';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Job posting method.
|
||
|
*
|
||
|
* Post a job to LinkedIn, assuming that you have access to this feature.
|
||
|
* Full details from LinkedIn on this functionality can be found here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/community/jobs?view=documents
|
||
|
*
|
||
|
* @param str $xml
|
||
|
* The XML defining a job to post.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function postJob($xml) {
|
||
|
// check passed data
|
||
|
if(is_string($xml)) {
|
||
|
$xml = trim(stripslashes($xml));
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->postJob(): bad data passed, $xml must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/jobs';
|
||
|
$response = $this->fetch('POST', $query, $xml);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* General profile retrieval function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests profile data from the
|
||
|
* Linkedin Profile API. See the official documentation for $options
|
||
|
* 'field selector' formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1014
|
||
|
* http://developer.linkedin.com/docs/DOC-1002
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function profile($options = '~') {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->profile(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Send a message
|
||
|
*
|
||
|
* Send a message to another member or members
|
||
|
*
|
||
|
* @author @timersys
|
||
|
*
|
||
|
* @param array $recipients
|
||
|
* The id or ids to send the message to.
|
||
|
* @param str $subject
|
||
|
* The subject of the invitation to send.
|
||
|
* @param str $body
|
||
|
* The body of the invitation to send.
|
||
|
*
|
||
|
* @return arr array
|
||
|
* Containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function send_msg($recipients, $subject, $body) {
|
||
|
/**
|
||
|
* Clean up the passed data per these rules:
|
||
|
*
|
||
|
* 1) No HTML permitted
|
||
|
* 2) 200 characters max in the invitation subject
|
||
|
* 3) Only able to connect as a friend at this point
|
||
|
*/
|
||
|
|
||
|
// check passed data
|
||
|
if(empty($recipients)) {
|
||
|
throw new LinkedInException('LinkedIn->send_msg(): you must provide an invitation recipient.');
|
||
|
}
|
||
|
if(!empty($subject)) {
|
||
|
$subject = trim(htmlspecialchars(strip_tags(stripslashes($subject))));
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->send_msg(): message subject is empty.');
|
||
|
}
|
||
|
if(!empty($body)) {
|
||
|
$body = trim(htmlspecialchars(strip_tags(stripslashes($body))));
|
||
|
|
||
|
if(strlen($body) > self::_INV_BODY_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->send_msg(): message body length is too long - max length is ' . self::_INV_BODY_LENGTH . ' characters.');
|
||
|
}
|
||
|
} else {
|
||
|
throw new LinkedInException('LinkedIn->send_msg(): message body is empty.');
|
||
|
}
|
||
|
|
||
|
// construct the xml data
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<mailbox-item>
|
||
|
<recipients>';
|
||
|
|
||
|
foreach( $recipients as $recipient )
|
||
|
{
|
||
|
$data .= '<recipient>';
|
||
|
$data .= '<person path="/people/'. $recipient . '"/>';
|
||
|
$data .= '</recipient>';
|
||
|
}
|
||
|
$data .= ' </recipients>
|
||
|
<subject>' . $subject . '</subject>
|
||
|
<body>' . $body . '</body>
|
||
|
</mailbox-item>';
|
||
|
// send request
|
||
|
$query = self::_URL_API . '/v1/people/~/mailbox';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Manual API call method, allowing for support for un-implemented API
|
||
|
* functionality to be supported.
|
||
|
*
|
||
|
* @param str $method
|
||
|
* The data communication method.
|
||
|
* @param str $url
|
||
|
* The Linkedin API endpoint to connect with - should NOT include the
|
||
|
* leading https://api.linkedin.com/v1.
|
||
|
* @param str $body
|
||
|
* [OPTIONAL] The URL-encoded body data to send to LinkedIn with the request.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval information, LinkedIn response. Note that you
|
||
|
* must manually check the return code and compare this to the expected
|
||
|
* API response to determine if the raw call was successful.
|
||
|
*/
|
||
|
public function raw($method, $url, $body = null) {
|
||
|
if(!is_string($method)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->raw(): bad data passed, $method must be of string value.');
|
||
|
}
|
||
|
if(!is_string($url)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->raw(): bad data passed, $url must be of string value.');
|
||
|
}
|
||
|
if(!is_null($body) && !is_string($url)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->raw(): bad data passed, $body must be of string value.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1' . trim($url);
|
||
|
return $this->fetch($method, $query, $body);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This removes the specified group from the group suggestions, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function removeSuggestedGroup($gid) {
|
||
|
if(!is_string($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->removeSuggestedGroup(): bad data passed, $gid must be of type string');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/suggestions/groups/' .trim($gid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Renew a job.
|
||
|
*
|
||
|
* Calling this method causes the passed job to be renewed, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1154
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* Job ID you want to renew.
|
||
|
* @param str $cid
|
||
|
* Contract ID that covers the passed Job ID.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function renewJob($jid, $cid) {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->renewJob(): bad data passed, $jid must be of string value.');
|
||
|
}
|
||
|
if(!is_string($cid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->renewJob(): bad data passed, $cid must be of string value.');
|
||
|
}
|
||
|
|
||
|
// construct the xml data
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<job>
|
||
|
<contract-id>' . trim($cid) . '</contract-id>
|
||
|
<renewal/>
|
||
|
</job>';
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/jobs/partner-job-id=' . trim($jid);
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Access token retrieval.
|
||
|
*
|
||
|
* Request the user's access token from the Linkedin API.
|
||
|
*
|
||
|
* @param str $token
|
||
|
* The token returned from the user authorization stage.
|
||
|
* @param str $secret
|
||
|
* The secret returned from the request token stage.
|
||
|
* @param str $verifier
|
||
|
* The verification value from LinkedIn.
|
||
|
*
|
||
|
* @return arr
|
||
|
* The Linkedin OAuth/http response, in array format.
|
||
|
*/
|
||
|
public function retrieveTokenAccess($token, $secret, $verifier) {
|
||
|
// check passed data
|
||
|
if(!is_string($token) || !is_string($secret) || !is_string($verifier)) {
|
||
|
// nothing passed, raise an exception
|
||
|
throw new LinkedInException('LinkedIn->retrieveTokenAccess(): bad data passed, string type is required for $token, $secret and $verifier.');
|
||
|
}
|
||
|
|
||
|
// start retrieval process
|
||
|
$this->setToken(array('oauth_token' => $token, 'oauth_token_secret' => $secret));
|
||
|
$parameters = array(
|
||
|
'oauth_verifier' => $verifier
|
||
|
);
|
||
|
$response = $this->fetch(self::_METHOD_TOKENS, self::_URL_ACCESS, null, $parameters);
|
||
|
parse_str($response['linkedin'], $response['linkedin']);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
if($response['info']['http_code'] == 200) {
|
||
|
// tokens retrieved
|
||
|
$this->setToken($response['linkedin']);
|
||
|
|
||
|
// set the response
|
||
|
$return_data = $response;
|
||
|
$return_data['success'] = true;
|
||
|
} else {
|
||
|
// error getting the request tokens
|
||
|
$this->setToken(null);
|
||
|
|
||
|
// set the response
|
||
|
$return_data = $response;
|
||
|
$return_data['error'] = 'HTTP response from LinkedIn end-point was not code 200';
|
||
|
$return_data['success'] = false;
|
||
|
}
|
||
|
return $return_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Request token retrieval.
|
||
|
*
|
||
|
* Get the request token from the Linkedin API.
|
||
|
*
|
||
|
* @return arr
|
||
|
* The Linkedin OAuth/http response, in array format.
|
||
|
*/
|
||
|
public function retrieveTokenRequest() {
|
||
|
$parameters = array(
|
||
|
'oauth_callback' => $this->getCallbackUrl()
|
||
|
);
|
||
|
$response = $this->fetch(self::_METHOD_TOKENS, self::_URL_REQUEST, null, $parameters);
|
||
|
parse_str($response['linkedin'], $response['linkedin']);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
if(($response['info']['http_code'] == 200) && (array_key_exists('oauth_callback_confirmed', $response['linkedin'])) && ($response['linkedin']['oauth_callback_confirmed'] == 'true')) {
|
||
|
// tokens retrieved
|
||
|
$this->setToken($response['linkedin']);
|
||
|
|
||
|
// set the response
|
||
|
$return_data = $response;
|
||
|
$return_data['success'] = true;
|
||
|
} else {
|
||
|
// error getting the request tokens
|
||
|
$this->setToken(null);
|
||
|
|
||
|
// set the response
|
||
|
$return_data = $response;
|
||
|
if((array_key_exists('oauth_callback_confirmed', $response['linkedin'])) && ($response['linkedin']['oauth_callback_confirmed'] == 'true')) {
|
||
|
$return_data['error'] = 'HTTP response from LinkedIn end-point was not code 200';
|
||
|
} else {
|
||
|
$return_data['error'] = 'OAuth callback URL was not confirmed by the LinkedIn end-point';
|
||
|
}
|
||
|
$return_data['success'] = false;
|
||
|
}
|
||
|
return $return_data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* User authorization revocation.
|
||
|
*
|
||
|
* Revoke the current user's access token, clear the access token's from
|
||
|
* current LinkedIn object. The current documentation for this feature is
|
||
|
* found in a blog entry from April 29th, 2010:
|
||
|
*
|
||
|
* http://developer.linkedin.com/community/apis/blog/2010/04/29/oauth--now-for-authentication
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function revoke() {
|
||
|
// construct and send the request
|
||
|
$response = $this->fetch('GET', self::_URL_REVOKE);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* [DEPRECATED] General people search function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests profile data from the
|
||
|
* Linkedin People Search API. See the official documentation for $options
|
||
|
* querystring formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1191
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function search($options = null) {
|
||
|
return searchPeople($options);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Company search.
|
||
|
*
|
||
|
* Uses the Company Search API to find companies using keywords, industry,
|
||
|
* location, or some other criteria. It returns a collection of matching
|
||
|
* companies.
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1325
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Search options.
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function searchCompanies($options = '') {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->searchCompanies(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/company-search' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Jobs search.
|
||
|
*
|
||
|
* Use the Job Search API to find jobs using keywords, company, location,
|
||
|
* or some other criteria. It returns a collection of matching jobs. Each
|
||
|
* entry can contain much of the information available on the job listing.
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1321
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function searchJobs($options = '') {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->jobsSearch(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/job-search' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* General people search function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests profile data from the
|
||
|
* Linkedin People Search API. See the official documentation for $options
|
||
|
* querystring formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1191
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function searchPeople($options = null) {
|
||
|
// check passed data
|
||
|
if(!is_null($options) && !is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->search(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people-search' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the application_key property.
|
||
|
*
|
||
|
* @param str $key
|
||
|
* The application key.
|
||
|
*/
|
||
|
public function setApplicationKey($key) {
|
||
|
$this->application_key = $key;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the application_secret property.
|
||
|
*
|
||
|
* @param str $secret
|
||
|
* The application secret.
|
||
|
*/
|
||
|
public function setApplicationSecret($secret) {
|
||
|
$this->application_secret = $secret;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the callback property.
|
||
|
*
|
||
|
* @param str $url
|
||
|
* The callback url.
|
||
|
*/
|
||
|
public function setCallbackUrl($url) {
|
||
|
$this->callback = $url;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This sets the group settings of the specified group.
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @param str $gid
|
||
|
* The group id.
|
||
|
* @param str $xml
|
||
|
* The group settings to set. The settings are:
|
||
|
* -<show-group-logo-in-profile>
|
||
|
* -<contact-email>
|
||
|
* -<email-digest-frequency>
|
||
|
* -<email-announcements-from-managers>
|
||
|
* -<allow-messages-from-members>
|
||
|
* -<email-for-every-new-post>
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function setGroupSettings($gid, $xml) {
|
||
|
if(!is_string ($gid)) {
|
||
|
throw new LinkedInException('LinkedIn->setGroupSettings(): bad data passed, $token_access should be in array format.');
|
||
|
}
|
||
|
if(!is_string ($xml)) {
|
||
|
throw new LinkedInException('LinkedIn->setGroupSettings(): bad data passed, $token_access should be in array format.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/group-memberships/' . trim($gid);
|
||
|
$response = $this->fetch('PUT', $query, $xml);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the response_format property.
|
||
|
*
|
||
|
* @param str $format
|
||
|
* [OPTIONAL] The response format to specify to LinkedIn.
|
||
|
*/
|
||
|
public function setResponseFormat($format = self::_DEFAULT_RESPONSE_FORMAT) {
|
||
|
$this->response_format = $format;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the token property.
|
||
|
*
|
||
|
* @return arr $token
|
||
|
* The LinkedIn OAuth token.
|
||
|
*/
|
||
|
public function setToken($token) {
|
||
|
// check passed data
|
||
|
if(!is_null($token) && !is_array($token)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->setToken(): bad data passed, $token_access should be in array format.');
|
||
|
}
|
||
|
|
||
|
// set token
|
||
|
$this->token = $token;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* [DEPRECATED] Set the token_access property.
|
||
|
*
|
||
|
* @return arr $token_access
|
||
|
* [OPTIONAL] The LinkedIn OAuth access token.
|
||
|
*/
|
||
|
public function setTokenAccess($token_access) {
|
||
|
$this->setToken($token_access);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Post a share.
|
||
|
*
|
||
|
* Create a new or reshare another user's shared content. Full details from
|
||
|
* LinkedIn on this functionality can be found here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1212
|
||
|
*
|
||
|
* $action values: ('new', 'reshare')
|
||
|
* $content format:
|
||
|
* $action = 'new'; $content => ('comment' => 'xxx', 'title' => 'xxx', 'submitted-url' => 'xxx', 'submitted-image-url' => 'xxx', 'description' => 'xxx')
|
||
|
* $action = 'reshare'; $content => ('comment' => 'xxx', 'id' => 'xxx')
|
||
|
*
|
||
|
* @param str $action
|
||
|
* The sharing action to perform.
|
||
|
* @param str $content
|
||
|
* The share content.
|
||
|
* @param bool $private
|
||
|
* [OPTIONAL] Should we restrict this shared item to connections only?
|
||
|
* @param bool $twitter
|
||
|
* [OPTIONAL] Also update the teathered Twitter account.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function share($action, $content, $private = true, $twitter = false) {
|
||
|
// check the status itself
|
||
|
if(!empty($action) && !empty($content)) {
|
||
|
/**
|
||
|
* Status is not empty, wrap a cleaned version of it in xml. Status
|
||
|
* rules:
|
||
|
*
|
||
|
* 1) Comments are 700 chars max (if this changes, change _SHARE_COMMENT_LENGTH constant)
|
||
|
* 2) Content/title 200 chars max (if this changes, change _SHARE_CONTENT_TITLE_LENGTH constant)
|
||
|
* 3) Content/description 400 chars max (if this changes, change _SHARE_CONTENT_DESC_LENGTH constant)
|
||
|
* 4a) New shares must contain a comment and/or (content/title and content/submitted-url)
|
||
|
* 4b) Reshared content must contain an attribution id.
|
||
|
* 4c) Reshared content must contain actual content, not just a comment.
|
||
|
* 5) No HTML permitted in comment, content/title, content/description.
|
||
|
*/
|
||
|
|
||
|
// prepare the share data per the rules above
|
||
|
$share_flag = false;
|
||
|
$content_xml = null;
|
||
|
switch($action) {
|
||
|
case 'new':
|
||
|
// share can be an article
|
||
|
if(array_key_exists('title', $content) && array_key_exists('submitted-url', $content)) {
|
||
|
// we have shared content, format it as needed per rules above
|
||
|
$content_title = trim(htmlspecialchars(strip_tags(stripslashes($content['title']))));
|
||
|
if(strlen($content_title) > self::_SHARE_CONTENT_TITLE_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->share(): title length is too long - max length is ' . self::_SHARE_CONTENT_TITLE_LENGTH . ' characters.');
|
||
|
}
|
||
|
$content_xml .= '<content>
|
||
|
<title>' . $content_title . '</title>
|
||
|
<submitted-url>' . trim(htmlspecialchars($content['submitted-url'])) . '</submitted-url>';
|
||
|
if(array_key_exists('submitted-image-url', $content)) {
|
||
|
$content_xml .= '<submitted-image-url>' . trim(htmlspecialchars($content['submitted-image-url'])) . '</submitted-image-url>';
|
||
|
}
|
||
|
if(array_key_exists('description', $content)) {
|
||
|
$content_desc = trim(htmlspecialchars(strip_tags(stripslashes($content['description']))));
|
||
|
if(strlen($content_desc) > self::_SHARE_CONTENT_DESC_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->share(): description length is too long - max length is ' . self::_SHARE_CONTENT_DESC_LENGTH . ' characters.');
|
||
|
}
|
||
|
$content_xml .= '<description>' . $content_desc . '</description>';
|
||
|
}
|
||
|
$content_xml .= '</content>';
|
||
|
|
||
|
$share_flag = true;
|
||
|
}
|
||
|
|
||
|
// share can be just a comment
|
||
|
if(array_key_exists('comment', $content)) {
|
||
|
// comment located
|
||
|
$comment = htmlspecialchars(trim(strip_tags(stripslashes($content['comment']))));
|
||
|
if(strlen($comment) > self::_SHARE_COMMENT_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->share(): comment length is too long - max length is ' . self::_SHARE_COMMENT_LENGTH . ' characters.');
|
||
|
}
|
||
|
$content_xml .= '<comment>' . $comment . '</comment>';
|
||
|
|
||
|
$share_flag = true;
|
||
|
}
|
||
|
break;
|
||
|
case 'reshare':
|
||
|
if(array_key_exists('id', $content)) {
|
||
|
// put together the re-share attribution XML
|
||
|
$content_xml .= '<attribution>
|
||
|
<share>
|
||
|
<id>' . trim($content['id']) . '</id>
|
||
|
</share>
|
||
|
</attribution>';
|
||
|
|
||
|
// optional additional comment
|
||
|
if(array_key_exists('comment', $content)) {
|
||
|
// comment located
|
||
|
$comment = htmlspecialchars(trim(strip_tags(stripslashes($content['comment']))));
|
||
|
if(strlen($comment) > self::_SHARE_COMMENT_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->share(): comment length is too long - max length is ' . self::_SHARE_COMMENT_LENGTH . ' characters.');
|
||
|
}
|
||
|
$content_xml .= '<comment>' . $comment . '</comment>';
|
||
|
}
|
||
|
|
||
|
$share_flag = true;
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
// bad action passed
|
||
|
throw new LinkedInException('LinkedIn->share(): share action is an invalid value, must be one of: share, reshare.');
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// should we proceed?
|
||
|
if($share_flag) {
|
||
|
// put all of the xml together
|
||
|
$visibility = ($private) ? 'connections-only' : 'anyone';
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<share>
|
||
|
' . $content_xml . '
|
||
|
<visibility>
|
||
|
<code>' . $visibility . '</code>
|
||
|
</visibility>
|
||
|
</share>';
|
||
|
|
||
|
// create the proper url
|
||
|
$share_url = self::_URL_API . '/v1/people/~/shares';
|
||
|
if($twitter) {
|
||
|
// update twitter as well
|
||
|
$share_url .= '?twitter-post=true';
|
||
|
}
|
||
|
|
||
|
// send request
|
||
|
$response = $this->fetch('POST', $share_url, $data);
|
||
|
} else {
|
||
|
// data constraints/rules not met, raise an exception
|
||
|
throw new LinkedInException('LinkedIn->share(): sharing data constraints not met; check that you have supplied valid content and combinations of content to share.');
|
||
|
}
|
||
|
} else {
|
||
|
// data missing, raise an exception
|
||
|
throw new LinkedInException('LinkedIn->share(): sharing action or shared content is missing.');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Network statistics.
|
||
|
*
|
||
|
* General network statistics retrieval function, returns the number of connections,
|
||
|
* second-connections an authenticated user has. More information here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1006
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function statistics() {
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/network-stats';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Companies you may want to follow.
|
||
|
*
|
||
|
* Returns a list of companies the current user may want to follow, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1324
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function suggestedCompanies() {
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/suggestions/to-follow/companies';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Retrieves suggested groups for the user, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/documents/groups-api
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function suggestedGroups() {
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/suggestions/groups:(id,name,is-open-to-non-members)';
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse (200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Jobs you may be interested in.
|
||
|
*
|
||
|
* Returns a list of jobs the current user may be interested in, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1323
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function suggestedJobs($options = ':(jobs)') {
|
||
|
// check passed data
|
||
|
if(!is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->suggestedJobs(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/suggestions/job-suggestions' . trim($options);
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unbookmark a job.
|
||
|
*
|
||
|
* Calling this method causes the current user to remove a bookmark for the
|
||
|
* specified job:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1323
|
||
|
*
|
||
|
* @param str $jid
|
||
|
* Job ID you want to unbookmark.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function unbookmarkJob($jid) {
|
||
|
// check passed data
|
||
|
if(!is_string($jid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->unbookmarkJob(): bad data passed, $jid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/job-bookmarks/' . trim($jid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unfollow a company.
|
||
|
*
|
||
|
* Calling this method causes the current user to stop following the specified
|
||
|
* company, per:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1324
|
||
|
*
|
||
|
* @param str $cid
|
||
|
* Company ID you want to unfollow.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function unfollowCompany($cid) {
|
||
|
// check passed data
|
||
|
if(!is_string($cid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->unfollowCompany(): bad data passed, $cid must be of string value.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
$query = self::_URL_API . '/v1/people/~/following/companies/id=' . trim($cid);
|
||
|
$response = $this->fetch('DELETE', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 204 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(204, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Unlike a network update.
|
||
|
*
|
||
|
* Unlike another user's network update:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $uid
|
||
|
* The LinkedIn update ID.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function unlike($uid) {
|
||
|
// check passed data
|
||
|
if(!is_string($uid)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->unlike(): bad data passed, $uid must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct the xml data
|
||
|
$data = '<?xml version="1.0" encoding="UTF-8"?>
|
||
|
<is-liked>false</is-liked>';
|
||
|
|
||
|
// send request
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates/key=' . $uid . '/is-liked';
|
||
|
$response = $this->fetch('PUT', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Post network update.
|
||
|
*
|
||
|
* Update the user's Linkedin network status. Full details from LinkedIn
|
||
|
* on this functionality can be found here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1009
|
||
|
* http://developer.linkedin.com/docs/DOC-1009#comment-1077
|
||
|
*
|
||
|
* @param str $update
|
||
|
* The network update.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function updateNetwork($update) {
|
||
|
// check passed data
|
||
|
if(!is_string($update)) {
|
||
|
// nothing/non-string passed, raise an exception
|
||
|
throw new LinkedInException('LinkedIn->updateNetwork(): bad data passed, $update must be a non-zero length string.');
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Network update is not empty, wrap a cleaned version of it in xml.
|
||
|
* Network update rules:
|
||
|
*
|
||
|
* 1) No HTML permitted except those found in _NETWORK_HTML constant
|
||
|
* 2) Update cannot be longer than 140 characters.
|
||
|
*/
|
||
|
// get the user data
|
||
|
$response = self::profile('~:(first-name,last-name,site-standard-profile-request)');
|
||
|
if($response['success'] === true) {
|
||
|
/**
|
||
|
* We are converting response to usable data. I'd use SimpleXML here, but
|
||
|
* to keep the class self-contained, we will use a portable XML parsing
|
||
|
* routine, self::xmlToarray.
|
||
|
*/
|
||
|
$person = self::xmlToarray($response['linkedin']);
|
||
|
if($person === false) {
|
||
|
// bad xml data
|
||
|
throw new LinkedInException('LinkedIn->updateNetwork(): LinkedIn returned bad XML data.');
|
||
|
}
|
||
|
$fields = $person['person']['children'];
|
||
|
|
||
|
// prepare user data
|
||
|
$first_name = trim($fields['first-name']['content']);
|
||
|
$last_name = trim($fields['last-name']['content']);
|
||
|
$profile_url = trim($fields['site-standard-profile-request']['children']['url']['content']);
|
||
|
|
||
|
// create the network update
|
||
|
$update = trim(htmlspecialchars(strip_tags($update, self::_NETWORK_HTML)));
|
||
|
if(strlen($update) > self::_NETWORK_LENGTH) {
|
||
|
throw new LinkedInException('LinkedIn->share(): update length is too long - max length is ' . self::_NETWORK_LENGTH . ' characters.');
|
||
|
}
|
||
|
$user = htmlspecialchars('<a href="' . $profile_url . '">' . $first_name . ' ' . $last_name . '</a>');
|
||
|
$data = '<activity locale="en_US">
|
||
|
<content-type>linkedin-html</content-type>
|
||
|
<body>' . $user . ' ' . $update . '</body>
|
||
|
</activity>';
|
||
|
|
||
|
// send request
|
||
|
$query = self::_URL_API . '/v1/people/~/person-activities';
|
||
|
$response = $this->fetch('POST', $query, $data);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 201 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(201, $response);
|
||
|
} else {
|
||
|
// profile retrieval failed
|
||
|
throw new LinkedInException('LinkedIn->updateNetwork(): profile data could not be retrieved.');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* General network update retrieval function.
|
||
|
*
|
||
|
* Takes a string of parameters as input and requests update-related data
|
||
|
* from the Linkedin Network Updates API. See the official documentation for
|
||
|
* $options parameter formatting:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1006
|
||
|
*
|
||
|
* For getting more comments, likes, etc, see here:
|
||
|
*
|
||
|
* http://developer.linkedin.com/docs/DOC-1043
|
||
|
*
|
||
|
* @param str $options
|
||
|
* [OPTIONAL] Data retrieval options.
|
||
|
* @param str $id
|
||
|
* [OPTIONAL] The LinkedIn ID to restrict the updates for.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing retrieval success, LinkedIn response.
|
||
|
*/
|
||
|
public function updates($options = null, $id = null) {
|
||
|
// check passed data
|
||
|
if(!is_null($options) && !is_string($options)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->updates(): bad data passed, $options must be of type string.');
|
||
|
}
|
||
|
if(!is_null($id) && !is_string($id)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->updates(): bad data passed, $id must be of type string.');
|
||
|
}
|
||
|
|
||
|
// construct and send the request
|
||
|
if(!is_null($id) && self::isId($id)) {
|
||
|
$query = self::_URL_API . '/v1/people/' . $id . '/network/updates' . trim($options);
|
||
|
} else {
|
||
|
$query = self::_URL_API . '/v1/people/~/network/updates' . trim($options);
|
||
|
}
|
||
|
$response = $this->fetch('GET', $query);
|
||
|
|
||
|
/**
|
||
|
* Check for successful request (a 200 response from LinkedIn server)
|
||
|
* per the documentation linked in method comments above.
|
||
|
*/
|
||
|
return $this->checkResponse(200, $response);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Converts passed XML data to an array.
|
||
|
*
|
||
|
* @param str $xml
|
||
|
* The XML to convert to an array.
|
||
|
*
|
||
|
* @return arr
|
||
|
* array containing the XML data.
|
||
|
* @return bool
|
||
|
* false if passed data cannot be parsed to an array.
|
||
|
*/
|
||
|
public static function xmlToarray($xml) {
|
||
|
// check passed data
|
||
|
if(!is_string($xml)) {
|
||
|
// bad data passed
|
||
|
throw new LinkedInException('LinkedIn->xmlToarray(): bad data passed, $xml must be a non-zero length string.');
|
||
|
}
|
||
|
|
||
|
$parser = xml_parser_create();
|
||
|
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
|
||
|
xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1);
|
||
|
if(xml_parse_into_struct($parser, $xml, $tags)) {
|
||
|
$elements = array();
|
||
|
$stack = array();
|
||
|
foreach($tags as $tag) {
|
||
|
$index = count($elements);
|
||
|
if($tag['type'] == 'complete' || $tag['type'] == 'open') {
|
||
|
$elements[$tag['tag']] = array();
|
||
|
$elements[$tag['tag']]['attributes'] = (array_key_exists('attributes', $tag)) ? $tag['attributes'] : null;
|
||
|
$elements[$tag['tag']]['content'] = (array_key_exists('value', $tag)) ? $tag['value'] : null;
|
||
|
if($tag['type'] == 'open') {
|
||
|
$elements[$tag['tag']]['children'] = array();
|
||
|
$stack[count($stack)] = &$elements;
|
||
|
$elements = &$elements[$tag['tag']]['children'];
|
||
|
}
|
||
|
}
|
||
|
if($tag['type'] == 'close') {
|
||
|
$elements = &$stack[count($stack) - 1];
|
||
|
unset($stack[count($stack) - 1]);
|
||
|
}
|
||
|
}
|
||
|
$return_data = $elements;
|
||
|
} else {
|
||
|
// not valid xml data
|
||
|
$return_data = false;
|
||
|
}
|
||
|
xml_parser_free($parser);
|
||
|
return $return_data;
|
||
|
}
|
||
|
}
|