dready92 / PHP-on-Couch

Data Access Library to access a CouchDB server with PHP.
http://dready.byethost31.com/index.php/display/view/192
GNU Lesser General Public License v3.0
246 stars 102 forks source link

Improvements to the exception system #13

Closed MrTrick closed 13 years ago

MrTrick commented 13 years ago

It is in many cases desirable to catch particular error types - For instance to discriminate between document not found and server failure. I have written improvements to the couchException class that try to identify the failure and construct the proper sub-exception. It is of course, easy to extend to other error types, but these are the only ones I've had to handle so far.

In _queryAndTest, on error: throw couchException::factory($response, $method, $url, $parameters); The code that makes it work: /* * customized Exception class for CouchDB errors * this class uses : the Exception message to store the HTTP message sent by the server * the Exception code to store the HTTP status code sent by the server * and adds a method getBody() to fetch the body sent by the server (if any) / class couchException extends Exception { protected static $code_subtypes = array(404=>'couchNotFoundException', 403=>'couchForbiddenException', 401=>'couchUnauthorizedException', 417=>'couchExpectationException'); protected static $status_subtypes = array('Conflict'=>'couchConflictException');

    public static function factory($response, $method, $url, $parameters) {
        //var_dump(compact('response', 'method','url','parameters')); 

        if (is_string($response)) $response = couch::parseRawResponse($response);
        if (!$response) return new couchNoResponseException();

        if (isset($response['status_code']) and isset(self::$code_subtypes[$response['status_code']]))
            return new self::$code_subtypes[$response['status_code']]($response, $method, $url, $parameters);
        elseif (isset($response['status_message']) and isset(self::$status_subtypes[$response['status_message']]))
            return new self::$status_subtypes[$response['status_message']]($response, $method, $url, $parameters);
        else
            return new self($response, $method, $url, $parameters);
    }

    // couchDB response once parsed
    protected $couch_response = array();

    /**
    *class constructor
    *
    * @param string $raw_response HTTP response from the CouchDB server
    */
    function __construct(array $response, $method, $url, $parameters) {
        if (is_string($response)) $response = couch::parseRawResponse($response);
        $this->couch_response = $response;
        if (is_object($this->couch_response['body']) and isset($this->couch_response['body']->reason))
            $message = $this->couch_response['status_message'] . ' - ' . $this->couch_response['body']->reason;
        else
            $message = $this->couch_response['status_message'];
        $message.= " ($method $url ".json_encode($parameters).')';

        parent::__construct($message, isset($this->couch_response['status_code']) ? $this->couch_response['status_code'] : null);
    }

    /**
    * returns CouchDB server response body (if any)
    *
    * if the response's "Content-Type" is set to "application/json", the
    * body is json_decode()d
    *
    * @return string|object|null CouchDB server response
    */
    function getBody() {
        return $this->couch_response['body'];
    }

}

class couchNoResponseException extends couchException {
    function __construct() {
        parent::__construct(array('status_message'=>'No response from server - '));
    }
}
class couchNotFoundException extends couchException {}
class couchForbiddenException extends couchException {}
class couchUnauthorizedException extends couchException {}
class couchExpectationException extends couchException {}
class couchConflictException extends couchException {}
dready92 commented 13 years ago

Hello,

it's a great improvement, thanks ! Applied in commit a4dab93635c7aefbad5c .

regards,

Mickael