Permalink
Browse files

Added initial release with methods for get(), getAll() and getAllLang…

…uages(). Includes tests and README documentation.
  • Loading branch information...
benjaminpearson committed Nov 26, 2009
1 parent ef11978 commit c5b4fbfc4d7851d7e66d493285b52ec01210dec3
View
103 README
@@ -0,0 +1,103 @@
+Snipplr API PHP Library
+
+A small library that allows interaction with Snipplr's API. Designed to be used in PHP projects or as a CakePHP vendor. When using this library its highly recommended that you cache your results, visit CakePHP Cache page: http://book.cakephp.org/view/767/Cache-write
+
+QUIRKS
+----------------------------------------------------------------------------------------
+1. In getAll method: Multiple tags don't seem to work in the Snipplr API. Only the last tag will be used.
+2. In getAll method: Limit of 0 or 1 appears to return all snippets (ie, not limited)
+
+
+USAGE
+----------------------------------------------------------------------------------------
+
+CakePHP:
+App::import('Vendor', 'SnipplrCore', array('file' => 'snipplr-api-php'.DS.'snipplr.core.php'));
+$SnipplrCore = new SnipplrCore();
+$snippet = $SnipplrCore->get('18153');
+$snippets = $SnipplrCore->getAll();
+$languages = $SnipplrCore->getAllLanguages();
+
+PHP:
+require_once "snipplr-api-php".DIRECTORY_SEPARATOR."snipplr.core.php";
+$SnipplrCore = new SnipplrCore();
+$snippet = $SnipplrCore->get('18153');
+$snippets = $SnipplrCore->getAll();
+$languages = $SnipplrCore->getAllLanguages();
+
+
+OUTPUT
+----------------------------------------------------------------------------------------
+
+Method Call: get('18153');
+Example Output:
+ Array
+ (
+ [id] => 18153
+ [user_id] => 11806
+ [username] => benjaminpearson
+ [title] => CakePHP highlight active menu item for page
+ [language] => Other
+ [comment] =>
+ [created] => 2009-08-11 00:35:14
+ [updated] => 2009-11-14 15:56:18
+ [source] => <ul>
+ <li class="<?php if($this->viewVars['page'] == 'home') { echo 'active'; } ?>"><?php echo $html->link('Home', '/') ?></li>
+ </ul>
+ [tags] => Array
+ (
+ [0] => textmate
+ [1] => cakephp
+ )
+ [snipplr_url] => http://snipplr.com/view/18153/cakephp-highlight-active-menu-item-for-page
+ )
+
+
+Method Call: getAll();
+Example Output:
+ Array
+ (
+ [0] => Array
+ (
+ [id] => 22696
+ [title] => Sinatra Ajax Layout
+ [updated] => Array
+ (
+ [datetime] => 20091107T07:47:12
+ [timezone] => -05:00 EST
+ )
+ [private] => 0
+ [favourite] => 0
+ )
+
+ [1] => Array
+ (
+ [id] => 22385
+ [title] => jQuery Log Function
+ [updated] => Array
+ (
+ [datetime] => 20091103T08:12:37
+ [timezone] => -05:00 EST
+ )
+ [private] => 0
+ [favourite] => 0
+ )
+ ..etc
+ )
+
+Method Call: getAllLanguages();
+Example Output:
+ Array
+ (
+ [0] => Array
+ (
+ [slug] => actionscript
+ [name] => ActionScript
+ )
+ [1] => Array
+ (
+ [slug] => actionscript-3
+ [name] => ActionScript 3
+ )
+ ...etc
+ )
@@ -0,0 +1,77 @@
+<?php
+/**
+ * A Response Helper that manipulates the response XML into formatted arrays for ease of use.
+ * The responses received from Snipplr follow a set structure. Each method attempts to format
+ * this structure for use in your application. If a response doesn't match the structure
+ * defined, an error is assumed. If Snipplr changes the output of their responses in future updates,
+ * this file will also need to be updated.
+ */
+
+class SnipplrResponse
+{
+ function processSnippetGetResponse($response) {
+ $formatted = array();
+
+ // if response is in correct array structure then process it, else return empty array
+ if(isset($response['params']['param']['value']['struct']['member'])) {
+ $item = $response['params']['param']['value']['struct']['member'];
+ $formatted = array(
+ 'id' => $item[0]['value']['string'],
+ 'user_id' => $item[1]['value']['string'],
+ 'username' => $item[2]['value']['string'],
+ 'title' => $item[3]['value']['string'],
+ 'language' => $item[4]['value']['string'],
+ 'comment' => $item[5]['value']['string'],
+ 'created' => $item[6]['value']['string'],
+ 'updated' => $item[7]['value']['string'],
+ 'source' => $item[8]['value']['string'],
+ 'tags' => explode(" ", trim($item[9]['value']['string'])),
+ 'snipplr_url' => $item[10]['value']['string']
+ );
+ }
+
+ return $formatted;
+ }
+
+ function processSnippetListResponse($response) {
+ $formatted = array();
+
+ // if response is in correct array structure then process it, else return empty array
+ if(isset($response['params']['param']['value']['array']['data']['value'])) {
+ foreach($response['params']['param']['value']['array']['data']['value'] as $item) {
+ $item = $item['struct']['member'];
+
+ $datetime = new DateTime($item[2]['value']['struct']['member'][0]['value']['dateTime.iso8601']);
+
+ $formatted[] = array(
+ 'id' => $item[0]['value']['string'],
+ 'title' => $item[1]['value']['string'],
+ 'updated' => array(
+ 'datetime' => $datetime->format('Y-m-d h:m:s'),
+ 'timezone' => $item[2]['value']['struct']['member'][1]['value']['string'],
+ ),
+ 'private' => $item[3]['value']['boolean'],
+ 'favourite' => $item[4]['value']['boolean'],
+ );
+ }
+ }
+
+ return $formatted;
+ }
+
+ function processLanguagesListResponse($response) {
+ $formatted = array();
+ // if response is in correct array structure then process it, else return empty array
+ if(isset($response['params']['param']['value']['struct']['member'])) {
+ foreach($response['params']['param']['value']['struct']['member'] as $item) {
+ $formatted[] = array(
+ 'slug' => $item['name'],
+ 'name' => $item['value']['string']
+ );
+ }
+ }
+
+ return $formatted;
+ }
+}
+?>
View
@@ -0,0 +1,91 @@
+<?php
+/**
+ * A REST Helper that prepares and sends data to API URLs.
+ * Snipplr only uses POST requests which require XML structured data to be sent to them.
+ *
+ */
+
+require_once('snipplr.xml.php');
+require_once('snipplr.response.php');
+
+class SnipplrRest
+{
+ var $api_key;
+ var $url = 'http://snipplr.com/xml-rpc.php';
+ var $SnipplrXML;
+ var $SnipplrResponse;
+
+ function SnipplrRest($api_key) {
+ $this->api_key = $api_key;
+ $this->SnipplrXML = new SnipplrXML();
+ $this->SnipplrResponse = new SnipplrResponse();
+ }
+
+ // Snipplr API only uses post calls. This manages the steps involved.
+ function post($method, $params = array()) {
+ try {
+ $xml = $this->_constructXML($method, $params);
+ $response = $this->_httpPost($this->url, $xml);
+ return $this->_processResponse($method, $response);
+ } catch (Exception $e) {
+ return null;
+ }
+ }
+
+ // Contructs an XML object in the format required by Snipplr
+ function _constructXML($method, $params = array()) {
+ // list of methods that require an api key
+ $api_key_required_methods = array('snippet.list');
+
+ // set the methodName for xml query
+ $xml_data['methodName'] = $method;
+
+ // if method requires api key then add it
+ if(in_array($method, $api_key_required_methods)) {
+ $xml_data['params']['param'][] = array(
+ 'key' => "api_key",
+ 'value' => $this->api_key
+ );
+ }
+
+ // add all other specified params
+ foreach($params as $key => $value) {
+ $xml_data['params']['param'][] = array(
+ 'key' => $key,
+ 'value' => $value
+ );
+ }
+
+ return $this->SnipplrXML->toXML($xml_data, 'methodCall');
+ }
+
+ // Makes a generic http post request
+ function _httpPost($url, $data) {
+ $c = curl_init();
+ curl_setopt($c, CURLOPT_URL, $url);
+ curl_setopt($c, CURLOPT_POST, 1);
+ curl_setopt($c, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($c, CURLOPT_POSTFIELDS, $data);
+ curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
+ $output = curl_exec($c);
+ curl_close($c);
+ return $output;
+ }
+
+ // Processes the xml
+ function _processResponse($method, $response) {
+ $raw = $this->SnipplrXML->toArray($response);
+
+ switch($method) {
+ case 'snippet.get':
+ return $this->SnipplrResponse->processSnippetGetResponse($raw);
+ case 'snippet.list':
+ return $this->SnipplrResponse->processSnippetListResponse($raw);
+ case 'languages.list':
+ return $this->SnipplrResponse->processLanguagesListResponse($raw);
+ default:
+ return null;
+ }
+ }
+}
+?>
View
@@ -0,0 +1,117 @@
+<?php
+/**
+ * An XML Helper that allows conversion between arrays and XML objects.
+ * This version isn't specific for Snipplr and can be transported to other applications by changing
+ * the classname and appropriate static class name calls in the code. "SnipplrXML" is used as a pseudo namespace.
+ *
+ * Originating Source: http://snipplr.com/view/3491/convert-php-array-to-xml-or-simple-xml-object-if-you-wish/
+ */
+class SnipplrXML
+{
+ /**
+ * The main function for converting to an XML document.
+ * Pass in a multi dimensional array and this recursively loops through and builds up an XML document.
+ *
+ * @param array $data
+ * @param string $rootNodeName - what you want the root node to be - defaults to data.
+ * @param SimpleXMLElement $xml - should only be used recursively
+ * @return string XML
+ */
+ public static function toXML($data, $rootNodeName = 'ResultSet', &$xml = null) {
+ // turn off compatibility mode as simple xml throws a wobbly if you don't.
+ if(ini_get('zend.ze1_compatibility_mode') == 1) {
+ ini_set('zend.ze1_compatibility_mode', 0);
+ }
+
+ if(is_null($xml)) {
+ $xml = simplexml_load_string("<?xml version='1.0' encoding='utf-8'?><$rootNodeName/>");
+ }
+
+ // loop through the data passed in.
+ foreach($data as $key => $value) {
+ // no numeric keys in our xml please!
+ $numeric = 0;
+ if(is_numeric($key)) {
+ $numeric = 1;
+ $key = $rootNodeName;
+ }
+
+ // delete any char not allowed in XML element names
+ $key = preg_replace('/[^a-z0-9\-\_\.\:]/i', '', $key);
+
+ // if there is another array found recrusively call this function
+ if(is_array($value)) {
+ $node = SnipplrXML::isAssoc($value) || $numeric ? $xml->addChild($key) : $xml;
+
+ // recrusive call.
+ if($numeric) {
+ $key = 'anon';
+ }
+ SnipplrXML::toXml($value, $key, $node);
+ } else {
+ // add single node.
+ $value = htmlentities($value);
+ $xml->addChild($key, $value);
+ }
+ }
+
+ // pass back as XML
+ return $xml->asXML();
+ }
+
+
+ /**
+ * Convert an XML document to a multi dimensional array
+ * Pass in an XML document (or SimpleXMLElement object) and this recrusively loops through and builds a representative array
+ *
+ * @param string $xml - XML document - can optionally be a SimpleXMLElement object
+ * @return array ARRAY
+ */
+ public static function toArray( $xml ) {
+ if(is_string($xml)) {
+ $xml = new SimpleXMLElement( $xml );
+ }
+
+ $children = $xml->children();
+
+ if(!$children) {
+ return (string) $xml;
+ }
+
+ $arr = array();
+ $adjusted = array(); // used to determine if a node has been converted to an array of nodes
+ foreach($children as $key => $node) {
+ $node = SnipplrXML::toArray($node);
+
+ // support for 'anon' non-associative arrays
+ if($key == 'anon') {
+ $key = count($arr);
+ }
+
+ // if the node is already set, put it into an array
+ if(isset($arr[$key])) {
+ if(isset($adjusted[$key]) && $adjusted[$key] == false) {
+ $first_value = $arr[$key];
+ $arr[$key] = array();
+ $arr[$key][] = $first_value;
+ $adjusted[$key] = true;
+ }
+
+ if(!is_array($arr[$key]) || (isset($arr[$key][0]) && $arr[$key][0] == null)) {
+ $arr[$key] = array( $arr[$key] );
+ }
+ $arr[$key][] = $node;
+ } else {
+ $arr[$key] = $node;
+ $adjusted[$key] = false;
+ }
+ }
+ return $arr;
+ }
+
+ // determine if a variable is an associative array
+ public static function isAssoc( $array ) {
+ return (is_array($array) && 0 !== count(array_diff_key($array, array_keys(array_keys($array)))));
+ }
+}
+?>
Oops, something went wrong.

0 comments on commit c5b4fbf

Please sign in to comment.