web/enmi/Zend/Service/Delicious.php
changeset 19 1c2f13fd785c
parent 0 4eba9c11703f
equal deleted inserted replaced
18:bd595ad770fc 19:1c2f13fd785c
       
     1 <?php
       
     2 
       
     3 /**
       
     4  * Zend Framework
       
     5  *
       
     6  * LICENSE
       
     7  *
       
     8  * This source file is subject to the new BSD license that is bundled
       
     9  * with this package in the file LICENSE.txt.
       
    10  * It is also available through the world-wide-web at this URL:
       
    11  * http://framework.zend.com/license/new-bsd
       
    12  * If you did not receive a copy of the license and are unable to
       
    13  * obtain it through the world-wide-web, please send an email
       
    14  * to license@zend.com so we can send you a copy immediately.
       
    15  *
       
    16  * @category   Zend
       
    17  * @package    Zend_Service
       
    18  * @subpackage Delicious
       
    19  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    20  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    21  * @version    $Id: Delicious.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    22  */
       
    23 
       
    24 
       
    25 /**
       
    26  * @see Zend_Rest_Client
       
    27  */
       
    28 require_once 'Zend/Rest/Client.php';
       
    29 
       
    30 /**
       
    31  * @see Zend_Json_Decoder
       
    32  */
       
    33 require_once 'Zend/Json/Decoder.php';
       
    34 
       
    35 /**
       
    36  * @see Zend_Service_Delicious_SimplePost
       
    37  */
       
    38 require_once 'Zend/Service/Delicious/SimplePost.php';
       
    39 
       
    40 /**
       
    41  * @see Zend_Service_Delicious_Post
       
    42  */
       
    43 require_once 'Zend/Service/Delicious/Post.php';
       
    44 
       
    45 /**
       
    46  * @see Zend_Service_Delicious_PostList
       
    47  */
       
    48 require_once 'Zend/Service/Delicious/PostList.php';
       
    49 
       
    50 
       
    51 /**
       
    52  * Zend_Service_Delicious is a concrete implementation of the del.icio.us web service
       
    53  *
       
    54  * @category   Zend
       
    55  * @package    Zend_Service
       
    56  * @subpackage Delicious
       
    57  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    58  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    59  */
       
    60 class Zend_Service_Delicious
       
    61 {
       
    62     const API_URI = 'https://api.del.icio.us';
       
    63 
       
    64     const PATH_UPDATE        = '/v1/posts/update';
       
    65     const PATH_TAGS          = '/v1/tags/get';
       
    66     const PATH_TAG_RENAME    = '/v1/tags/rename';
       
    67     const PATH_BUNDLES       = '/v1/tags/bundles/all';
       
    68     const PATH_BUNDLE_DELETE = '/v1/tags/bundles/delete';
       
    69     const PATH_BUNDLE_ADD    = '/v1/tags/bundles/set';
       
    70     const PATH_DATES         = '/v1/posts/dates';
       
    71     const PATH_POST_DELETE   = '/v1/posts/delete';
       
    72     const PATH_POSTS_GET     = '/v1/posts/get';
       
    73     const PATH_POSTS_ALL     = '/v1/posts/all';
       
    74     const PATH_POSTS_ADD     = '/v1/posts/add';
       
    75     const PATH_POSTS_RECENT  = '/v1/posts/recent';
       
    76 
       
    77     const JSON_URI     = 'http://del.icio.us';
       
    78     const JSON_POSTS   = '/feeds/json/%s/%s';
       
    79     const JSON_TAGS    = '/feeds/json/tags/%s';
       
    80     const JSON_NETWORK = '/feeds/json/network/%s';
       
    81     const JSON_FANS    = '/feeds/json/fans/%s';
       
    82     const JSON_URL     = '/feeds/json/url/data';
       
    83 
       
    84     /**
       
    85      * Zend_Service_Rest instance
       
    86      *
       
    87      * @var Zend_Service_Rest
       
    88      */
       
    89     protected $_rest;
       
    90 
       
    91     /**
       
    92      * Username
       
    93      *
       
    94      * @var string
       
    95      */
       
    96     protected $_authUname;
       
    97 
       
    98     /**
       
    99      * Password
       
   100      *
       
   101      * @var string
       
   102      */
       
   103     protected $_authPass;
       
   104 
       
   105     /**
       
   106      * Microtime of last request
       
   107      *
       
   108      * @var float
       
   109      */
       
   110     protected static $_lastRequestTime = 0;
       
   111 
       
   112     /**
       
   113      * Constructs a new del.icio.us Web Services Client
       
   114      *
       
   115      * @param  string $uname Client username
       
   116      * @param  string $pass  Client password
       
   117      * @return void
       
   118      */
       
   119     public function __construct($uname = null, $pass = null)
       
   120     {
       
   121         $this->_rest = new Zend_Rest_Client();
       
   122         $this->_rest->getHttpClient()->setConfig(array('ssltransport' => 'ssl'));
       
   123         $this->setAuth($uname, $pass);
       
   124     }
       
   125 
       
   126     /**
       
   127      * Set client username and password
       
   128      *
       
   129      * @param  string $uname Client user name
       
   130      * @param  string $pass  Client password
       
   131      * @return Zend_Service_Delicious Provides a fluent interface
       
   132      */
       
   133     public function setAuth($uname, $pass)
       
   134     {
       
   135         $this->_authUname = $uname;
       
   136         $this->_authPass  = $pass;
       
   137 
       
   138         return $this;
       
   139     }
       
   140 
       
   141     /**
       
   142      * Get time of the last update
       
   143      *
       
   144      * @throws Zend_Service_Delicious_Exception
       
   145      * @return Zend_Date
       
   146      */
       
   147     public function getLastUpdate()
       
   148     {
       
   149         $response = $this->makeRequest(self::PATH_UPDATE);
       
   150 
       
   151         $rootNode = $response->documentElement;
       
   152         if ($rootNode && $rootNode->nodeName == 'update') {
       
   153             /**
       
   154              * @todo replace strtotime() with Zend_Date equivalent
       
   155              */
       
   156             return new Zend_Date(strtotime($rootNode->getAttribute('time')));
       
   157         } else {
       
   158             /**
       
   159              * @see Zend_Service_Delicious_Exception
       
   160              */
       
   161             require_once 'Zend/Service/Delicious/Exception.php';
       
   162             throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
       
   163         }
       
   164     }
       
   165 
       
   166     /**
       
   167      * Get all tags, returning an array with tags as keys and number of corresponding posts as values
       
   168      *
       
   169      * @return array list of tags
       
   170      */
       
   171     public function getTags()
       
   172     {
       
   173         $response = $this->makeRequest(self::PATH_TAGS);
       
   174 
       
   175         return self::_xmlResponseToArray($response, 'tags', 'tag', 'tag', 'count');
       
   176     }
       
   177 
       
   178     /**
       
   179      * Rename a tag
       
   180      *
       
   181      * @param  string $old Old tag name
       
   182      * @param  string $new New tag name
       
   183      * @return Zend_Service_Delicious Provides a fluent interface
       
   184      */
       
   185     public function renameTag($old, $new)
       
   186     {
       
   187         $response = $this->makeRequest(self::PATH_TAG_RENAME, array('old' => $old, 'new' => $new));
       
   188 
       
   189         self::_evalXmlResult($response);
       
   190 
       
   191         return $this;
       
   192     }
       
   193 
       
   194     /**
       
   195      * Get all bundles, returning an array with bundles as keys and array of tags as values
       
   196      *
       
   197      * @return array list of bundles
       
   198      */
       
   199     public function getBundles()
       
   200     {
       
   201         $response = $this->makeRequest(self::PATH_BUNDLES);
       
   202 
       
   203         $bundles = self::_xmlResponseToArray($response, 'bundles', 'bundle', 'name', 'tags');
       
   204         foreach ($bundles as &$tags) {
       
   205             $tags = explode(' ', $tags);
       
   206         }
       
   207         return $bundles;
       
   208     }
       
   209 
       
   210     /**
       
   211      * Adds a new bundle
       
   212      *
       
   213      * @param  string $bundle Name of new bundle
       
   214      * @param  array  $tags   Array of tags
       
   215      * @return Zend_Service_Delicious Provides a fluent interface
       
   216      */
       
   217     public function addBundle($bundle, array $tags)
       
   218     {
       
   219         $tags = implode(' ', (array) $tags);
       
   220         $response = $this->makeRequest(self::PATH_BUNDLE_ADD, array('bundle' => $bundle, 'tags' => $tags));
       
   221 
       
   222         self::_evalXmlResult($response);
       
   223 
       
   224         return $this;
       
   225     }
       
   226 
       
   227     /**
       
   228      * Delete a bundle
       
   229      *
       
   230      * @param  string $bundle Name of bundle to be deleted
       
   231      * @return Zend_Service_Delicious Provides a fluent interface
       
   232      */
       
   233     public function deleteBundle($bundle)
       
   234     {
       
   235         $response = $this->makeRequest(self::PATH_BUNDLE_DELETE, array('bundle' => $bundle));
       
   236 
       
   237         self::_evalXmlResult($response);
       
   238 
       
   239         return $this;
       
   240     }
       
   241 
       
   242     /**
       
   243      * Delete a post
       
   244      *
       
   245      * @param  string $url URL of post to be deleted
       
   246      * @return Zend_Service_Delicious Provides a fluent interface
       
   247      */
       
   248     public function deletePost($url)
       
   249     {
       
   250         $response = $this->makeRequest(self::PATH_POST_DELETE, array('url' => $url));
       
   251 
       
   252         self::_evalXmlResult($response);
       
   253 
       
   254         return $this;
       
   255     }
       
   256 
       
   257     /**
       
   258      * Get number of posts by date
       
   259      *
       
   260      * Returns array where keys are dates and values are numbers of posts
       
   261      *
       
   262      * @param  string $tag Optional filtering by tag
       
   263      * @return array list of dates
       
   264      */
       
   265     public function getDates($tag = null)
       
   266     {
       
   267         $parms = array();
       
   268         if ($tag) {
       
   269             $parms['tag'] = $tag;
       
   270         }
       
   271 
       
   272         $response = $this->makeRequest(self::PATH_DATES, $parms);
       
   273 
       
   274         return self::_xmlResponseToArray($response, 'dates', 'date', 'date', 'count');
       
   275     }
       
   276 
       
   277     /**
       
   278      * Get posts matching the arguments
       
   279      *
       
   280      * If no date or url is given, most recent date will be used
       
   281      *
       
   282      * @param  string    $tag Optional filtering by tag
       
   283      * @param  Zend_Date $dt  Optional filtering by date
       
   284      * @param  string    $url Optional filtering by url
       
   285      * @throws Zend_Service_Delicious_Exception
       
   286      * @return Zend_Service_Delicious_PostList
       
   287      */
       
   288     public function getPosts($tag = null, Zend_Date $dt = null, $url = null)
       
   289     {
       
   290         $parms = array();
       
   291         if ($tag) {
       
   292             $parms['tag'] = $tag;
       
   293         }
       
   294         if ($url) {
       
   295             $parms['url'] = $url;
       
   296         }
       
   297         if ($dt) {
       
   298             $parms['dt'] = $dt->get('Y-m-d\TH:i:s\Z');
       
   299         }
       
   300 
       
   301         $response = $this->makeRequest(self::PATH_POSTS_GET, $parms);
       
   302 
       
   303         return $this->_parseXmlPostList($response);
       
   304     }
       
   305 
       
   306     /**
       
   307      * Get all posts
       
   308      *
       
   309      * @param  string $tag Optional filtering by tag
       
   310      * @return Zend_Service_Delicious_PostList
       
   311      */
       
   312     public function getAllPosts($tag = null)
       
   313     {
       
   314         $parms = array();
       
   315         if ($tag) {
       
   316             $parms['tag'] = $tag;
       
   317         }
       
   318 
       
   319         $response = $this->makeRequest(self::PATH_POSTS_ALL, $parms);
       
   320 
       
   321         return $this->_parseXmlPostList($response);
       
   322     }
       
   323 
       
   324     /**
       
   325      * Get recent posts
       
   326      *
       
   327      * @param  string $tag   Optional filtering by tag
       
   328      * @param  string $count Maximum number of posts to be returned (default 15)
       
   329      * @return Zend_Service_Delicious_PostList
       
   330      */
       
   331     public function getRecentPosts($tag = null, $count = 15)
       
   332     {
       
   333         $parms = array();
       
   334         if ($tag) {
       
   335             $parms['tag'] = $tag;
       
   336         }
       
   337         if ($count) {
       
   338             $parms['count'] = $count;
       
   339         }
       
   340 
       
   341         $response = $this->makeRequest(self::PATH_POSTS_RECENT, $parms);
       
   342 
       
   343         return $this->_parseXmlPostList($response);
       
   344     }
       
   345 
       
   346     /**
       
   347      * Create new post
       
   348      *
       
   349      * @return Zend_Service_Delicious_Post
       
   350      */
       
   351     public function createNewPost($title, $url)
       
   352     {
       
   353         return new Zend_Service_Delicious_Post($this, array('title' => $title, 'url' => $url));
       
   354     }
       
   355 
       
   356     /**
       
   357      * Get posts of a user
       
   358      *
       
   359      * @param  string $user  Owner of the posts
       
   360      * @param  int    $count Number of posts (default 15, max. 100)
       
   361      * @param  string $tag   Optional filtering by tag
       
   362      * @return Zend_Service_Delicious_PostList
       
   363      */
       
   364     public function getUserPosts($user, $count = null, $tag = null)
       
   365     {
       
   366         $parms = array();
       
   367         if ($count) {
       
   368             $parms['count'] = $count;
       
   369         }
       
   370 
       
   371         $path = sprintf(self::JSON_POSTS, $user, $tag);
       
   372         $res = $this->makeRequest($path, $parms, 'json');
       
   373 
       
   374         return new Zend_Service_Delicious_PostList($this, $res);
       
   375     }
       
   376 
       
   377     /**
       
   378      * Get tags of a user
       
   379      *
       
   380      * Returned array has tags as keys and number of posts as values
       
   381      *
       
   382      * @param  string $user    Owner of the posts
       
   383      * @param  int    $atleast Include only tags for which there are at least ### number of posts
       
   384      * @param  int    $count   Number of tags to get (default all)
       
   385      * @param  string $sort    Order of returned tags ('alpha' || 'count')
       
   386      * @return array
       
   387      */
       
   388     public function getUserTags($user, $atleast = null, $count = null, $sort = 'alpha')
       
   389     {
       
   390         $parms = array();
       
   391         if ($atleast) {
       
   392             $parms['atleast'] = $atleast;
       
   393         }
       
   394         if ($count) {
       
   395             $parms['count'] = $count;
       
   396         }
       
   397         if ($sort) {
       
   398             $parms['sort'] = $sort;
       
   399         }
       
   400 
       
   401         $path = sprintf(self::JSON_TAGS, $user);
       
   402 
       
   403         return $this->makeRequest($path, $parms, 'json');
       
   404     }
       
   405 
       
   406     /**
       
   407      * Get network of a user
       
   408      *
       
   409      * @param  string $user Owner of the network
       
   410      * @return array
       
   411      */
       
   412     public function getUserNetwork($user)
       
   413     {
       
   414         $path = sprintf(self::JSON_NETWORK, $user);
       
   415         return $this->makeRequest($path, array(), 'json');
       
   416     }
       
   417 
       
   418     /**
       
   419      * Get fans of a user
       
   420      *
       
   421      * @param  string $user Owner of the fans
       
   422      * @return array
       
   423      */
       
   424     public function getUserFans($user)
       
   425     {
       
   426         $path = sprintf(self::JSON_FANS, $user);
       
   427         return $this->makeRequest($path, array(), 'json');
       
   428     }
       
   429 
       
   430     /**
       
   431      * Get details on a particular bookmarked URL
       
   432      *
       
   433      * Returned array contains four elements:
       
   434      *  - hash - md5 hash of URL
       
   435      *  - top_tags - array of tags and their respective usage counts
       
   436      *  - url - URL for which details were returned
       
   437      *  - total_posts - number of users that have bookmarked URL
       
   438      *
       
   439      * If URL hasen't been bookmarked null is returned.
       
   440      *
       
   441      * @param  string $url URL for which to get details
       
   442      * @return array
       
   443      */
       
   444     public function getUrlDetails($url)
       
   445     {
       
   446         $parms = array('hash' => md5($url));
       
   447 
       
   448         $res = $this->makeRequest(self::JSON_URL, $parms, 'json');
       
   449 
       
   450         if(isset($res[0])) {
       
   451             return $res[0];
       
   452         } else {
       
   453             return null;
       
   454         }
       
   455     }
       
   456 
       
   457     /**
       
   458      * Handles all GET requests to a web service
       
   459      *
       
   460      * @param   string $path  Path
       
   461      * @param   array  $parms Array of GET parameters
       
   462      * @param   string $type  Type of a request ("xml"|"json")
       
   463      * @return  mixed  decoded response from web service
       
   464      * @throws  Zend_Service_Delicious_Exception
       
   465      */
       
   466     public function makeRequest($path, array $parms = array(), $type = 'xml')
       
   467     {
       
   468         // if previous request was made less then 1 sec ago
       
   469         // wait until we can make a new request
       
   470         $timeDiff = microtime(true) - self::$_lastRequestTime;
       
   471         if ($timeDiff < 1) {
       
   472             usleep((1 - $timeDiff) * 1000000);
       
   473         }
       
   474 
       
   475         $this->_rest->getHttpClient()->setAuth($this->_authUname, $this->_authPass);
       
   476 
       
   477         switch ($type) {
       
   478             case 'xml':
       
   479                 $this->_rest->setUri(self::API_URI);
       
   480                 break;
       
   481             case 'json':
       
   482                 $parms['raw'] = true;
       
   483                 $this->_rest->setUri(self::JSON_URI);
       
   484                 break;
       
   485             default:
       
   486                 /**
       
   487                  * @see Zend_Service_Delicious_Exception
       
   488                  */
       
   489                 require_once 'Zend/Service/Delicious/Exception.php';
       
   490                 throw new Zend_Service_Delicious_Exception('Unknown request type');
       
   491         }
       
   492 
       
   493         self::$_lastRequestTime = microtime(true);
       
   494         $response = $this->_rest->restGet($path, $parms);
       
   495 
       
   496         if (!$response->isSuccessful()) {
       
   497             /**
       
   498              * @see Zend_Service_Delicious_Exception
       
   499              */
       
   500             require_once 'Zend/Service/Delicious/Exception.php';
       
   501             throw new Zend_Service_Delicious_Exception("Http client reported an error: '{$response->getMessage()}'");
       
   502         }
       
   503 
       
   504         $responseBody = $response->getBody();
       
   505 
       
   506         switch ($type) {
       
   507             case 'xml':
       
   508                 $dom = new DOMDocument() ;
       
   509 
       
   510                 if (!@$dom->loadXML($responseBody)) {
       
   511                     /**
       
   512                      * @see Zend_Service_Delicious_Exception
       
   513                      */
       
   514                     require_once 'Zend/Service/Delicious/Exception.php';
       
   515                     throw new Zend_Service_Delicious_Exception('XML Error');
       
   516                 }
       
   517 
       
   518                 return $dom;
       
   519             case 'json':
       
   520                 return Zend_Json_Decoder::decode($responseBody);
       
   521         }
       
   522     }
       
   523 
       
   524     /**
       
   525      * Transform XML string to array
       
   526      *
       
   527      * @param   DOMDocument $response
       
   528      * @param   string      $root     Name of root tag
       
   529      * @param   string      $child    Name of children tags
       
   530      * @param   string      $attKey   Attribute of child tag to be used as a key
       
   531      * @param   string      $attValue Attribute of child tag to be used as a value
       
   532      * @return  array
       
   533      * @throws  Zend_Service_Delicious_Exception
       
   534      */
       
   535     private static function _xmlResponseToArray(DOMDocument $response, $root, $child, $attKey, $attValue)
       
   536     {
       
   537         $rootNode = $response->documentElement;
       
   538         $arrOut = array();
       
   539 
       
   540         if ($rootNode->nodeName == $root) {
       
   541             $childNodes = $rootNode->childNodes;
       
   542 
       
   543             for ($i = 0; $i < $childNodes->length; $i++) {
       
   544                 $currentNode = $childNodes->item($i);
       
   545                 if ($currentNode->nodeName == $child) {
       
   546                     $arrOut[$currentNode->getAttribute($attKey)] = $currentNode->getAttribute($attValue);
       
   547                 }
       
   548             }
       
   549         } else {
       
   550             /**
       
   551              * @see Zend_Service_Delicious_Exception
       
   552              */
       
   553             require_once 'Zend/Service/Delicious/Exception.php';
       
   554             throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
       
   555         }
       
   556 
       
   557         return $arrOut;
       
   558     }
       
   559 
       
   560     /**
       
   561      * Constructs Zend_Service_Delicious_PostList from XML response
       
   562      *
       
   563      * @param   DOMDocument $response
       
   564      * @return  Zend_Service_Delicious_PostList
       
   565      * @throws  Zend_Service_Delicious_Exception
       
   566      */
       
   567     private function _parseXmlPostList(DOMDocument $response)
       
   568     {
       
   569         $rootNode = $response->documentElement;
       
   570 
       
   571         if ($rootNode->nodeName == 'posts') {
       
   572             return new Zend_Service_Delicious_PostList($this, $rootNode->childNodes);
       
   573         } else {
       
   574             /**
       
   575              * @see Zend_Service_Delicious_Exception
       
   576              */
       
   577             require_once 'Zend/Service/Delicious/Exception.php';
       
   578             throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
       
   579         }
       
   580     }
       
   581 
       
   582     /**
       
   583      * Evaluates XML response
       
   584      *
       
   585      * @param   DOMDocument $response
       
   586      * @return  void
       
   587      * @throws  Zend_Service_Delicious_Exception
       
   588      */
       
   589     private static function _evalXmlResult(DOMDocument $response)
       
   590     {
       
   591         $rootNode = $response->documentElement;
       
   592 
       
   593         if ($rootNode && $rootNode->nodeName == 'result') {
       
   594 
       
   595             if ($rootNode->hasAttribute('code')) {
       
   596                 $strResponse = $rootNode->getAttribute('code');
       
   597             } else {
       
   598                 $strResponse = $rootNode->nodeValue;
       
   599             }
       
   600 
       
   601             if ($strResponse != 'done' && $strResponse != 'ok') {
       
   602                 /**
       
   603                  * @see Zend_Service_Delicious_Exception
       
   604                  */
       
   605                 require_once 'Zend/Service/Delicious/Exception.php';
       
   606                 throw new Zend_Service_Delicious_Exception("del.icio.us web service: '{$strResponse}'");
       
   607             }
       
   608         } else {
       
   609             /**
       
   610              * @see Zend_Service_Delicious_Exception
       
   611              */
       
   612             require_once 'Zend/Service/Delicious/Exception.php';
       
   613             throw new Zend_Service_Delicious_Exception('del.icio.us web service has returned something odd!');
       
   614         }
       
   615     }
       
   616 }