Kohana v3.3.0

This commit is contained in:
Deon George
2013-04-22 14:09:50 +10:00
commit f96694b18f
1280 changed files with 145034 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* [Request_Client_External] Curl driver performs external requests using the
* php-curl extention. This is the default driver for all external requests.
*
* @package Kohana
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
* @uses [PHP cURL](http://php.net/manual/en/book.curl.php)
*/
class Kohana_Request_Client_Curl extends Request_Client_External {
/**
* Sends the HTTP message [Request] to a remote server and processes
* the response.
*
* @param Request $request request to send
* @param Response $request response to send
* @return Response
*/
public function _send_message(Request $request, Response $response)
{
// Response headers
$response_headers = array();
$options = array();
// Set the request method
$options = $this->_set_curl_request_method($request, $options);
// Set the request body. This is perfectly legal in CURL even
// if using a request other than POST. PUT does support this method
// and DOES NOT require writing data to disk before putting it, if
// reading the PHP docs you may have got that impression. SdF
$options[CURLOPT_POSTFIELDS] = $request->body();
// Process headers
if ($headers = $request->headers())
{
$http_headers = array();
foreach ($headers as $key => $value)
{
$http_headers[] = $key.': '.$value;
}
$options[CURLOPT_HTTPHEADER] = $http_headers;
}
// Process cookies
if ($cookies = $request->cookie())
{
$options[CURLOPT_COOKIE] = http_build_query($cookies, NULL, '; ');
}
// Get any exisiting response headers
$response_header = $response->headers();
// Implement the standard parsing parameters
$options[CURLOPT_HEADERFUNCTION] = array($response_header, 'parse_header_string');
$this->_options[CURLOPT_RETURNTRANSFER] = TRUE;
$this->_options[CURLOPT_HEADER] = FALSE;
// Apply any additional options set to
$options += $this->_options;
$uri = $request->uri();
if ($query = $request->query())
{
$uri .= '?'.http_build_query($query, NULL, '&');
}
// Open a new remote connection
$curl = curl_init($uri);
// Set connection options
if ( ! curl_setopt_array($curl, $options))
{
throw new Request_Exception('Failed to set CURL options, check CURL documentation: :url',
array(':url' => 'http://php.net/curl_setopt_array'));
}
// Get the response body
$body = curl_exec($curl);
// Get the response information
$code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($body === FALSE)
{
$error = curl_error($curl);
}
// Close the connection
curl_close($curl);
if (isset($error))
{
throw new Request_Exception('Error fetching remote :url [ status :code ] :error',
array(':url' => $request->url(), ':code' => $code, ':error' => $error));
}
$response->status($code)
->body($body);
return $response;
}
/**
* Sets the appropriate curl request options. Uses the responding options
* for POST and PUT, uses CURLOPT_CUSTOMREQUEST otherwise
* @param Request $request
* @param array $options
* @return array
*/
public function _set_curl_request_method(Request $request, array $options)
{
switch ($request->method()) {
case Request::POST:
$options[CURLOPT_POST] = TRUE;
break;
case Request::PUT:
$options[CURLOPT_PUT] = TRUE;
break;
default:
$options[CURLOPT_CUSTOMREQUEST] = $request->method();
break;
}
return $options;
}
} // End Kohana_Request_Client_Curl

View File

@@ -0,0 +1,207 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* [Request_Client_External] provides a wrapper for all external request
* processing. This class should be extended by all drivers handling external
* requests.
*
* Supported out of the box:
* - Curl (default)
* - PECL HTTP
* - Streams
*
* To select a specific external driver to use as the default driver, set the
* following property within the Application bootstrap. Alternatively, the
* client can be injected into the request object.
*
* @example
*
* // In application bootstrap
* Request_Client_External::$client = 'Request_Client_Stream';
*
* // Add client to request
* $request = Request::factory('http://some.host.tld/foo/bar')
* ->client(Request_Client_External::factory('Request_Client_HTTP));
*
* @package Kohana
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
* @uses [PECL HTTP](http://php.net/manual/en/book.http.php)
*/
abstract class Kohana_Request_Client_External extends Request_Client {
/**
* Use:
* - Request_Client_Curl (default)
* - Request_Client_HTTP
* - Request_Client_Stream
*
* @var string defines the external client to use by default
*/
public static $client = 'Request_Client_Curl';
/**
* Factory method to create a new Request_Client_External object based on
* the client name passed, or defaulting to Request_Client_External::$client
* by default.
*
* Request_Client_External::$client can be set in the application bootstrap.
*
* @param array $params parameters to pass to the client
* @param string $client external client to use
* @return Request_Client_External
* @throws Request_Exception
*/
public static function factory(array $params = array(), $client = NULL)
{
if ($client === NULL)
{
$client = Request_Client_External::$client;
}
$client = new $client($params);
if ( ! $client instanceof Request_Client_External)
{
throw new Request_Exception('Selected client is not a Request_Client_External object.');
}
return $client;
}
/**
* @var array curl options
* @link http://www.php.net/manual/function.curl-setopt
* @link http://www.php.net/manual/http.request.options
*/
protected $_options = array();
/**
* Processes the request, executing the controller action that handles this
* request, determined by the [Route].
*
* 1. Before the controller action is called, the [Controller::before] method
* will be called.
* 2. Next the controller action will be called.
* 3. After the controller action is called, the [Controller::after] method
* will be called.
*
* By default, the output from the controller is captured and returned, and
* no headers are sent.
*
* $request->execute();
*
* @param Request $request A request object
* @param Response $response A response object
* @return Response
* @throws Kohana_Exception
* @uses [Kohana::$profiling]
* @uses [Profiler]
*/
public function execute_request(Request $request, Response $response)
{
if (Kohana::$profiling)
{
// Set the benchmark name
$benchmark = '"'.$request->uri().'"';
if ($request !== Request::$initial AND Request::$current)
{
// Add the parent request uri
$benchmark .= ' « "'.Request::$current->uri().'"';
}
// Start benchmarking
$benchmark = Profiler::start('Requests', $benchmark);
}
// Store the current active request and replace current with new request
$previous = Request::$current;
Request::$current = $request;
// Resolve the POST fields
if ($post = $request->post())
{
$request->body(http_build_query($post, NULL, '&'))
->headers('content-type', 'application/x-www-form-urlencoded');
}
// If Kohana expose, set the user-agent
if (Kohana::$expose)
{
$request->headers('user-agent', Kohana::version());
}
try
{
$response = $this->_send_message($request, $response);
}
catch (Exception $e)
{
// Restore the previous request
Request::$current = $previous;
if (isset($benchmark))
{
// Delete the benchmark, it is invalid
Profiler::delete($benchmark);
}
// Re-throw the exception
throw $e;
}
// Restore the previous request
Request::$current = $previous;
if (isset($benchmark))
{
// Stop the benchmark
Profiler::stop($benchmark);
}
// Return the response
return $response;
}
/**
* Set and get options for this request.
*
* @param mixed $key Option name, or array of options
* @param mixed $value Option value
* @return mixed
* @return Request_Client_External
*/
public function options($key = NULL, $value = NULL)
{
if ($key === NULL)
return $this->_options;
if (is_array($key))
{
$this->_options = $key;
}
elseif ($value === NULL)
{
return Arr::get($this->_options, $key);
}
else
{
$this->_options[$key] = $value;
}
return $this;
}
/**
* Sends the HTTP message [Request] to a remote server and processes
* the response.
*
* @param Request $request Request to send
* @param Response $response Response to send
* @return Response
*/
abstract protected function _send_message(Request $request, Response $response);
} // End Kohana_Request_Client_External

View File

@@ -0,0 +1,121 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* [Request_Client_External] HTTP driver performs external requests using the
* php-http extention. To use this driver, ensure the following is completed
* before executing an external request- ideally in the application bootstrap.
*
* @example
*
* // In application bootstrap
* Request_Client_External::$client = 'Request_Client_HTTP';
*
* @package Kohana
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
* @uses [PECL HTTP](http://php.net/manual/en/book.http.php)
*/
class Kohana_Request_Client_HTTP extends Request_Client_External {
/**
* Creates a new `Request_Client` object,
* allows for dependency injection.
*
* @param array $params Params
* @throws Request_Exception
*/
public function __construct(array $params = array())
{
// Check that PECL HTTP supports requests
if ( ! http_support(HTTP_SUPPORT_REQUESTS))
{
throw new Request_Exception('Need HTTP request support!');
}
// Carry on
parent::__construct($params);
}
/**
* @var array curl options
* @link http://www.php.net/manual/function.curl-setopt
*/
protected $_options = array();
/**
* Sends the HTTP message [Request] to a remote server and processes
* the response.
*
* @param Request $request request to send
* @param Response $request response to send
* @return Response
*/
public function _send_message(Request $request, Response $response)
{
$http_method_mapping = array(
HTTP_Request::GET => HTTPRequest::METH_GET,
HTTP_Request::HEAD => HTTPRequest::METH_HEAD,
HTTP_Request::POST => HTTPRequest::METH_POST,
HTTP_Request::PUT => HTTPRequest::METH_PUT,
HTTP_Request::DELETE => HTTPRequest::METH_DELETE,
HTTP_Request::OPTIONS => HTTPRequest::METH_OPTIONS,
HTTP_Request::TRACE => HTTPRequest::METH_TRACE,
HTTP_Request::CONNECT => HTTPRequest::METH_CONNECT,
);
// Create an http request object
$http_request = new HTTPRequest($request->uri(), $http_method_mapping[$request->method()]);
if ($this->_options)
{
// Set custom options
$http_request->setOptions($this->_options);
}
// Set headers
$http_request->setHeaders($request->headers()->getArrayCopy());
// Set cookies
$http_request->setCookies($request->cookie());
// Set query data (?foo=bar&bar=foo)
$http_request->setQueryData($request->query());
// Set the body
if ($request->method() == HTTP_Request::PUT)
{
$http_request->addPutData($request->body());
}
else
{
$http_request->setBody($request->body());
}
try
{
$http_request->send();
}
catch (HTTPRequestException $e)
{
throw new Request_Exception($e->getMessage());
}
catch (HTTPMalformedHeaderException $e)
{
throw new Request_Exception($e->getMessage());
}
catch (HTTPEncodingException $e)
{
throw new Request_Exception($e->getMessage());
}
// Build the response
$response->status($http_request->getResponseCode())
->headers($http_request->getResponseHeader())
->cookie($http_request->getResponseCookies())
->body($http_request->getResponseBody());
return $response;
}
} // End Kohana_Request_Client_HTTP

View File

@@ -0,0 +1,128 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* Request Client for internal execution
*
* @package Kohana
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
* @since 3.1.0
*/
class Kohana_Request_Client_Internal extends Request_Client {
/**
* @var array
*/
protected $_previous_environment;
/**
* Processes the request, executing the controller action that handles this
* request, determined by the [Route].
*
* $request->execute();
*
* @param Request $request
* @return Response
* @throws Kohana_Exception
* @uses [Kohana::$profiling]
* @uses [Profiler]
*/
public function execute_request(Request $request, Response $response)
{
// Create the class prefix
$prefix = 'Controller_';
// Directory
$directory = $request->directory();
// Controller
$controller = $request->controller();
if ($directory)
{
// Add the directory name to the class prefix
$prefix .= str_replace(array('\\', '/'), '_', trim($directory, '/')).'_';
}
if (Kohana::$profiling)
{
// Set the benchmark name
$benchmark = '"'.$request->uri().'"';
if ($request !== Request::$initial AND Request::$current)
{
// Add the parent request uri
$benchmark .= ' « "'.Request::$current->uri().'"';
}
// Start benchmarking
$benchmark = Profiler::start('Requests', $benchmark);
}
// Store the currently active request
$previous = Request::$current;
// Change the current request to this request
Request::$current = $request;
// Is this the initial request
$initial_request = ($request === Request::$initial);
try
{
if ( ! class_exists($prefix.$controller))
{
throw HTTP_Exception::factory(404,
'The requested URL :uri was not found on this server.',
array(':uri' => $request->uri())
)->request($request);
}
// Load the controller using reflection
$class = new ReflectionClass($prefix.$controller);
if ($class->isAbstract())
{
throw new Kohana_Exception(
'Cannot create instances of abstract :controller',
array(':controller' => $prefix.$controller)
);
}
// Create a new instance of the controller
$controller = $class->newInstance($request, $response);
// Run the controller's execute() method
$response = $class->getMethod('execute')->invoke($controller);
if ( ! $response instanceof Response)
{
// Controller failed to return a Response.
throw new Kohana_Exception('Controller failed to return a Response');
}
}
catch (HTTP_Exception $e)
{
// Get the response via the Exception
$response = $e->get_response();
}
catch (Exception $e)
{
// Generate an appropriate Response object
$response = Kohana_Exception::_handler($e);
}
// Restore the previous request
Request::$current = $previous;
if (isset($benchmark))
{
// Stop the benchmark
Profiler::stop($benchmark);
}
// Return the response
return $response;
}
} // End Kohana_Request_Client_Internal

View File

@@ -0,0 +1,10 @@
<?php
defined('SYSPATH') OR die('No direct script access.');
/**
* @package Kohana
* @category Exceptions
* @author Kohana Team
* @copyright (c) 2009-2012 Kohana Team
* @license http://kohanaframework.org/license
*/
class Kohana_Request_Client_Recursion_Exception extends Kohana_Exception {}

View File

@@ -0,0 +1,109 @@
<?php defined('SYSPATH') OR die('No direct script access.');
/**
* [Request_Client_External] Stream driver performs external requests using php
* sockets. To use this driver, ensure the following is completed
* before executing an external request- ideally in the application bootstrap.
*
* @example
*
* // In application bootstrap
* Request_Client_External::$client = 'Request_Client_Stream';
*
* @package Kohana
* @category Base
* @author Kohana Team
* @copyright (c) 2008-2012 Kohana Team
* @license http://kohanaframework.org/license
* @uses [PHP Streams](http://php.net/manual/en/book.stream.php)
*/
class Kohana_Request_Client_Stream extends Request_Client_External {
/**
* Sends the HTTP message [Request] to a remote server and processes
* the response.
*
* @param Request $request request to send
* @param Response $request response to send
* @return Response
* @uses [PHP cURL](http://php.net/manual/en/book.curl.php)
*/
public function _send_message(Request $request, Response $response)
{
// Calculate stream mode
$mode = ($request->method() === HTTP_Request::GET) ? 'r' : 'r+';
// Process cookies
if ($cookies = $request->cookie())
{
$request->headers('cookie', http_build_query($cookies, NULL, '; '));
}
// Get the message body
$body = $request->body();
if (is_resource($body))
{
$body = stream_get_contents($body);
}
// Set the content length
$request->headers('content-length', (string) strlen($body));
list($protocol) = explode('/', $request->protocol());
// Create the context
$options = array(
strtolower($protocol) => array(
'method' => $request->method(),
'header' => (string) $request->headers(),
'content' => $body
)
);
// Create the context stream
$context = stream_context_create($options);
stream_context_set_option($context, $this->_options);
$uri = $request->uri();
if ($query = $request->query())
{
$uri .= '?'.http_build_query($query, NULL, '&');
}
$stream = fopen($uri, $mode, FALSE, $context);
$meta_data = stream_get_meta_data($stream);
// Get the HTTP response code
$http_response = array_shift($meta_data['wrapper_data']);
if (preg_match_all('/(\w+\/\d\.\d) (\d{3})/', $http_response, $matches) !== FALSE)
{
$protocol = $matches[1][0];
$status = (int) $matches[2][0];
}
else
{
$protocol = NULL;
$status = NULL;
}
// Get any exisiting response headers
$response_header = $response->headers();
// Process headers
array_map(array($response_header, 'parse_header_string'), array(), $meta_data['wrapper_data']);
$response->status($status)
->protocol($protocol)
->body(stream_get_contents($stream));
// Close the stream after use
fclose($stream);
return $response;
}
} // End Kohana_Request_Client_Stream