DEV

CakePHP2 - Pingサーバを構築してブログの更新通知を受け取る

XML-RPCという仕組みが使われていて、大体weblogUpdates.extendedPingか、weblogUpdates.pingというメソッド名が使われる。IXR_Library.phpというライブラリがあるのでこれを使って作る。飛んでくる情報の最小単位はブログ名とブログURLなので、ブログURLからRSSのURLを取得して、RSSから最新記事のURLとタイトルを取得する。WordPressがweblogUpdates.extendedPingで、アメブロとライブドアが、weblogUpdates.pingだった。wordpressは、array(ブログ名、ブログURL、RSS_URL)できた。RSS URLを取得するのにphpQuery使おうと思ったけど、どうもライブドアだとエラーになるから使うのやめた。あとアメブロのRSSは、新規投稿が1分後くらいにしか反映されないから、CRONで5分後に再チェックするようにした。

<?php
App::uses('AppController', 'Controller');
App::import('Vendor', 'xmlrpc');
//App::import('Vendor', 'phpquery/phpQuery/phpQuery');
class PingController extends AppController
{
public $uses = array('Site');
public function beforeFilter()
{
parent::beforeFilter();
$this->Components->disable('Security');
$this->Auth->allow(array('index'));
Configure::write('debug', 0);
$this->autoRender = false;
}
public function index()
{
$callbacks = array();
$callbacks['weblogUpdates.ping'] = array(&amp;$this, '_updates');
$callbacks['weblogUpdates.extendedPing'] = array(&amp;$this, '_updates_extended');
$callbacks['weblogUpdates.pbping'] = array(&amp;$this, '_pbping');
$this->server = new IXR_Server($callbacks);
}
public function _updates($data)
{
$this->log('weblogUpdates.ping', 'debug');
if(empty($data[1])){
$this->log('Fail to updates.', 'debug');
$this->log($data, 'debug');
return false;
}
if($this->_get_new_post($data[1])){
return true;
}
return false;
}
public function _updates_extended($data)
{
$this->log('weblogUpdates.extendedPing', 'debug');
if(empty($data[1]) || empty($data[2])){
$this->log('Fail to updates_extended.', 'debug');
$this->log($data, 'debug');
return false;
}
if($this->_get_new_post($data[1], $data[2])){
return true;
}
return false;
}
public function _pbping($data)
{
$this->log('weblogUpdates.pbping', 'debug');
$this->log($data);
}
private function _get_new_post($blog_url, $rss_url = null)
{
if(!$site = $this->Site->findByUrlForPing($blog_url)) return false;
if(!$rss_url){
if(!$rss_url = $this->_get_rss_url($blog_url)) return false;
}
if(!$rss = $this->_get_rss($rss_url)) return false;
if(!$this->Site->saveNewPost($rss['url'], $rss['title'], $site['Site']['id'])){
$this->log('Fail to save new post', 'debug');
return false;
}
return true;
}
private function _get_rss_url($blog_url)
{
$pattern = '/type="application\/rss\+xml".+?href="(.+?)"/s';
$html = file_get_contents($blog_url);
if(!preg_match($pattern, $html, $match)){
$this->log('Not Match. '.$blog_url, 'debug');
return null;
}
return $match[1];
}
//private function _get_rss_url($blog_url)
//{
// try{
// $doc = phpQuery::newDocumentFile($blog_url);
// return pq($doc)->find('link[type=application/rss+xml]:first')->attr('href');
// }catch(Exception $e){
// $this->log('Fail to get rss url: '.$e->getCode().'|'.$e->getMessage(), 'debug');
// return null;
// }
//}
private function _get_rss($rss_url)
{
try{
$rss = Xml::build($rss_url);
if(!empty($rss->channel->item[0])){
$item = $rss->channel->item[0];
}elseif(!empty($rss->item[0])){
$item = $rss->item[0];
}
return array(
'url' => (string)$item->link,
'title' => (string)$item->title
);
}catch(Exception $e){
$this->log('Fail to get rss: '.$e->getCode().'|'.$e->getMessage(), 'debug');
return null;
}
}
}

参考: 更新Pingの送信 Pingを送信する! Google ブログ検索の更新通知 API について CakePHP + 更新Ping送信で更新情報サービスを利用する方法 IXRライブラリの使い方 utils/Model/Behavior/PingbackableBehavior.php How-to-create-an-XML-RPC-server-with-CakePHP.rst CakePHP-Wordpress-Datasource/Vendor/IXR_Library.php [42-3] link rel=“alternate” で他言語サイトやモバイル版へ導こう