Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 118 additions & 5 deletions src/AccessToken.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,32 @@ class AccessToken implements \JsonSerializable
*/
protected $expiresAt;

/**
*
* @var string
*/
protected $refreshToken;

/**
* @var int
*/
protected $refreshTokenExpiresAt;

/**
* AccessToken constructor.
*
* @param string $token
* @param int $expiresAt
* @param string $refreshToken
* @param int $refreshTokenExpiresAt
*/
public function __construct($token = '', $expiresAt = 0)
public function __construct($token = '', $expiresAt = 0, $refreshToken = '', $refreshTokenExpiresAt = 0)
{
$this->setToken($token);
$this->setExpiresAt($expiresAt);

$this->setRefreshToken($refreshToken);
$this->setRefreshTokenExpiresAt($refreshTokenExpiresAt);
}

/**
Expand All @@ -66,6 +82,16 @@ public function getToken()
return $this->token;
}

/**
* Get RefreshToken string
*
* @return string
*/
public function getRefreshToken()
{
return $this->refreshToken;
}

/**
* Set token string
*
Expand All @@ -79,6 +105,19 @@ public function setToken($token)
return $this;
}

/**
* Set RefreshToken string
*
* @param string $token
*
* @return AccessToken
*/
public function setRefreshToken($refreshToken)
{
$this->refreshToken = $refreshToken;
return $this;
}

/**
* The number of seconds remaining, from the time it was requested, before the token will expire.
*
Expand All @@ -89,6 +128,14 @@ public function getExpiresIn()
return $this->expiresAt - time();
}

/**
* @return int seconds
*/
public function getRefreshTokenExpiresIn()
{
return $this->refreshTokenExpiresAt - time();
}

/**
* Set token expiration time
*
Expand All @@ -102,6 +149,18 @@ public function setExpiresIn($expiresIn)
return $this;
}

/**
*
* @param int $expiresIn amount of seconds before expiration
*
* @return AccessToken
*/
public function setRefreshTokenExpiresIn($expiresIn)
{
$this->refreshTokenExpiresAt = $expiresIn + time();
return $this;
}

/**
* Dynamically typecast token object into string
*
Expand All @@ -122,6 +181,15 @@ public function getExpiresAt()
return $this->expiresAt;
}

/**
*
* @return int
*/
public function getRefreshTokenExpiresAt()
{
return $this->refreshTokenExpiresAt;
}

/**
* Set Unix epoch time when token will expire
*
Expand All @@ -135,6 +203,35 @@ public function setExpiresAt($expiresAt)
return $this;
}

/**
* @param int $expiresAt seconds, unix time
*
* @return AccessToken
*/
public function setRefreshTokenExpiresAt($expiresAt)
{
$this->refreshTokenExpiresAt = $expiresAt;
return $this;
}

/**
*
* @return boolean
*/
public function isExpired()
{
return $this->expiresAt < time() + 60 * 5;
}

/**
*
* @return boolean
*/
public function isRefreshTokenExpired()
{
return !$this->refreshTokenExpiresAt || $this->refreshTokenExpiresAt < time() + 60 * 5;
}

/**
* Convert API response into AccessToken
*
Expand Down Expand Up @@ -173,9 +270,23 @@ public static function fromResponseArray($responseArray)
'Access token expiration date is not specified'
);
}

if (!isset($responseArray['refresh_token'])) {
throw new \InvalidArgumentException(
'Refresh token is not available'
);
}
if (!isset($responseArray['refresh_token_expires_in'])) {
throw new \InvalidArgumentException(
'Refresh token expiration date is not specified'
);
}

return new static(
$responseArray['access_token'],
$responseArray['expires_in'] + time()
$responseArray['expires_in'] + time(),
$responseArray['refresh_token'],
$responseArray['refresh_token_expires_in'] + time()
);
}

Expand All @@ -185,8 +296,10 @@ public static function fromResponseArray($responseArray)
public function jsonSerialize()
{
return [
'token' => $this->getToken(),
'expiresAt' => $this->getExpiresAt(),
'token' => $this->getToken(),
'expiresAt' => $this->getExpiresAt(),
'refreshToken' => $this->getRefreshToken(),
'refreshTokenExpiresAt' => $this->getRefreshTokenExpiresAt(),
];
}
}
}
42 changes: 41 additions & 1 deletion src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ class Client
*/
const OAUTH2_GRANT_TYPE = 'authorization_code';

/**
* Grant type
*/
const REFRESH_TOKEN_GRANT_TYPE = 'refresh_token';

/**
* Response type
*/
Expand Down Expand Up @@ -292,13 +297,48 @@ public function getAccessToken($code = '')
} catch (RequestException $exception) {
throw Exception::fromRequestException($exception);
}

$this->setAccessToken(
AccessToken::fromResponse($response)
);
}
return $this->accessToken;
}

/**
*
* @param AccessToken $token
* @return AccessToken
*/
public function refreshAccessToken(AccessToken $token)
{
$uri = $this->buildUrl('accessToken', []);
$guzzle = new GuzzleClient([
'headers' => [
'Content-Type' => 'application/json',
'x-li-format' => 'json',
'Connection' => 'Keep-Alive'
]
]);

try {
$response = $guzzle->post($uri, ['form_params' => [
'grant_type' => self::REFRESH_TOKEN_GRANT_TYPE,
'refresh_token' => $token->getRefreshToken(),
'client_id' => $this->getClientId(),
'client_secret' => $this->getClientSecret(),
]]);
} catch (RequestException $exception) {
throw Exception::fromRequestException($exception);
}

$this->setAccessToken(
AccessToken::fromResponse($response)
);

return $this->accessToken;
}

/**
* Convert API response into Array
*
Expand Down Expand Up @@ -597,4 +637,4 @@ protected function prepareOptions(array $params, $method)
}
return $options;
}
}
}
19 changes: 8 additions & 11 deletions src/Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,18 +80,15 @@ public static function fromRequestException($exception)
*/
private static function extractErrorDescription($exception)
{
$response = $exception->getResponse();
if (!$response) {
return null;
}

$json = Client::responseToArray($response);
$json = Client::responseToArray(
$exception->getResponse()
);
if (isset($json['error_description'])) {
return $json['error_description'];
}
if (isset($json['message'])) {
return $json['message'];
return $json['error_description'];
} elseif (isset($json['message'])) {
return $json['message'];
} else {
return null;
}
return null;
}
}
47 changes: 8 additions & 39 deletions src/Scope.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,54 +27,23 @@ class Scope extends AbstractEnum
* Allows to read basic information about profile, such as name
*/
const READ_BASIC_PROFILE = 'r_basicprofile';

/**
* Request a minimum information about the user
* Use this scope when implementing "Sign In with LI"
*/
const READ_LITE_PROFILE = 'r_liteprofile';

const READ_FULL_PROFILE = 'r_fullprofile';

/**
* Enables access to email address field
*/
const READ_EMAIL_ADDRESS = 'r_emailaddress';

/**
* Manage and delete your data including your profile, posts, invitations, and messages
*/
const COMPLIANCE = 'w_compliance';
/**
* Enables managing business company
*/
const MANAGE_COMPANY = 'rw_organization_admin';
/**
* Post, comment and like posts on behalf of an organization.
*/
const SHARE_AS_ORGANIZATION = 'w_organization_social';

/**
* Retrieve organizations' posts, comments, and likes.
*/
const READ_ORGANIZATION_SHARES = 'r_organization_social';


/**
* Post, comment and like posts on behalf of an authenticated member.
* Enables to manage business company, retrieve analytics
*/
const SHARE_AS_USER = 'w_member_social';
const MANAGE_COMPANY = 'rw_company_admin';

/**
* Restricted API!
* Enables ability to share content on LinkedIn
*/
const READ_USER_CONTENT = 'r_member_social';

const SHARING = 'w_share';
/**
* Read and write access to ads.
* Manage and delete your data including your profile, posts, invitations, and messages
*/
const ADS_MANAGEMENT = 'rw_ads';
const READ_ADS = 'r_ads';
const READ_LEADS = 'r_ads_leadgen_automation';
const READ_ADS_REPORTING = 'r_ads_reporting';
const READ_WRITE_DMP_SEGMENTS = 'rw_dmp_segments';
const COMPLIANCE = 'w_compliance';
}