Advertisement
Guest User

ShortLinkPhp

a guest
May 1st, 2011
397
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 13.73 KB | None | 0 0
  1. <?php
  2. /**
  3.  * Google Apps Short Links API Class
  4.  *
  5.  * PHP version 5
  6.  *
  7.  * Permission is hereby granted, free of charge, to any person obtaining a copy
  8.  * of this software and associated documentation files (the "Software"), to deal
  9.  * in the Software without restriction, including without limitation the rights
  10.  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11.  * copies of the Software, and to permit persons to whom the Software is
  12.  * furnished to do so, subject to the following conditions:
  13.  * The above copyright notice and this permission notice shall be included in
  14.  * all copies or substantial portions of the Software.
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18.  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20.  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21.  * THE SOFTWARE.
  22.  *
  23.  * @package   ShortLink
  24.  * @author    Adrien Gibrat <adrien.gibrat@gmail.com>
  25.  * @copyright 2011 Adrien Gibrat
  26.  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
  27.  * @version   1.0.0
  28.  * @see       https://www.google.com/enterprise/marketplace/viewListing?productListingId=5143210+6352879591152674960
  29.  * @see       http://www.google.com/support/a/bin/answer.py?answer=114245
  30.  * @usage
  31.     $s = new ShortLink( 'my.domain.com', 'MyHmacSecretKey','user@any-domain.com' );
  32.     echo 'create public short url : ', $r = clone $s->pub( 'http://www.google.com' ), '<br/>', // clone result to keep it for later
  33.         'get status : ',              $r->status, '<br/>',
  34.         'request status : ',          $s->info( $r->short )->status, '<br/>', // non sense, only for demo purpose
  35.         'remaining API call : ',      $s->remain, '<br/>',
  36.         'Info request : ',            $s->request, '<br/>',
  37.         'Creation request : ',        $r->request;
  38.  *
  39.  * If 'status' property is 'no response', check your domain.
  40.  * If 'status' property is 'error 403', check your Hmac secret key or your server time setting!
  41.  */
  42.  
  43. /**
  44.  * Google Apps Short Links Class
  45.  *
  46.  * Easy usage of Google Apps Short Links API (by Google Labs)
  47.  * 3 main methods : short, hash & info
  48.  * + 2 convenience methods : pub & priv
  49.  *
  50.  * @package   ShortLink
  51.  * @author    Adrien Gibrat <adrien.gibrat@gmail.com>
  52.  * @copyright 2011 Adrien Gibrat
  53.  * @license   http://www.opensource.org/licenses/mit-license.php The MIT License
  54.  * @version   1.0.0
  55.  *
  56.  * Access magic properties
  57.  *
  58.  * @property string    $status   Status of last request
  59.  * @property string    $long     Long link
  60.  * @property string    $short    Short link
  61.  * @property boolean   $public   Is link public
  62.  * @property boolean   $hash     Is link hashed
  63.  * @property string    $owner    Owner email
  64.  * @property integer   $usage    Usage link counter
  65.  * @property integer   $count    Usage link counter
  66.  * @property integer   $remain   Remaining API call
  67.  * @property string    $request  Requested url
  68.  * @property stdObject $response Raw decoded response
  69.  *
  70.  */
  71. class ShortLink {
  72.  
  73.     /**
  74.      * Alias for easy access to response propeties
  75.      * @var    array
  76.      * @access public
  77.      * @static
  78.      */
  79.   static public $alias = array(
  80.     'usage'  => 'usage_count',
  81.     'count'  => 'usage_count',
  82.     'short'  => 'shortcut',
  83.     'long'   => 'url',
  84.     'public' => 'is_public',
  85.     'hash'   => 'is_hash'
  86.   );
  87.  
  88.     /**
  89.      * Remaining API call stored by domain
  90.      * @var    array
  91.      * @access protected
  92.      * @static
  93.      */
  94.   static protected $remain = array();
  95.  
  96.     /**
  97.      * Max number of retry in case of creation / update failure
  98.      * @var    integer
  99.      * @access public
  100.      */
  101.   public $maxRetry = 2;
  102.    
  103.     /**
  104.      * Actual number of retry for last request
  105.      * @var    integer
  106.      * @access protected
  107.      */
  108.   protected $retry;
  109.  
  110.     /**
  111.      * Domain name
  112.      * @var    string  
  113.      * @access protected
  114.      */
  115.   protected $domain;
  116.  
  117.     /**
  118.      * Hmac secret key
  119.      * @var    string  
  120.      * @access protected
  121.      */
  122.   protected $key;
  123.  
  124.     /**
  125.      * User email
  126.      * @var    string  
  127.      * @access protected
  128.      */
  129.   protected $user;
  130.  
  131.     /**
  132.      * Last request url
  133.      * @var    string
  134.      * @access protected
  135.      */
  136.   protected $request;
  137.  
  138.     /**
  139.      * Last request response
  140.      * @var    object|false
  141.      * @access protected
  142.      */
  143.   protected $response;
  144.  
  145.     /**
  146.      * Constructor
  147.      *
  148.      * Set mandatory informations
  149.      *
  150.      * @param  string  $domain   Domain name
  151.      * @param  string  $key      Hmac secret key
  152.      * @param  string  $user     Owner / user email
  153.      */
  154.   public function __construct ( $domain, $key, $user ) {
  155.     $this->user   = $user;
  156.     $this->key    = $key;
  157.     $this->domain = $domain;
  158.   }
  159.  
  160.     /**
  161.      * Magic getter
  162.      *
  163.      * Get last request, response and number of retry (read only)
  164.      * Easy access to last response properties (with alias)
  165.      *
  166.      * @param  string  $property Property name
  167.      * @return mixed             Last response property value or last request / response
  168.      */
  169.   public function __get ( $property ) {
  170.     switch ( $property ) {
  171.       case 'remain' :
  172.         return isset( self::$remain[$this->domain] ) ? self::$remain[$this->domain] : true;
  173.       case 'response' :
  174.         return $this->response;
  175.       case 'request' :
  176.         return $this->request;
  177.       case 'retry' :
  178.         return $this->retry;
  179.     }
  180.     if ( ! $this->response ) {
  181.         return;
  182.     }
  183.     $alias = isset( self::$alias[$property] ) ? self::$alias[$property] : false;
  184.     if ( $alias && isset( $this->response->{$alias} ) ) {
  185.       return $this->response->{$alias};
  186.     }
  187.     if ( isset( $this->response->{$property} ) ) {
  188.       return $this->response->{$property};
  189.     }
  190.   }
  191.  
  192.     /**
  193.      * Magic toString
  194.      *
  195.      * Get last response short url
  196.      *
  197.      * @return string            Last request short url or empty string on failure
  198.      */
  199.   public function __toString () {
  200.       return $this->_success () && isset( $this->response->shortcut ) ?
  201.         'http://' . $this->domain . '/' . $this->response->shortcut :
  202.         '';
  203.   }
  204.  
  205.     /**
  206.      * Create private short link (for convenience)
  207.      *
  208.      * Create / update private shortcut or hashed link
  209.      * If hashed link exists, visibility is set to private, no new hashed link is created
  210.      * If shortcut exists, url is updated and visibility set to private
  211.      *
  212.      * @param  string $url       Long url to shorten
  213.      * @param  string $shortcut  Optional shortcut, if ommited create or update hashed link
  214.      * @return ShortLink         Chainable object to allow easy access to response
  215.      */
  216.   public function priv ( $url, $shortcut = null ) {
  217.     return $shortcut ?
  218.       $this->short( $shortcut, $url, false ) :
  219.       $this->hash( $url, false  );
  220.   }
  221.  
  222.     /**
  223.      * Create public short link (for convenience)
  224.      *
  225.      * Create / update public shortcut or hashed link
  226.      * If hashed link exists, visibility is set to public, no new hashed link is created
  227.      * If shortcut exists, url is updated and visibility set to public
  228.      *
  229.      * @param  string $url       Long url to shorten
  230.      * @param  string $shortcut  Optional shortcut, if ommited create or update hashed link
  231.      * @return ShortLink         Chainable object to allow easy access to response
  232.      */
  233.   public function pub ( $url, $shortcut = null ) {
  234.     return $shortcut ?
  235.       $this->short( $shortcut, $url, true ) :
  236.       $this->hash( $url, true );
  237.   }
  238.  
  239.     /**
  240.      * Create shortcut link
  241.      *
  242.      * Create / update shortcut link
  243.      * If shortcut exists, url and visibility are updated
  244.      *
  245.      * @param  string  $shortcut Shortcut
  246.      * @param  string  $url      Long url to shorten
  247.      * @param  boolean $public   Short link visiblity: true = public, false = private (default)
  248.      * @return ShortLink         Chainable object to allow easy access to response
  249.      */
  250.   public function short ( $shortcut, $url, $public = false ) {
  251.     $this->_valid( $shortcut ) && $this->_request( 'get_or_create_shortlink', array(
  252.         'is_public' => $public ? 'true' : 'false',
  253.         'shortcut' => $shortcut,
  254.         'url' => $url,
  255.         'user' => $this->user
  256.       ), $this->maxRetry );
  257.     return $this;
  258.   }
  259.  
  260.     /**
  261.      * Create hashed link
  262.      *
  263.      * Create / update hashed link
  264.      * If hashed link exists, visibility is updated, no new hashed link is created
  265.      *
  266.      * @param  string  $url      Long url to shorten
  267.      * @param  boolean $public   Short link visiblity: true = public, false = private (default)
  268.      * @return ShortLink         Chainable object to allow easy access to response
  269.      */
  270.   public function hash ( $url, $public = false ) {
  271.     $this->_request( 'get_or_create_hash', array(
  272.       'is_public' => $public ? 'true' : 'false',
  273.       'url' => $url,
  274.       'user' => $this->user
  275.     ), $this->maxRetry );
  276.     return $this;
  277.   }
  278.  
  279.     /**
  280.      * Get details about short link
  281.      *
  282.      * Retrieve basic informations about short link
  283.      *
  284.      * @param  string  $shortcut Shortcut
  285.      * @return ShortLink         Chainable object to allow easy access to response
  286.      */
  287.   public function info ( $shortcut ) {
  288.     $this->_valid( $shortcut ) && $this->_request( 'get_details', array( 'shortcut' => $shortcut ) );
  289.     return $this;
  290.   }
  291.  
  292.    /**
  293.      * Send signed request to API
  294.      *
  295.      * Build signed GET request and get response
  296.      * Automatically retry on failure, you can set the number of retry with public "retry" property
  297.      *
  298.      * @param  string  $method   Method to call
  299.      * @param  array   $params   Request parameters
  300.      * @param  integer $maxRetry Maximum retry
  301.      * @return stdObject|boolean Response object on success or false on failure
  302.      */
  303.   protected function _request ( $method, array $params, $maxRetry = 0 ) {
  304.     $params = array(
  305.       'oauth_signature_method' => 'HMAC-SHA1',
  306.       'timestamp' => time(),
  307.       'user' => $this->user
  308.     ) + $params;
  309.     ksort($params);
  310.     $params = http_build_query( $params );
  311.     $url = 'http://' . $this->domain . '/js/' . $method;
  312.     $signature = 'GET&' . $this->_encode( $url ) . '&' . $this->_encode( $params );
  313.     $oauth = $this->_encode( base64_encode( hash_hmac( 'sha1', $signature, $this->key, true ) ) );
  314.     $handle = curl_init( $this->request = $url . '?' . $params . '&oauth_signature=' . $oauth ) ;
  315.     curl_setopt( $handle, CURLOPT_RETURNTRANSFER, 1 );
  316.     $this->retry = 0;
  317.     while ( ( $this->retry <= $maxRetry ) && $this->_response( $handle ) ) {
  318.       if ( ! isset( $this->response->shortcut ) ) {
  319.         $this->retry++;
  320.         continue;
  321.       }
  322.       break;
  323.     }
  324.     curl_close( $handle );
  325.     return $this->response;
  326.   }
  327.  
  328.     /**
  329.      * Check and set response
  330.      *
  331.      * Set response property on success and set appropriate status on error
  332.      *
  333.      * @param  ressource $curl   Curl handle ressource.
  334.      * @return boolean           True on success or false on failure
  335.      */
  336.   protected function _response ( $curl ) {
  337.     $this->response = json_decode( curl_exec( $curl ) );
  338.     if ( $this->response && isset( $this->response->status ) ) {
  339.       if ( isset( $this->response->estimated_api_calls_remaining ) ) {
  340.         self::$remain[$this->domain] = $this->response->estimated_api_calls_remaining;
  341.       }
  342.           return true;
  343.       }
  344.       $code = curl_getinfo( $curl, CURLINFO_HTTP_CODE );
  345.       $this->response = (object) array( 'status' =>  $code ? 'error ' . $code : 'no response' );
  346.       return false;
  347.   }
  348.  
  349.     /**
  350.      * Proper url encode
  351.      *
  352.      * Replace space characters encoded as "+" by "%20"
  353.      *
  354.      * @param  string  $value    String to encode
  355.      * @return string            Url-encoded string
  356.      */
  357.   protected function _encode ( $value ) {
  358.     return str_replace( '+', '%20', urlencode( $value ) );
  359.   }
  360.  
  361.     /**
  362.      * Check shortcut
  363.      *
  364.      * Check if shortcut is valid, as some url specific characters are not allowed
  365.      * Reset request and response properties if invalid shortcut (consistency purpose)
  366.      *
  367.      * @param  string  $shortcut Shortcut
  368.      * @return boolean           True if shortcut is valid or false if it's not
  369.      */
  370.   protected function _valid ( $shortcut ) {
  371.     if ( preg_match( '~\/|\?|=|#~', $shortcut ) ) {
  372.       $this->retry = 0;
  373.       $this->request = null;
  374.       return $this->response = false;
  375.     }
  376.     return true;
  377.   }
  378.  
  379.     /**
  380.      * Check response
  381.      *
  382.      * Check if last response status is ok
  383.      *
  384.      * @return boolean           True if last response status is ok or false if it's not
  385.      */
  386.   protected function _success () {
  387.     return $this->response && $this->response->status === 'ok';
  388.   }
  389.  
  390. }
  391. /* Bonus functions */
  392. function utm ( $url, $campaign, $medium, $source, $content = null, $term = null ) {
  393.     $params = array_filter( array(
  394.       'utm_campaign' => $campaign,
  395.       'utm_medium'   => $medium,
  396.       'utm_source'   => $source,
  397.       'utm_content'  => $content,
  398.       'utm_term'     => $term
  399.     ) );
  400.     if ( $query = parse_url( $url, PHP_URL_QUERY ) ) {
  401.       parse_str( $query, $oldParams );
  402.       $params = array_merge( $oldParams, $params );
  403.     }
  404.     $newQuery = http_build_query( $params );
  405.     return $query ?
  406.       str_replace( $query, $newQuery, $url ) :
  407.       $url . '?' . $newQuery;
  408. }
  409.  
  410. function qr ( $url, $size = 150 ) {
  411.   return 'http://chart.apis.google.com/chart?cht=qr&chs=' . $size . 'x' . $size . '&choe=UTF-8&chld=H&chl=' . urlencode( $url );
  412. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement