├── .gitignore ├── tests ├── bootstrap.php └── Network │ └── Tests │ └── Curl │ └── CurlTest.php ├── phpunit.xml ├── LICENSE ├── lib ├── vendor │ └── Symfony │ │ └── Component │ │ └── ClassLoader │ │ ├── LICENSE │ │ ├── MapFileClassLoader.php │ │ ├── DebugUniversalClassLoader.php │ │ ├── ApcUniversalClassLoader.php │ │ ├── ClassCollectionLoader.php │ │ └── UniversalClassLoader.php └── Network │ └── Curl │ └── Curl.php ├── README.md └── examples └── example.php /.gitignore: -------------------------------------------------------------------------------- 1 | *.komodoproject -------------------------------------------------------------------------------- /tests/bootstrap.php: -------------------------------------------------------------------------------- 1 | registerNamespaces(array( 7 | 'Network' => __DIR__.'/../lib' 8 | )); 9 | $loader->register(); 10 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 16 | ./tests/Network/ 17 | 18 | 19 | 20 | 21 | 22 | ./lib/Network/ 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 d.syph.3r@gmail.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /lib/vendor/Symfony/Component/ClassLoader/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2004-2011 Fabien Potencier 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple PHP cURL Library 2 | 3 | ## Overview 4 | 5 | Simple PHP cURL library. Supports requests for GET, POST, PUT, PATCH and DELETE. 6 | 7 | ## Requirements 8 | 9 | * PHP 5.3+ 10 | * cURL 11 | 12 | ## Usage 13 | 14 | ### HTTP GET 15 | 16 | ```php 17 | get('https://api.github.com/users/dsyph3r'); 22 | 23 | $curlInfo = $response['curl_info']; 24 | $status = $response['status']; 25 | $headers = $response['headers']; 26 | $data = json_decode($response['data'], true); 27 | ``` 28 | 29 | ### HTTP POST 30 | 31 | ```php 32 | post('https://api.github.com/user/emails', array('octocat@github.com')); 37 | ``` 38 | 39 | ## Examples 40 | 41 | There are some simple examples using Google Geocoding API and GitHub API in the 42 | examples folder. 43 | 44 | The Symfony ClassLoader Component is used for autoloading, but this could easy be 45 | substituted for another autoloader. 46 | 47 | ## Tests 48 | 49 | Library is tested with PHPUnit 50 | 51 | Run tests with 52 | 53 | ```bash 54 | $ phpunit 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /examples/example.php: -------------------------------------------------------------------------------- 1 | registerNamespaces(array( 17 | 'Network' => __DIR__.'/../lib' 18 | )); 19 | $loader->register(); 20 | 21 | 22 | use Network\Curl\Curl; 23 | 24 | $curl = new Curl(); 25 | 26 | /** 27 | * Google Geocoding API example 28 | * 29 | * @link http://code.google.com/apis/maps/documentation/geocoding/ 30 | */ 31 | echo "Geolocating ...\n"; 32 | $address = 'Millenium Stadium, Cardiff, Wales'; 33 | $response = $curl->get('http://maps.googleapis.com/maps/api/geocode/json?address=' . urlencode($address) . '&sensor=false'); 34 | 35 | $status = $response['status']; 36 | $headers = $response['headers']; 37 | $data = json_decode($response['data'], true); 38 | 39 | echo "\tStatus:\t\t$status\n"; 40 | echo "\tHeaders:\t" . print_r($headers, true) . "\n"; 41 | echo "\tLatLng:\t\t" . $data['results'][0]['geometry']['location']['lat'] . ',' . $data['results'][0]['geometry']['location']['lat'] . "\n"; 42 | echo "\n\n"; 43 | 44 | 45 | /** 46 | * GitHub API example 47 | * 48 | * @link http://developer.github.com/v3/users/ 49 | */ 50 | echo "GitHub ...\n"; 51 | $response = $curl->get('https://api.github.com/users/dsyph3r'); 52 | 53 | $status = $response['status']; 54 | $headers = $response['headers']; 55 | $data = json_decode($response['data'], true); 56 | 57 | echo "\tStatus:\t\t$status\n"; 58 | echo "\tHeaders:\t" . print_r($headers, true) . "\n"; 59 | echo "\tUrl:\t\t" . $data['html_url']. "\n"; 60 | -------------------------------------------------------------------------------- /lib/vendor/Symfony/Component/ClassLoader/MapFileClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * A class loader that uses a mapping file to look up paths. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class MapFileClassLoader 20 | { 21 | private $map = array(); 22 | 23 | /** 24 | * Constructor. 25 | * 26 | * @param string $file Path to class mapping file 27 | */ 28 | public function __construct($file) 29 | { 30 | $this->map = require $file; 31 | } 32 | 33 | /** 34 | * Registers this instance as an autoloader. 35 | * 36 | * @param Boolean $prepend Whether to prepend the autoloader or not 37 | */ 38 | public function register($prepend = false) 39 | { 40 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 41 | } 42 | 43 | /** 44 | * Loads the given class or interface. 45 | * 46 | * @param string $class The name of the class 47 | */ 48 | public function loadClass($class) 49 | { 50 | if ('\\' === $class[0]) { 51 | $class = substr($class, 1); 52 | } 53 | 54 | if (isset($this->map[$class])) { 55 | require $this->map[$class]; 56 | } 57 | } 58 | 59 | /** 60 | * Finds the path to the file where the class is defined. 61 | * 62 | * @param string $class The name of the class 63 | * 64 | * @return string|null The path, if found 65 | */ 66 | public function findFile($class) 67 | { 68 | if ('\\' === $class[0]) { 69 | $class = substr($class, 1); 70 | } 71 | 72 | if (isset($this->map[$class])) { 73 | return $this->map[$class]; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /lib/vendor/Symfony/Component/ClassLoader/DebugUniversalClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * Checks that the class is actually declared in the included file. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class DebugUniversalClassLoader extends UniversalClassLoader 20 | { 21 | /** 22 | * Replaces all regular UniversalClassLoader instances by a DebugUniversalClassLoader ones. 23 | */ 24 | static public function enable() 25 | { 26 | if (!is_array($functions = spl_autoload_functions())) { 27 | return; 28 | } 29 | 30 | foreach ($functions as $function) { 31 | spl_autoload_unregister($function); 32 | } 33 | 34 | foreach ($functions as $function) { 35 | if (is_array($function) && $function[0] instanceof UniversalClassLoader) { 36 | $loader = new static(); 37 | $loader->registerNamespaceFallbacks($function[0]->getNamespaceFallbacks()); 38 | $loader->registerPrefixFallbacks($function[0]->getPrefixFallbacks()); 39 | $loader->registerNamespaces($function[0]->getNamespaces()); 40 | $loader->registerPrefixes($function[0]->getPrefixes()); 41 | 42 | $function[0] = $loader; 43 | } 44 | 45 | spl_autoload_register($function); 46 | } 47 | } 48 | 49 | /** 50 | * {@inheritDoc} 51 | */ 52 | public function loadClass($class) 53 | { 54 | if ($file = $this->findFile($class)) { 55 | require $file; 56 | 57 | if (!class_exists($class, false) && !interface_exists($class, false)) { 58 | throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". You probably have a typo in the namespace or the class name.', $class, $file)); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /lib/vendor/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * ApcUniversalClassLoader implements a "universal" autoloader cached in APC for PHP 5.3. 16 | * 17 | * It is able to load classes that use either: 18 | * 19 | * * The technical interoperability standards for PHP 5.3 namespaces and 20 | * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); 21 | * 22 | * * The PEAR naming convention for classes (http://pear.php.net/). 23 | * 24 | * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be 25 | * looked for in a list of locations to ease the vendoring of a sub-set of 26 | * classes for large projects. 27 | * 28 | * Example usage: 29 | * 30 | * require 'vendor/symfony/src/Symfony/Component/ClassLoader/UniversalClassLoader.php'; 31 | * require 'vendor/symfony/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php'; 32 | * 33 | * use Symfony\Component\ClassLoader\ApcUniversalClassLoader; 34 | * 35 | * $loader = new ApcUniversalClassLoader('apc.prefix.'); 36 | * 37 | * // register classes with namespaces 38 | * $loader->registerNamespaces(array( 39 | * 'Symfony\Component' => __DIR__.'/component', 40 | * 'Symfony' => __DIR__.'/framework', 41 | * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), 42 | * )); 43 | * 44 | * // register a library using the PEAR naming convention 45 | * $loader->registerPrefixes(array( 46 | * 'Swift_' => __DIR__.'/Swift', 47 | * )); 48 | * 49 | * // activate the autoloader 50 | * $loader->register(); 51 | * 52 | * In this example, if you try to use a class in the Symfony\Component 53 | * namespace or one of its children (Symfony\Component\Console for instance), 54 | * the autoloader will first look for the class under the component/ 55 | * directory, and it will then fallback to the framework/ directory if not 56 | * found before giving up. 57 | * 58 | * @author Fabien Potencier 59 | * @author Kris Wallsmith 60 | * 61 | * @api 62 | */ 63 | class ApcUniversalClassLoader extends UniversalClassLoader 64 | { 65 | private $prefix; 66 | 67 | /** 68 | * Constructor. 69 | * 70 | * @param string $prefix A prefix to create a namespace in APC 71 | * 72 | * @api 73 | */ 74 | public function __construct($prefix) 75 | { 76 | if (!extension_loaded('apc')) { 77 | throw new \RuntimeException('Unable to use ApcUniversalClassLoader as APC is not enabled.'); 78 | } 79 | 80 | $this->prefix = $prefix; 81 | } 82 | 83 | /** 84 | * Finds a file by class name while caching lookups to APC. 85 | * 86 | * @param string $class A class name to resolve to file 87 | */ 88 | public function findFile($class) 89 | { 90 | if (false === $file = apc_fetch($this->prefix.$class)) { 91 | apc_store($this->prefix.$class, $file = parent::findFile($class)); 92 | } 93 | 94 | return $file; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /lib/Network/Curl/Curl.php: -------------------------------------------------------------------------------- 1 | 12 | */ 13 | class Curl 14 | { 15 | /** 16 | * Constants for available HTTP methods 17 | */ 18 | const GET = 'GET'; 19 | const POST = 'POST'; 20 | const PUT = 'PUT'; 21 | const PATCH = 'PATCH'; 22 | const DELETE = 'DELETE'; 23 | 24 | /** 25 | * @var cURL handle 26 | */ 27 | private $curl; 28 | 29 | /** 30 | * Create the cURL resource 31 | */ 32 | public function __construct() 33 | { 34 | $this->curl = curl_init(); 35 | } 36 | 37 | /** 38 | * Clean up the cURL handle 39 | */ 40 | public function __destruct() 41 | { 42 | if (is_resource($this->curl)) 43 | { 44 | curl_close($this->curl); 45 | } 46 | } 47 | 48 | /** 49 | * Get the cURL handle 50 | * 51 | * @return cURL cURL handle 52 | */ 53 | public function getCurl() 54 | { 55 | return $this->curl; 56 | } 57 | 58 | /** 59 | * Make a HTTP GET request 60 | * 61 | * @param string $url Full URL including protocol 62 | * @param array $params Any GET params 63 | * @param array $options Additional options for the request 64 | * @return array Response 65 | */ 66 | public function get($url, $params = array(), $options = array()) 67 | { 68 | return $this->request($url, self::GET, $params, $options); 69 | } 70 | 71 | /** 72 | * Make a HTTP POST request 73 | * 74 | * @param string $url Full URL including protocol 75 | * @param array $params Any POST params 76 | * @param array $options Additional options for the request 77 | * @return array Response 78 | */ 79 | public function post($url, $params = array(), $options = array()) 80 | { 81 | return $this->request($url, self::POST, $params, $options); 82 | } 83 | 84 | /** 85 | * Make a HTTP PUT request 86 | * 87 | * @param string $url Full URL including protocol 88 | * @param array $params Any PUT params 89 | * @param array $options Additional options for the request 90 | * @return array Response 91 | */ 92 | public function put($url, $params = array(), $options = array()) 93 | { 94 | return $this->request($url, self::PUT, $params, $options); 95 | } 96 | 97 | /** 98 | * Make a HTTP PATCH request 99 | * 100 | * @param string $url Full URL including protocol 101 | * @param array $params Any PATCH params 102 | * @param array $options Additional options for the request 103 | * @return array Response 104 | */ 105 | public function patch($url, $params = array(), $options = array()) 106 | { 107 | return $this->request($url, self::PATCH, $params, $options); 108 | } 109 | 110 | /** 111 | * Make a HTTP DELETE request 112 | * 113 | * @param string $url Full URL including protocol 114 | * @param array $params Any DELETE params 115 | * @param array $options Additional options for the request 116 | * @return array Response 117 | */ 118 | public function delete($url, $params = array(), $options = array()) 119 | { 120 | return $this->request($url, self::DELETE, $params, $options); 121 | } 122 | 123 | /** 124 | * Make a HTTP request 125 | * 126 | * @param string $url Full URL including protocol 127 | * @param string $method HTTP method 128 | * @param array $params Any params 129 | * @param array $options Additional options for the request 130 | * @return array Response 131 | */ 132 | protected function request($url, $method = self::GET, $params = array(), $options = array()) 133 | { 134 | curl_setopt($this->curl, CURLOPT_HEADER, true); 135 | curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); 136 | 137 | curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); 138 | curl_setopt($this->curl, CURLOPT_URL, $url); 139 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, http_build_query($params)); 140 | 141 | // Check for custom headers 142 | if (isset($options['headers']) && count($options['headers'])) 143 | curl_setopt($curl, CURLOPT_HTTPHEADER, $options['headers']); 144 | 145 | // Check for basic auth 146 | if (isset($options['auth']['type']) && "basic" === $options['auth']['type']) 147 | curl_setopt($curl, CURLOPT_USERPWD, $options['auth']['username'] . ':' . $options['auth']['password']); 148 | 149 | $response = $this->doCurl(); 150 | 151 | // Separate headers and body 152 | $responseSplit = preg_split('/((?:\\r?\\n){2})/', $response['response']); 153 | $responseCount = count($responseSplit); 154 | 155 | $results = array( 156 | 'curl_info' => $response['curl_info'], 157 | 'status' => $response['curl_info']['http_code'], 158 | 'headers' => $this->splitHeaders($responseSplit[$responseCount-2]), 159 | 'data' => $responseSplit[$responseCount-1], 160 | ); 161 | 162 | return $results; 163 | } 164 | 165 | /** 166 | * Split the HTTP headers 167 | * 168 | * @param string $rawHeaders Raw HTTP headers 169 | * @return array Key/Value headers 170 | */ 171 | protected function splitHeaders($rawHeaders) 172 | { 173 | $headers = array(); 174 | 175 | $headerLines = explode("\n", $rawHeaders); 176 | $headers['HTTP'] = array_shift($headerLines); 177 | foreach ($headerLines as $line) { 178 | $header = explode(":", $line, 2); 179 | $headers[trim($header[0])] = trim($header[1]); 180 | } 181 | 182 | return $headers; 183 | } 184 | 185 | /** 186 | * Perform the Curl request 187 | * 188 | * @param cURL Handle $curl The cURL handle to use 189 | * @return array cURL response 190 | */ 191 | protected function doCurl() 192 | { 193 | $response = curl_exec($this->curl); 194 | $curlInfo = curl_getinfo($this->curl); 195 | 196 | $results = array( 197 | 'curl_info' => $curlInfo, 198 | 'response' => $response, 199 | ); 200 | 201 | return $results; 202 | } 203 | 204 | } 205 | 206 | /** 207 | * General Curl Exception 208 | */ 209 | class CurlException extends \Exception 210 | { 211 | } 212 | -------------------------------------------------------------------------------- /tests/Network/Tests/Curl/CurlTest.php: -------------------------------------------------------------------------------- 1 | 11 | */ 12 | class CurlTest extends \PHPUnit_Framework_TestCase 13 | { 14 | public function testGet() 15 | { 16 | $curlMock = $this->getCurlMock(); 17 | 18 | $curlMock->expects($this->once()) 19 | ->method('doCurl') 20 | ->will($this->returnValue($this->getResultRequest())); 21 | 22 | $result = $curlMock->get("http://test.com"); 23 | $this->assertArrayHasKey('status', $result); 24 | $this->assertArrayHasKey('headers', $result); 25 | $this->assertArrayHasKey('data', $result); 26 | } 27 | 28 | public function testPost() 29 | { 30 | $curlMock = $this->getCurlMock(); 31 | 32 | $curlMock->expects($this->once()) 33 | ->method('doCurl') 34 | ->will($this->returnValue($this->getResultRequest())); 35 | 36 | $result = $curlMock->post("http://test.com"); 37 | $this->assertArrayHasKey('status', $result); 38 | $this->assertArrayHasKey('headers', $result); 39 | $this->assertArrayHasKey('data', $result); 40 | } 41 | 42 | public function testPut() 43 | { 44 | $curlMock = $this->getCurlMock(); 45 | 46 | $curlMock->expects($this->once()) 47 | ->method('doCurl') 48 | ->will($this->returnValue($this->getResultRequest())); 49 | 50 | $result = $curlMock->put("http://test.com"); 51 | $this->assertArrayHasKey('status', $result); 52 | $this->assertArrayHasKey('headers', $result); 53 | $this->assertArrayHasKey('data', $result); 54 | } 55 | 56 | public function testPatch() 57 | { 58 | $curlMock = $this->getCurlMock(); 59 | 60 | $curlMock->expects($this->once()) 61 | ->method('doCurl') 62 | ->will($this->returnValue($this->getResultRequest())); 63 | 64 | $result = $curlMock->patch("http://test.com"); 65 | $this->assertArrayHasKey('status', $result); 66 | $this->assertArrayHasKey('headers', $result); 67 | $this->assertArrayHasKey('data', $result); 68 | } 69 | 70 | public function testDelete() 71 | { 72 | $curlMock = $this->getCurlMock(); 73 | 74 | $curlMock->expects($this->once()) 75 | ->method('doCurl') 76 | ->will($this->returnValue($this->getResultRequest())); 77 | 78 | $result = $curlMock->delete("http://test.com"); 79 | $this->assertArrayHasKey('status', $result); 80 | $this->assertArrayHasKey('headers', $result); 81 | $this->assertArrayHasKey('data', $result); 82 | } 83 | 84 | public function test200Headers() 85 | { 86 | // Test 200 OK headers 87 | $curlMock = $this->getCurlMock(); 88 | $curlMock->expects($this->once()) 89 | ->method('doCurl') 90 | ->will($this->returnValue($this->getResultRequest())); 91 | 92 | $result = $curlMock->get("http://test.com"); 93 | 94 | $headers = $result['headers']; 95 | 96 | $this->assertEquals('application/json', $headers['Content-Type']); 97 | $this->assertEquals('Tue, 22 Aug 2011 08:45:15 GMT', $headers['Date']); 98 | } 99 | 100 | /** 101 | * Tests 1 line headers such as a 501 response 102 | */ 103 | public function test501Headers() 104 | { 105 | $response = <<getCurlMock(); 113 | $curlMock->expects($this->once()) 114 | ->method('doCurl') 115 | ->will($this->returnValue(array( 116 | 'curl_info' => array('http_code' => 501), 117 | 'response' => $response 118 | ) 119 | )); 120 | 121 | $result = $curlMock->get("http://test.com"); 122 | 123 | $headers = $result['headers']; 124 | 125 | $this->assertEquals('HTTP/1.1 501 Not Implemented', $headers['HTTP']); 126 | } 127 | 128 | /** 129 | * Tests for 100 Continue header supported by HTTP 1.1 130 | * HTTP 100 should be dropped to return 2nd header status 131 | */ 132 | public function test100Headers() 133 | { 134 | $response = <<getCurlMock(); 147 | $curlMock->expects($this->once()) 148 | ->method('doCurl') 149 | ->will($this->returnValue(array( 150 | 'curl_info' => array('http_code' => 200), 151 | 'response' => $response 152 | ) 153 | )); 154 | 155 | $result = $curlMock->post("http://test.com"); 156 | 157 | $headers = $result['headers']; 158 | 159 | $this->assertEquals('HTTP/1.1 200 OK', $headers['HTTP']); 160 | $this->assertEquals('text/html; charset=UTF-8', $headers['Content-Type']); 161 | } 162 | 163 | /** 164 | * Tests headers than contains multiple whitespace and split correclty 165 | * if on LF is used, ie not CRLF 166 | */ 167 | public function testMultiWhiteSpaceHeaders() 168 | { 169 | $response = <<getCurlMock(); 178 | $curlMock->expects($this->once()) 179 | ->method('doCurl') 180 | ->will($this->returnValue(array( 181 | 'curl_info' => array('http_code' => 200), 182 | 'response' => $response 183 | ) 184 | )); 185 | 186 | $result = $curlMock->post("http://test.com"); 187 | 188 | $headers = $result['headers']; 189 | 190 | $this->assertEquals('HTTP/1.1 200 OK', $headers['HTTP']); 191 | $this->assertEquals('Wed, 21 Sep 2011 12:54:49 GMT', $headers['Date']); 192 | $this->assertEquals('Apache/2.2.17 (Ubuntu)', $headers['Server']); 193 | $this->assertEquals('text/html; charset=UTF-8', $headers['Content-Type']); 194 | } 195 | 196 | public function testData() 197 | { 198 | $curlMock = $this->getCurlMock(); 199 | 200 | $curlMock->expects($this->once()) 201 | ->method('doCurl') 202 | ->will($this->returnValue($this->getResultRequest())); 203 | 204 | $result = $curlMock->get("http://test.com"); 205 | 206 | $this->assertEquals('Hello, World!', $result['data']); 207 | } 208 | 209 | protected function getCurlMock() 210 | { 211 | return $this->getMock('Network\Curl\Curl', array('doCurl')); 212 | } 213 | 214 | protected function getResultRequest() 215 | { 216 | $response = << array('http_code' => 200), 228 | 'response' => $response 229 | ); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /lib/vendor/Symfony/Component/ClassLoader/ClassCollectionLoader.php: -------------------------------------------------------------------------------- 1 | 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * ClassCollectionLoader. 16 | * 17 | * @author Fabien Potencier 18 | */ 19 | class ClassCollectionLoader 20 | { 21 | static private $loaded; 22 | 23 | /** 24 | * Loads a list of classes and caches them in one big file. 25 | * 26 | * @param array $classes An array of classes to load 27 | * @param string $cacheDir A cache directory 28 | * @param string $name The cache name prefix 29 | * @param Boolean $autoReload Whether to flush the cache when the cache is stale or not 30 | * @param Boolean $adaptive Whether to remove already declared classes or not 31 | * @param string $extension File extension of the resulting file 32 | * 33 | * @throws \InvalidArgumentException When class can't be loaded 34 | */ 35 | static public function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php') 36 | { 37 | // each $name can only be loaded once per PHP process 38 | if (isset(self::$loaded[$name])) { 39 | return; 40 | } 41 | 42 | self::$loaded[$name] = true; 43 | 44 | $classes = array_unique($classes); 45 | 46 | if ($adaptive) { 47 | // don't include already declared classes 48 | $classes = array_diff($classes, get_declared_classes(), get_declared_interfaces()); 49 | 50 | // the cache is different depending on which classes are already declared 51 | $name = $name.'-'.substr(md5(implode('|', $classes)), 0, 5); 52 | } 53 | 54 | $cache = $cacheDir.'/'.$name.$extension; 55 | 56 | // auto-reload 57 | $reload = false; 58 | if ($autoReload) { 59 | $metadata = $cacheDir.'/'.$name.$extension.'.meta'; 60 | if (!file_exists($metadata) || !file_exists($cache)) { 61 | $reload = true; 62 | } else { 63 | $time = filemtime($cache); 64 | $meta = unserialize(file_get_contents($metadata)); 65 | 66 | if ($meta[1] != $classes) { 67 | $reload = true; 68 | } else { 69 | foreach ($meta[0] as $resource) { 70 | if (!file_exists($resource) || filemtime($resource) > $time) { 71 | $reload = true; 72 | 73 | break; 74 | } 75 | } 76 | } 77 | } 78 | } 79 | 80 | if (!$reload && file_exists($cache)) { 81 | require_once $cache; 82 | 83 | return; 84 | } 85 | 86 | $files = array(); 87 | $content = ''; 88 | foreach ($classes as $class) { 89 | if (!class_exists($class) && !interface_exists($class)) { 90 | throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class)); 91 | } 92 | 93 | $r = new \ReflectionClass($class); 94 | $files[] = $r->getFileName(); 95 | 96 | $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($r->getFileName())); 97 | 98 | // add namespace declaration for global code 99 | if (!$r->inNamespace()) { 100 | $c = "\nnamespace\n{\n".self::stripComments($c)."\n}\n"; 101 | } else { 102 | $c = self::fixNamespaceDeclarations(' 7 | * 8 | * For the full copyright and license information, please view the LICENSE 9 | * file that was distributed with this source code. 10 | */ 11 | 12 | namespace Symfony\Component\ClassLoader; 13 | 14 | /** 15 | * UniversalClassLoader implements a "universal" autoloader for PHP 5.3. 16 | * 17 | * It is able to load classes that use either: 18 | * 19 | * * The technical interoperability standards for PHP 5.3 namespaces and 20 | * class names (http://groups.google.com/group/php-standards/web/psr-0-final-proposal); 21 | * 22 | * * The PEAR naming convention for classes (http://pear.php.net/). 23 | * 24 | * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be 25 | * looked for in a list of locations to ease the vendoring of a sub-set of 26 | * classes for large projects. 27 | * 28 | * Example usage: 29 | * 30 | * $loader = new UniversalClassLoader(); 31 | * 32 | * // register classes with namespaces 33 | * $loader->registerNamespaces(array( 34 | * 'Symfony\Component' => __DIR__.'/component', 35 | * 'Symfony' => __DIR__.'/framework', 36 | * 'Sensio' => array(__DIR__.'/src', __DIR__.'/vendor'), 37 | * )); 38 | * 39 | * // register a library using the PEAR naming convention 40 | * $loader->registerPrefixes(array( 41 | * 'Swift_' => __DIR__.'/Swift', 42 | * )); 43 | * 44 | * // activate the autoloader 45 | * $loader->register(); 46 | * 47 | * In this example, if you try to use a class in the Symfony\Component 48 | * namespace or one of its children (Symfony\Component\Console for instance), 49 | * the autoloader will first look for the class under the component/ 50 | * directory, and it will then fallback to the framework/ directory if not 51 | * found before giving up. 52 | * 53 | * @author Fabien Potencier 54 | * 55 | * @api 56 | */ 57 | class UniversalClassLoader 58 | { 59 | private $namespaces = array(); 60 | private $prefixes = array(); 61 | private $namespaceFallbacks = array(); 62 | private $prefixFallbacks = array(); 63 | 64 | /** 65 | * Gets the configured namespaces. 66 | * 67 | * @return array A hash with namespaces as keys and directories as values 68 | */ 69 | public function getNamespaces() 70 | { 71 | return $this->namespaces; 72 | } 73 | 74 | /** 75 | * Gets the configured class prefixes. 76 | * 77 | * @return array A hash with class prefixes as keys and directories as values 78 | */ 79 | public function getPrefixes() 80 | { 81 | return $this->prefixes; 82 | } 83 | 84 | /** 85 | * Gets the directory(ies) to use as a fallback for namespaces. 86 | * 87 | * @return array An array of directories 88 | */ 89 | public function getNamespaceFallbacks() 90 | { 91 | return $this->namespaceFallbacks; 92 | } 93 | 94 | /** 95 | * Gets the directory(ies) to use as a fallback for class prefixes. 96 | * 97 | * @return array An array of directories 98 | */ 99 | public function getPrefixFallbacks() 100 | { 101 | return $this->prefixFallbacks; 102 | } 103 | 104 | /** 105 | * Registers the directory to use as a fallback for namespaces. 106 | * 107 | * @param array $dirs An array of directories 108 | * 109 | * @api 110 | */ 111 | public function registerNamespaceFallbacks(array $dirs) 112 | { 113 | $this->namespaceFallbacks = $dirs; 114 | } 115 | 116 | /** 117 | * Registers the directory to use as a fallback for class prefixes. 118 | * 119 | * @param array $dirs An array of directories 120 | * 121 | * @api 122 | */ 123 | public function registerPrefixFallbacks(array $dirs) 124 | { 125 | $this->prefixFallbacks = $dirs; 126 | } 127 | 128 | /** 129 | * Registers an array of namespaces 130 | * 131 | * @param array $namespaces An array of namespaces (namespaces as keys and locations as values) 132 | * 133 | * @api 134 | */ 135 | public function registerNamespaces(array $namespaces) 136 | { 137 | foreach ($namespaces as $namespace => $locations) { 138 | $this->namespaces[$namespace] = (array) $locations; 139 | } 140 | } 141 | 142 | /** 143 | * Registers a namespace. 144 | * 145 | * @param string $namespace The namespace 146 | * @param array|string $paths The location(s) of the namespace 147 | * 148 | * @api 149 | */ 150 | public function registerNamespace($namespace, $paths) 151 | { 152 | $this->namespaces[$namespace] = (array) $paths; 153 | } 154 | 155 | /** 156 | * Registers an array of classes using the PEAR naming convention. 157 | * 158 | * @param array $classes An array of classes (prefixes as keys and locations as values) 159 | * 160 | * @api 161 | */ 162 | public function registerPrefixes(array $classes) 163 | { 164 | foreach ($classes as $prefix => $locations) { 165 | $this->prefixes[$prefix] = (array) $locations; 166 | } 167 | } 168 | 169 | /** 170 | * Registers a set of classes using the PEAR naming convention. 171 | * 172 | * @param string $prefix The classes prefix 173 | * @param array|string $paths The location(s) of the classes 174 | * 175 | * @api 176 | */ 177 | public function registerPrefix($prefix, $paths) 178 | { 179 | $this->prefixes[$prefix] = (array) $paths; 180 | } 181 | 182 | /** 183 | * Registers this instance as an autoloader. 184 | * 185 | * @param Boolean $prepend Whether to prepend the autoloader or not 186 | * 187 | * @api 188 | */ 189 | public function register($prepend = false) 190 | { 191 | spl_autoload_register(array($this, 'loadClass'), true, $prepend); 192 | } 193 | 194 | /** 195 | * Loads the given class or interface. 196 | * 197 | * @param string $class The name of the class 198 | */ 199 | public function loadClass($class) 200 | { 201 | if ($file = $this->findFile($class)) { 202 | require $file; 203 | } 204 | } 205 | 206 | /** 207 | * Finds the path to the file where the class is defined. 208 | * 209 | * @param string $class The name of the class 210 | * 211 | * @return string|null The path, if found 212 | */ 213 | public function findFile($class) 214 | { 215 | if ('\\' == $class[0]) { 216 | $class = substr($class, 1); 217 | } 218 | 219 | if (false !== $pos = strrpos($class, '\\')) { 220 | // namespaced class name 221 | $namespace = substr($class, 0, $pos); 222 | foreach ($this->namespaces as $ns => $dirs) { 223 | foreach ($dirs as $dir) { 224 | if (0 === strpos($namespace, $ns)) { 225 | $className = substr($class, $pos + 1); 226 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $namespace).DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; 227 | if (file_exists($file)) { 228 | return $file; 229 | } 230 | } 231 | } 232 | } 233 | 234 | foreach ($this->namespaceFallbacks as $dir) { 235 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('\\', DIRECTORY_SEPARATOR, $class).'.php'; 236 | if (file_exists($file)) { 237 | return $file; 238 | } 239 | } 240 | } else { 241 | // PEAR-like class name 242 | foreach ($this->prefixes as $prefix => $dirs) { 243 | foreach ($dirs as $dir) { 244 | if (0 === strpos($class, $prefix)) { 245 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; 246 | if (file_exists($file)) { 247 | return $file; 248 | } 249 | } 250 | } 251 | } 252 | 253 | foreach ($this->prefixFallbacks as $dir) { 254 | $file = $dir.DIRECTORY_SEPARATOR.str_replace('_', DIRECTORY_SEPARATOR, $class).'.php'; 255 | if (file_exists($file)) { 256 | return $file; 257 | } 258 | } 259 | } 260 | } 261 | } 262 | --------------------------------------------------------------------------------