-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
362 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
#### 1.0 (May 29, 2014) | ||
|
||
* Initial release |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,62 @@ | ||
helpscout-apps-php | ||
================== | ||
Help Scout Dynamic App Client Library | ||
===================================== | ||
|
||
Client library to help with building custom apps to integrate with Help Scout | ||
Client library to assist with building custom apps that integrate with Help Scout. More inforomation: [http://developer.helpscout.net/custom-apps/](http://developer.helpscout.net/custom-apps/) | ||
|
||
Version 1.0 Released | ||
--------------------- | ||
Please see the [Changelog](https://github.com/helpscout/helpscout-apps-php/blob/master/CHANGELOG.md) for details. | ||
|
||
Example Usage (1) | ||
--------------------- | ||
<pre><code> | ||
use HelpScoutApp\DynamicApp; | ||
|
||
include 'src/HelpScoutApp/DynamicApp.php'; | ||
|
||
$app = new DynamicApp('SECRET-KEY-HERE'); | ||
if ($app->isSignatureValid()) { | ||
$customer = $app->getCustomer(); | ||
$user = $app->getUser(); | ||
$convo = $app->getConversation(); | ||
|
||
$html = array( | ||
'<p>Convo</p>', | ||
'<ul>', | ||
'<li>Id: ' . $convo->getId() . '</li>', | ||
'<li>Number: ' . $convo->getNumber() . '</li>', | ||
'<li>Subject: ' . $convo->getSubject() . '</li>', | ||
'</ul>', | ||
'<p>Customer</p>', | ||
'<ul>', | ||
'<li>First: ' . $customer->getFirstName() . '</li>', | ||
'<li>Last: ' . $customer->getLastName() . '</li>', | ||
'<li>Email: ' . $customer->getEmail() . '</li>', | ||
'</ul>', | ||
'<p>User</p>', | ||
'<ul>', | ||
'<li>First: ' . $user->getFirstName() . '</li>', | ||
'<li>Last: ' . $user->getLastName() . '</li>', | ||
'<li>Id: ' . $user->getId() . '</li>', | ||
'</ul>' | ||
); | ||
echo $app->getResponse($html); | ||
} else { | ||
echo 'Invalid Request'; | ||
} | ||
</code></pre> | ||
|
||
Example Usage (2) | ||
--------------------- | ||
<pre><code> | ||
use HelpScoutApp\DynamicApp; | ||
|
||
include 'src/HelpScoutApp/DynamicApp.php'; | ||
|
||
$app = new DynamicApp('SECRET-KEY-HERE'); | ||
if ($app->isSignatureValid()) { | ||
echo $app->getResponse('<p>Hello World</p>'); | ||
} else { | ||
echo 'Invalid Request'; | ||
} | ||
</code></pre> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"name": "helpscout/apps", | ||
"type": "library", | ||
"description": "Client library to assist with building dynamic apps that integrate with the Help Scout UI", | ||
"keywords": ["apps", "dynamic-app", "helpscout"], | ||
"homepage": "http://www.helpscout.net", | ||
"license": "MIT", | ||
"require": { | ||
"php": ">=5.3.2", | ||
"ext-curl": "*" | ||
}, | ||
"autoload": { | ||
"psr-0": { "HelpScoutApp\\": "src/" } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
<?php | ||
namespace HelpScoutApp; | ||
|
||
final class ClassLoader { | ||
const NAMESPACE_SEPARATOR = '\\'; | ||
|
||
private $baseDir = false; | ||
|
||
/** | ||
* @var \HelpScout\ClassLoader | ||
*/ | ||
private static $instance = false; | ||
|
||
private function __construct() { | ||
spl_autoload_register(array($this,'autoload')); | ||
$this->baseDir = dirname(__FILE__) . DIRECTORY_SEPARATOR; | ||
} | ||
|
||
public function __destruct() { | ||
spl_autoload_unregister(array($this, 'autoload')); | ||
} | ||
|
||
public function autoload($className) { | ||
if (strpos($className, 'HelpScoutApp') === false) { | ||
return false; | ||
} | ||
$className = str_replace( | ||
array(self::NAMESPACE_SEPARATOR . 'HelpScoutApp' . self::NAMESPACE_SEPARATOR, 'HelpScoutApp' . self::NAMESPACE_SEPARATOR), '', $className | ||
); | ||
require_once ($this->baseDir . str_replace(self::NAMESPACE_SEPARATOR, DIRECTORY_SEPARATOR, $className) . '.php'); | ||
return true; | ||
} | ||
|
||
public static function register() { | ||
if (self::$instance === false) { | ||
self::$instance = new ClassLoader(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
<?php | ||
namespace HelpScoutApp; | ||
|
||
use HelpScoutApp\model\Customer; | ||
use HelpScoutApp\model\Conversation; | ||
use HelpScoutApp\model\User; | ||
|
||
require_once 'ClassLoader.php'; | ||
|
||
class DynamicApp { | ||
const NAMESPACE_SEPARATOR = '\\'; | ||
|
||
private $secretKey = false; | ||
private $input = false; | ||
|
||
/** @var \HelpScoutApp\model\Customer */ | ||
private $customer = false; | ||
|
||
/** @var \HelpScoutApp\model\Conversation */ | ||
private $convo = false; | ||
|
||
/** @var \HelpScoutApp\model\User */ | ||
private $user = false; | ||
|
||
public function __construct($key) { | ||
ClassLoader::register(); | ||
$this->secretKey = $key; | ||
} | ||
|
||
private function getHeader($header) { | ||
if (isset($_SERVER[$header])) { | ||
return $_SERVER[$header]; | ||
} | ||
return false; | ||
} | ||
|
||
private function getJsonString() { | ||
if ($this->input === false) { | ||
$this->input = @file_get_contents('php://input'); | ||
} | ||
return $this->input; | ||
} | ||
|
||
private function generateSignature() { | ||
$str = $this->getJsonString(); | ||
if ($str) { | ||
return base64_encode(hash_hmac('sha1', $str, $this->secretKey, true)); | ||
} | ||
return false; | ||
} | ||
|
||
private function initData() { | ||
if ($this->customer === false) { | ||
$data = $this->getHelpScoutData(); | ||
if ($data) { | ||
if (isset($data->customer)) { | ||
$this->customer = new Customer($data->customer); | ||
} | ||
if (isset($data->ticket)) { | ||
$this->convo = new Conversation($data->ticket); | ||
} | ||
if (isset($data->user)) { | ||
$this->user = new User($data->user); | ||
} | ||
} | ||
unset($data); | ||
$this->input = null; | ||
} | ||
} | ||
|
||
/** | ||
* @return \HelpScoutApp\model\Customer | ||
*/ | ||
public function getCustomer() { | ||
$this->initData(); | ||
return $this->customer; | ||
} | ||
|
||
/** | ||
* @return \HelpScoutApp\model\Conversation | ||
*/ | ||
public function getConversation() { | ||
$this->initData(); | ||
return $this->convo; | ||
} | ||
|
||
/** | ||
* @return \HelpScoutApp\model\User | ||
*/ | ||
public function getUser() { | ||
$this->initData(); | ||
return $this->user; | ||
} | ||
|
||
/** | ||
* Returns true if the current request is a valid webhook issued from Help Scout, false otherwise. | ||
* @return boolean | ||
*/ | ||
public function isSignatureValid() { | ||
$signature = $this->generateSignature(); | ||
if ($signature) { | ||
return $signature === $this->getHeader('HTTP_X_HELPSCOUT_SIGNATURE'); | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* @return array | ||
*/ | ||
private function getHelpScoutData() { | ||
$this->getJsonString(); //ensure data has been loaded from input | ||
return json_decode($this->input); | ||
} | ||
|
||
/** | ||
* Pass either an array that will be flattened to a string, or a string of HTML. | ||
* | ||
* @param mixed $html | ||
* @return string | ||
*/ | ||
public function getResponse($html) { | ||
if (is_array($html)) { | ||
$html = implode('', $html); | ||
} | ||
return json_encode(array('html' => $html)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
namespace HelpScoutApp\model; | ||
|
||
class Conversation { | ||
private $id; | ||
private $number; | ||
private $subject; | ||
|
||
public function __construct($data=null) { | ||
if ($data) { | ||
$this->id = isset($data->id) ? $data->id : §null; | ||
$this->number = isset($data->number) ? $data->number : null; | ||
$this->subject= isset($data->subject)? $data->subject : null; | ||
} | ||
} | ||
|
||
public function getId() { | ||
return $this->id; | ||
} | ||
|
||
public function getNumber() { | ||
return $this->number; | ||
} | ||
|
||
public function getSubject() { | ||
return $this->subject; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
namespace HelpScoutApp\model; | ||
|
||
class Customer { | ||
private $id; | ||
private $fname; | ||
private $lname; | ||
private $email; | ||
private $emails; | ||
|
||
public function __construct($data=null) { | ||
if ($data) { | ||
$this->id = isset($data->id) ? $data->id : null; | ||
$this->fname = isset($data->fname) ? $data->fname : null; | ||
$this->lname = isset($data->lname) ? $data->lname : null; | ||
$this->email = isset($data->email) ? $data->email : null; | ||
$this->emails= isset($data->emails)? $data->emails: null; | ||
} | ||
} | ||
|
||
public function getId() { | ||
return $this->id; | ||
} | ||
|
||
public function getFirstName() { | ||
return $this->fname; | ||
} | ||
|
||
public function getLastName() { | ||
return $this->lname; | ||
} | ||
|
||
public function getEmail() { | ||
return $this->email; | ||
} | ||
|
||
public function getEmails() { | ||
return $this->emails; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
<?php | ||
namespace HelpScoutApp\model; | ||
|
||
class User { | ||
const ROLE_USER = 3; | ||
const ROLE_ADMIN = 2; | ||
const ROLE_OWNER = 1; | ||
|
||
private $id; | ||
private $fname; | ||
private $lname; | ||
private $role; | ||
|
||
public function __construct($data=null) { | ||
if ($data) { | ||
$this->id = isset($data->id) ? $data->id : null; | ||
$this->fname = isset($data->fname) ? $data->fname : null; | ||
$this->lname = isset($data->lname) ? $data->lname : null; | ||
$this->role = isset($data->role) ? intval($data->role): null; | ||
} | ||
} | ||
|
||
public function getId() { | ||
return $this->id; | ||
} | ||
|
||
public function getFirstName() { | ||
return $this->fname; | ||
} | ||
|
||
public function getLastName() { | ||
return $this->lname; | ||
} | ||
|
||
public function getRole() { | ||
return $this->role; | ||
} | ||
|
||
public function isOwnerOrAdmin() { | ||
return in_array($this->role, array(self::ROLE_OWNER, self::ROLE_ADMIN)); | ||
} | ||
|
||
public function isOwner() { | ||
return $this->role == self::ROLE_OWNER; | ||
} | ||
public function isAdmin() { | ||
return $this->role == self::ROLE_ADMIN; | ||
} | ||
} |