1<?php 2/** 3* Part of the Services_Blogging package. 4* 5* PHP version 5 6* 7* @category Services 8* @package Services_Blogging 9* @author Anant Narayanan <anant@php.net> 10* @author Christian Weiske <cweiske@php.net> 11* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 12* @version CVS: $Id$ 13* @link http://pear.php.net/package/Services_Blogging 14*/ 15 16require_once 'Services/Blogging/Driver/Exception.php'; 17require_once 'Services/Blogging/ExtendedDriver.php'; 18require_once 'Services/Blogging/Post.php'; 19require_once 'Services/Blogging/XmlRpc.php'; 20require_once 'XML/RPC.php'; 21 22/** 23* metaWeblog API implementation. 24* http://www.xmlrpc.com/metaWeblogApi 25* http://www.movabletype.org/mt-static/docs/mtmanual_programmatic.html 26* 27* @category Services 28* @package Services_Blogging 29* @author Anant Narayanan <anant@php.net> 30* @author Christian Weiske <cweiske@php.net> 31* @license http://www.gnu.org/copyleft/lesser.html LGPL License 2.1 32* @link http://pear.php.net/package/Services_Blogging 33*/ 34class Services_Blogging_Driver_MetaWeblog extends Services_Blogging_ExtendedDriver 35{ 36 37 /** 38 * Internal list with user data. 39 * @var array 40 */ 41 protected $userdata = array(); 42 43 protected $arSupportedPostProperties = array( 44 Services_Blogging_Post::TITLE, 45 Services_Blogging_Post::CONTENT, 46 Services_Blogging_Post::DATE, 47 Services_Blogging_Post::URL, 48 Services_Blogging_Post::CATEGORIES, 49 ); 50 51 52 53 /** 54 * Constructor for the metaWeblog driver class. 55 * 56 * @param string $user The username of the blog account. 57 * @param string $pass The password of the blog account. 58 * @param string $server The URI of the server to connect to. 59 * @param string $path The path to the XML-RPC server script. 60 * 61 * @throws Services_Blogging_Exception If authentication fails 62 */ 63 public function __construct($user, $pass, $server, $path) 64 { 65 $this->userdata = array( 66 'user' => $user, 67 'pass' => $pass, 68 'server' => $server, 69 'path' => $path, 70 'rpc_user' => new XML_RPC_Value($user, 'string'), 71 'rpc_pass' => new XML_RPC_Value($pass, 'string'), 72 'rpc_blogid'=> new XML_RPC_Value($user, 'string'), 73 ); 74 75 $this->rpc_client = new XML_RPC_Client( 76 $this->userdata['path'], 77 $this->userdata['server'] 78 ); 79 //$this->rpc_client->setDebug(true); 80 }//public function __construct($userid, $pass, $server, $path) 81 82 83 84 /** 85 * Save a new post into the blog. 86 * 87 * @param Services_Blogging_Post $post Post object to put online 88 * 89 * @return void 90 * 91 * @throws Services_Blogging_Exception If an error occured 92 */ 93 public function savePost(Services_Blogging_Post $post) 94 { 95 if ($post->id === null) { 96 //post is new and has no Id => create new one 97 $request = new XML_RPC_Message('metaWeblog.newPost', 98 array( 99 $this->userdata['rpc_blogid'], 100 $this->userdata['rpc_user'], 101 $this->userdata['rpc_pass'], 102 self::convertPostToStruct($post), 103 new XML_RPC_Value(true, 'boolean') 104 ) 105 ); 106 $nPostId = Services_Blogging_XmlRpc::sendRequest( 107 $request, $this->rpc_client 108 ); 109 $post->setId($nPostId); 110 } else { 111 //edit the post; it already exists 112 $request = new XML_RPC_Message('metaWeblog.editPost', 113 array( 114 new XML_RPC_Value($post->id, 'string'), 115 $this->userdata['rpc_user'], 116 $this->userdata['rpc_pass'], 117 self::convertPostToStruct($post), 118 new XML_RPC_Value(true, 'boolean') 119 ) 120 ); 121 Services_Blogging_XmlRpc::sendRequest($request, $this->rpc_client); 122 } 123 }//public function savePost(Services_Blogging_Post $post) 124 125 126 127 /** 128 * The getPost method is intended to retrive a given post as an object of 129 * the Services_Blogging_Post class; given the unique post id which is passed 130 * as a parameter to the function. 131 * 132 * @param string $id The PostID of the post to be retrieved. (As 133 * returned by newPost() defined in 134 * Services_Blogging_driver). 135 * 136 * @return Services_Blogging_Post The elements of the post returned as an 137 * object of the Services_Blogging_Post class. 138 * 139 * @throws Services_Blogging_Exception If the post does not exist 140 */ 141 public function getPost($id) 142 { 143 $request = new XML_RPC_Message('metaWeblog.getPost', 144 array( 145 new XML_RPC_Value($id, 'int'), 146 $this->userdata['rpc_user'], 147 $this->userdata['rpc_pass'], 148 ) 149 ); 150 151 $arData = Services_Blogging_XmlRpc::sendRequest( 152 $request, $this->rpc_client 153 ); 154 return $this->convertStructToPost($arData); 155 }//public function getPost($id) 156 157 158 159 /** 160 * Delete a given post. 161 * The deletePost method in metaWeblog is just 162 * an alias to the deletePost blogger method 163 * 164 * @param mixed $post Services_Blogging_Post object to delete, 165 * or post id (integer) to delete 166 * 167 * @return boolean True if deleted, false if not. 168 */ 169 public function deletePost($post) 170 { 171 if (!($post instanceof Services_Blogging_Post)) { 172 $nPostId = $post; 173 $post = new Services_Blogging_Post(); 174 $post->setId($nPostId); 175 } 176 177 $request = new XML_RPC_Message('metaWeblog.deletePost', 178 array( 179 //dummy API key 180 new XML_RPC_Value('0123456789ABCDEF', 'string'), 181 new XML_RPC_Value($post->id, 'int'), 182 $this->userdata['rpc_user'], 183 $this->userdata['rpc_pass'], 184 new XML_RPC_Value(true, 'boolean') 185 ) 186 ); 187 Services_Blogging_XmlRpc::sendRequest($request, $this->rpc_client); 188 }//public function deletePost($post) 189 190 191 192 /** 193 * Returns an array of recent posts as Services_Blogging_Post objects 194 * 195 * @param int $number The number of posts to be retrieved. 196 * Defaults to 15 197 * 198 * @return Array An array of objects of the Services_Blogging_Post class that 199 * correspond to the number of posts requested. 200 */ 201 public function getRecentPosts($number = 15) 202 { 203 $request = new XML_RPC_Message('metaWeblog.getRecentPosts', 204 array( 205 $this->userdata['rpc_blogid'], 206 $this->userdata['rpc_user'], 207 $this->userdata['rpc_pass'], 208 new XML_RPC_Value($number, 'int') 209 ) 210 ); 211 212 $arData = Services_Blogging_XmlRpc::sendRequest( 213 $request, $this->rpc_client 214 ); 215 216 $arPosts = array(); 217 foreach ($arData as $data) { 218 $post = $this->convertStructToPost($data); 219 $arPosts[$post->id] = $post; 220 } 221 return $arPosts; 222 }//public function getRecentPosts($number = 15) 223 224 225 226 /** 227 * The getRecentPostTitles method is intended to retrieve the given number of 228 * posts titles from a blog. 229 * The posts themselves can be retrieved with getPost() or getRecentPosts(). 230 * 231 * There is no direct getRecentPostTitles method in metaWeblog. So 232 * we internally call getRecentPosts() and strip out ids and titles of 233 * the post. So this method is slow here, because all post data needs 234 * to be transmitted. 235 * 236 * @param int $number The number of posts to be retrieved. 237 * 238 * @return Array An array of int => strings representing the 239 * post ids (key) and their title (value). 240 */ 241 public function getRecentPostTitles($number = 15) 242 { 243 $arPosts = $this->getRecentPosts($number); 244 $arTitles = array(); 245 foreach ($arPosts as $post) { 246 $arTitles[$post->id] = $post->{Services_Blogging_Post::TITLE}; 247 } 248 return $arTitles; 249 }//public function getRecentPostTitles($number = 15) 250 251 252 253 /** 254 * Returns an array of strings thay define 255 * the properties that a post to this blog may 256 * have. 257 * 258 * @param string $strPostType Type of post to create. 259 * 260 * @return array Array of strings 261 * 262 * @see getSupportedPostTypes() 263 */ 264 public function getSupportedPostProperties($strPostType = 'post') 265 { 266 return $this->arSupportedPostProperties; 267 }//public function getSupportedPostProperties(..) 268 269 270 271 /** 272 * Checks if the given property name/id is supported 273 * for this driver. 274 * 275 * @param string $strProperty Property name/id to check 276 * @param string $strPostType Type of post to create. 277 * 278 * @return boolean If the property is supported 279 * 280 * @see getSupportedPostTypes() 281 */ 282 public function isPostPropertySupported($strProperty, $strPostType = 'post') 283 { 284 return in_array($strProperty, $this->arSupportedPostProperties); 285 }//public function isPostPropertySupported(..) 286 287 288 289 /** 290 * Converts a struct returned by the webservice to 291 * a Services_Blogging_Post object 292 * 293 * @param array $arStruct Struct to convert 294 * 295 * @return Services_Blogging_Post Converted post 296 */ 297 protected function convertStructToPost($arStruct) 298 { 299 $post = new Services_Blogging_Post($this); 300 301 $post->{Services_Blogging_Post::CONTENT} = $arStruct['description']; 302 $post->{Services_Blogging_Post::TITLE} = $arStruct['title']; 303 //0123456789012345678 304 //20060514T09:19:33 305 $post->{Services_Blogging_Post::DATE} = mktime( 306 substr($arStruct['dateCreated'], 9, 2), //hour 307 substr($arStruct['dateCreated'], 12, 2), //minute 308 substr($arStruct['dateCreated'], 15, 2), //second 309 substr($arStruct['dateCreated'], 4, 2), //month 310 substr($arStruct['dateCreated'], 6, 2), //day 311 substr($arStruct['dateCreated'], 0, 4) //year 312 ); 313 314 $post->{Services_Blogging_Post::URL} = $arStruct['link']; 315 316 if (!isset($arStruct['categories'])) { 317 $arStruct['categories'] = array(); 318 } 319 $post->{Services_Blogging_Post::CATEGORIES} = $arStruct['categories']; 320 $post->setId($arStruct['postid']); 321 322 return $post; 323 }//protected function convertStructToPost($arStruct) 324 325 326 327 /** 328 * Converts Services_Blogging_Post object to 329 * an XML-RPC struct that can be sent to the server. 330 * 331 * @param Services_Blogging_Post $post Post object to convert 332 * 333 * @return void 334 */ 335 protected function convertPostToStruct($post) 336 { 337 $time = $post->{Services_Blogging_Post::DATE}; 338 if ($time == '' || $time == 0) { 339 $time = time(); 340 } 341 $categories = $post->{Services_Blogging_Post::CATEGORIES}; 342 if (!is_array($categories)) { 343 $categories = array(); 344 } else { 345 $catstr = $categories; 346 $categories = array(); 347 foreach ($catstr as $cat) { 348 $categories[] = new XML_RPC_Value($cat, 'string'); 349 } 350 } 351 352 return new XML_RPC_Value( 353 array( 354 'categories' => new XML_RPC_Value($categories, 'array'), 355 'dateCreated' => new XML_RPC_Value( 356 date('Ymd\\TH:i:s', $time), 'dateTime.iso8601' 357 ), 358 'description' => new XML_RPC_Value( 359 $post->{Services_Blogging_Post::CONTENT}, 'string' 360 ), 361 'title' => new XML_RPC_Value( 362 $post->{Services_Blogging_Post::TITLE}, 'string' 363 ) 364 ), 365 'struct' 366 ); 367 }//protected function convertPostToStruct($post) 368 369}//class Services_Blogging_Driver_MetaWeblog extends Services_Blogging_ExtendedDriver 370?>