Location: PHPKode > scripts > CodernityDB-PHPClient > codernity-codernitydb-phpclient-beb6f58ff717/codernitydb.php
<?php

/*
Copyright (C) 2011-2012 Codernity.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

class Codernitydb
{

    /**
     * @var string CodernityDB-HTTP host address
     */
    private $_host = 'localhost';

    /**
     * @var string CodernityDB-HTTP port number
     */
    private $_port = 9876;

    /**
     * @var string CodernityDB-HTTP username
     */
    private $_username = null;

    /**
     * @var string CodernityDB-HTTP password
     */
    private $_password = null;

    /**
     * @var boolean tell if curl PHP extension has been detected
     */
    protected $_curl = false;

    /**
     * @var boolean tell if msgpack PHP extension has been detected
     */
    protected $_msgpack = false;

    /**
     * @var string default request content type
     */
    protected $_contentType = 'application/json';

    /**
    * class constructor
    *
    * @param array $config cofiguration data
    */
    public function __construct($config = array())
    {

        if (isset($config['host']))
            $this->_host = $config['host'];
        if (isset($config['port']))
            $this->_host = $config['port'];

        $this->_username = $config['username'];
        $this->_password = $config['password'];

        if (function_exists('curl_init'))
            $this->_curl = true;

        if (function_exists('msgpack_pack'))
            $this->_msgpack = true;

        if($this->_msgpack)
            $this->_contentType = 'application/msgpack';

    }

    /**
     * getting data
     * 
     * @param string $docId document ID
     * @return stdClass { status: [int] response code,
     * doc: [array] decoded response body |
     * details: [array] decoded response body }
     */
    public function get($docId)
    {
        $response = $this->_makeRequest('GET', '/get/id/' . $docId);
        $output = new StdClass;
        $output->status = $response->status;

        if ($response->status == 200) {
            $output->doc = $response->content;
        } else {
            $output->details = $response->content;
        }
        
        return $output;
    }

    /**
     * inserting new document
     *
     * @param array $doc document
     * @return stdClass { status: [int] response code,
     * doc: [array] decoded response body |
     * details: [array] decoded response body }
     */
    public function insert($doc)
    {
        $response = $this->_makeRequest('POST', '/insert', $doc);
        $output = new StdClass;
        $output->status = $response->status;

        if ($response->status == 200) {
            $output->doc = $response->content;
        } else {
            $output->details = $response->content;
        }

        return $output;
    }

    /**
     * update existing document
     * 
     * @param array $doc document
     * @return stdClass { status: [int] response code,
     * doc: [array] decoded response body |
     * details: [array] decoded response body }
     */
    public function update($doc)
    {
        $response = $this->_makeRequest('POST', '/update', $doc);
        $output = new StdClass;
        $output->status = $response->status;

        if ($response->status == 200) {
            $output->doc = $response->content;
        } else {
            $output->details = $response->content;
        }

        return $output;
    }

    /**
     * purging data
     *
     * @param string $docId document id
     * @param string $revId revision id
     * @return stdClass { true | status: [int] response code,
     * details: [array] decoded response body }
     */
    public function delete($docId, $revId)
    {
        $data = array(
            '_id' => $docId,
            '_rev' => $revId
        );

        $response = $this->_makeRequest('POST', '/delete', $data);
        if ($response->status == 200) {
            return $response->content;
        }

        $output = new StdClass;
        $output->details = $response->content;
        return $output;
    }

    /**
     * prepares HTTP request
     */
    private function _makeRequest($method, $url, $data = false)
    {
        if ($this->_curl)
            return $this->_makeCurlRequest($method, $url, $data);
        else
            return $this->_makeSocketRequest($method, $url, $data);
    }

    /**
     * makes CURL request
     */
    private function _makeCurlRequest($method, $url, $data = false)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $this->_host . $url);
        curl_setopt($ch, CURLOPT_PORT, $this->_port);
        curl_setopt(
            $ch,
            CURLOPT_USERPWD,
            $this->_username . ":" . $this->_password
        );
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt(
            $ch,
            CURLOPT_HTTPHEADER,
            array('Content-type: ' . $this->_contentType)
        );

        if (is_object($data) || is_array($data)) {
            $data = $this->_prepareInputData($data);
            curl_setopt($ch, CURLOPT_POST, true);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        }

        $content = curl_exec($ch);

        if ($content === false) {
            throw new Exception(
                'Could not open connection to '
                . $this->_host . ':' . $this->_port . ': '
                . curl_error($ch)
            );
            return false;
        }

        $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);

        $output = new StdClass;
        $output->status = $status;
        $output->content = $this->_prepareOutputData($content);
        return $output;
    }

    /**
     * makes Socket request
     */
    private function _makeSocketRequest($method, $url, $data = false)
    {
        $request = $this->_prepareSocketRequest($method, $url, $data);

        $socket = @fsockopen(
            $this->_host,
            $this->_port,
            $errNum,
            $errString
        );
        
        if (!$socket) {
            throw new Exception(
                'Could not open connection to '
                . $this->_host . ':' . $this->_port . ': '
                . $errString.' (' . $errNum . ')'
            );
            return false;
        }

        fwrite($socket, $request);
        $response = '';
        while (!feof($socket))
            $response .= fgets($socket);

        @fclose($socket);
        return $this->_parseSocketResponse($response);
    }

    /**
     * encodes input data to JSON
     */
    private function _prepareInputData($data)
    {
        if($this->_msgpack)
            $func = 'msgpack_pack';
        else
            $func = 'json_encode';
        
        return $func(
            array(
                'data' => $data
            )
        );
    }

    /**
     * decodes output data from JSON
     */
    private function _prepareOutputData($data)
    {
        if ($this->_msgpack)
            return msgpack_unpack($data);
        else
            return get_object_vars(json_decode($data));
    }

    /**
     * prepares socket request content
     */
    private function _prepareSocketRequest($method, $url, $data)
    {
        $request = "$method $url HTTP/1.0\r\n";
        $request .= "Host: $this->_host \r\n";
        $request .= 'Authorization: Basic ' . base64_encode(
            $this->_username . ':' . $this->_password
        ) . "\r\n";
        $request .= "Accept: ' . $this->_contentType
                . ',text/html,text/plain,*/*\r\n";

        if (is_object($data) || is_array($data)) {
            $data = $this->_prepareInputData($data);
            $request .= "Content-Type: $this->_contentType\r\n";
            $request .= "Content-Length: strlen($data)\r\n\r\n";
            $request .= $data."\r\n";
        } else {
            $request .= "\r\n";
        }
        
        return $request;
    }

    /**
     * returns body and status from socket response
     */
    private function _parseSocketResponse($rawData, $jsonAsArray = FALSE)
    {
        if (!strlen($rawData))
            throw new InvalidArgumentException("no data to parse");
        while (
            !substr_compare(
                $rawData, "HTTP/1.1 100 Continue\r\n\r\n",
                0,
                25
            )
        ) {
            $rawData = substr($rawData, 25);
        }
        $response = new StdClass;
        list($headers, $body) = explode("\r\n\r\n", $rawData, 2);
        $headersArray = explode("\n", $headers);
        $statusLine = reset($headersArray);
        $statusArray = explode(' ', $statusLine, 3);
        $response->status = trim($statusArray[1]);
        if (strlen($body)) {
            $response->content =
                preg_match(
                    '@Content-Type:\s+' . $this->_contentType.'@i',
                    $headers
                )
                ? json_decode($body, $jsonAsArray)
                : $body;
        }
        return $response;
    }

}
Return current item: CodernityDB-PHPClient