はてなグラフAPI サンプルプログラムのPHP版

PHP版がなかったので、Ruby版を参考に書いてみました。
PHP5.2以上が対象です。

<?php
class HatenaAPIGraph
{
    const DATE_FORMAT = '%Y-%m-%d';
    const GRAPH_API_URL = 'http://graph.hatena.ne.jp/api/';
    const GRAPH_API_DATA_PATH = 'data';
    const GRAPH_API_CONFIG_PATH = 'config';
    
    private $username;
    private $password;
    
    public function __construct($username, $password)
    {
        $this->username = $username;
        $this->password = $password;
    }
    
    public function postData($graphname, $options, $value = null)
    {
        if ($value === null) {
            $params = array('graphname' => $graphname);
            $params = array_merge($params, $options);
        } else {
            $date = $options;
            $params = array(
                'graphname' => $graphname,
                'date'      => $date,
                'value'     => $value,
            );
        }
        
        if ($params['value'] !== null) {
            $params['value'] = (float)$params['value'];
        }
        
        if (isset($params['date'])) {
            $ts = is_int($params['date']) ? $params['date'] : strtotime($params['date']);
            $params['date'] = strftime(self::DATE_FORMAT, $ts);
        }
        
        $res = $this->httpPost(self::GRAPH_API_DATA_PATH, $params);
        if ($res['code'] != 201) {
            throw new HatenaGraphException('request not successed: ' . var_export($res, true));
        }
        
        return $res;
    }
    
    public function getData($graphname, $options = array())
    {
        $params = array(
            'graphname' => $graphname,
            'type'      => 'json',
        );
        $params = array_merge($params, $options);
        
        $res = $this->httpGet(self::GRAPH_API_DATA_PATH, $params);
        if ($res['code'] != 200) {
            throw new HatenaGraphException('request not successed: ' . var_export($res, true));
        }
        
        return json_decode($res['body'], true);
    }
    
    public function getConfig($graphname)
    {
        $params = array(
            'graphname' => $graphname,
            'type'      => 'json',
        );
        
        $res = $this->httpGet(self::GRAPH_API_CONFIG_PATH, $params);
        if ($res['code'] != 200) {
            throw new HatenaGraphException('request not successed: ' . var_export($res, true));
        }
        
        return json_decode($res['body'], true);
    }
    
    public function postConfig($graphname, $options = array())
    {
        $params = array('graphname' => $graphname);
        $params = array_merge($params, $options);
        
        $res = $this->httpPost(self::GRAPH_API_CONFIG_PATH, $params);
        if ($res['code'] != 201) {
            throw new HatenaGraphException('request not successed: ' . var_export($res, true));
        }
        
        return $res;
    }
    
    private function httpPost($path, $params)
    {
        $url = self::GRAPH_API_URL . $path;
        return $this->http($url, $params, 'POST');
    }
    
    private function httpGet($path, $params)
    {
        $url = self::GRAPH_API_URL . $path . '?' . http_build_query($params, '', '&');
        return $this->http($url, array(), 'GET');
    }
    
    private function http($url, $params, $method = 'POST')
    {
        $request_headers = array(
            'Access: application/x.atom+xml, application/xml, text/xml, */*',
            'X-WSSE: ' . $this->wsse($this->username, $this->password),
        );
        
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_AUTOREFERER, true);
        curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
        
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $request_headers);
        
        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params, '', '&'));
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
        
        $response = curl_exec($curl);
        
        if (curl_errno($curl)) {
            throw new HatenaGraphException(curl_error($curl));
        }
        
        $requestInfo = curl_getinfo($curl);
        $res = array(
            'code'  => $requestInfo['http_code'],
            'body'  => $response,
        );
        
        curl_close($curl);
        return $res;
    }
    
    private function wsse($username, $password)
    {
        $created = date('Y-m-d\TH:i:s\Z');
        $nonce = sha1(md5(time()), true);
        $pass_digest = base64_encode(sha1($nonce . $created . $password, true));
        return 'UsernameToken Username="'  .$username . '", PasswordDigest="' . $pass_digest . '", Created="' . $created . '", Nonce="' . base64_encode($nonce) . '"';
    }
}

class HatenaGraphException extends Exception
{
}
<?php
require_once 'HatenaAPIGraph.php';

$graph = HatenaAPIGraph('username', 'password');
$graph->postData('graphname', array('value' => mt_rand(0, 10)));
$graph->postData('graphname', array('date' => date('Y-m-d'), 'value' => mt_rand(0, 10)));

$data = $graph->getData('graphname', array('username' => 'example'));

$config = $graph->getConfig('graphname');
$config['usercolor'] = 'FF00FF';
$graph->postConfig('graphname', $config);