diff --git a/src/Httpful/Bootstrap.php b/src/Httpful/Bootstrap.php index 0d40bfd..0056dd9 100644 --- a/src/Httpful/Bootstrap.php +++ b/src/Httpful/Bootstrap.php @@ -82,6 +82,7 @@ public static function registerHandlers() \Httpful\Mime::JSON => new \Httpful\Handlers\JsonHandler(), \Httpful\Mime::XML => new \Httpful\Handlers\XmlHandler(), \Httpful\Mime::FORM => new \Httpful\Handlers\FormHandler(), + \Httpful\Mime::CSV => new \Httpful\Handlers\CsvHandler(), ); foreach ($handlers as $mime => $handler) { @@ -90,4 +91,4 @@ public static function registerHandlers() self::$registered = true; } -} \ No newline at end of file +} diff --git a/src/Httpful/Handlers/CsvHandler.php b/src/Httpful/Handlers/CsvHandler.php new file mode 100644 index 0000000..3359351 --- /dev/null +++ b/src/Httpful/Handlers/CsvHandler.php @@ -0,0 +1,50 @@ + + */ + +namespace Httpful\Handlers; + +class CsvHandler extends MimeHandlerAdapter +{ + /** + * @param string $body + * @return mixed + */ + public function parse($body) + { + if (empty($body)) + return null; + + $parsed = array(); + $fp = fopen('data://text/plain;base64,' . base64_encode($body), 'r'); + while (($r = fgetcsv($fp)) !== FALSE) { + $parsed[] = $r; + } + + if (empty($parsed)) + throw new \Exception("Unable to parse response as CSV"); + return $parsed; + } + + /** + * @param mixed $payload + * @return string + */ + public function serialize($payload) + { + $fp = fopen('php://temp/maxmemory:'. (6*1024*1024), 'r+'); + $i = 0; + foreach ($payload as $fields) { + if($i++ == 0) { + fputcsv($fp, array_keys($fields)); + } + fputcsv($fp, $fields); + } + rewind($fp); + $data = stream_get_contents($fp); + fclose($fp); + return $data; + } +} diff --git a/src/Httpful/Mime.php b/src/Httpful/Mime.php index b8560b3..1a7c456 100644 --- a/src/Httpful/Mime.php +++ b/src/Httpful/Mime.php @@ -16,6 +16,7 @@ class Mime const JS = 'text/javascript'; const HTML = 'text/html'; const YAML = 'application/x-yaml'; + const CSV = 'text/csv'; /** * Map short name for a mime type @@ -32,6 +33,7 @@ class Mime 'js' => self::JS, 'javascript'=> self::JS, 'yaml' => self::YAML, + 'csv' => self::CSV, ); /** @@ -53,4 +55,4 @@ public static function supportsMimeType($short_name) { return array_key_exists($short_name, self::$mimes); } -} \ No newline at end of file +} diff --git a/tests/Httpful/HttpfulTest.php b/tests/Httpful/HttpfulTest.php index 5e269fd..03d7ecb 100644 --- a/tests/Httpful/HttpfulTest.php +++ b/tests/Httpful/HttpfulTest.php @@ -30,6 +30,15 @@ class HttpfulTest extends \PHPUnit_Framework_TestCase Connection: keep-alive Transfer-Encoding: chunked"; const SAMPLE_JSON_RESPONSE = '{"key":"value","object":{"key":"value"},"array":[1,2,3,4]}'; + const SAMPLE_CSV_HEADER = +"HTTP/1.1 200 OK +Content-Type: text/csv +Connection: keep-alive +Transfer-Encoding: chunked"; + const SAMPLE_CSV_RESPONSE = +"Key1,Key2 +Value1,Value2 +\"40.0\",\"Forty\""; const SAMPLE_XML_RESPONSE = '2a stringTRUE'; const SAMPLE_XML_HEADER = "HTTP/1.1 200 OK @@ -75,16 +84,19 @@ function testShortMime() $this->assertEquals(Mime::JSON, Mime::getFullMime('json')); $this->assertEquals(Mime::XML, Mime::getFullMime('xml')); $this->assertEquals(Mime::HTML, Mime::getFullMime('html')); + $this->assertEquals(Mime::CSV, Mime::getFullMime('csv')); // Valid long ones $this->assertEquals(Mime::JSON, Mime::getFullMime(Mime::JSON)); $this->assertEquals(Mime::XML, Mime::getFullMime(Mime::XML)); $this->assertEquals(Mime::HTML, Mime::getFullMime(Mime::HTML)); + $this->assertEquals(Mime::CSV, Mime::getFullMime(Mime::CSV)); // No false positives $this->assertNotEquals(Mime::XML, Mime::getFullMime(Mime::HTML)); $this->assertNotEquals(Mime::JSON, Mime::getFullMime(Mime::XML)); $this->assertNotEquals(Mime::HTML, Mime::getFullMime(Mime::JSON)); + $this->assertNotEquals(Mime::XML, Mime::getFullMime(Mime::CSV)); } function testSettingStrictSsl() @@ -121,6 +133,11 @@ function testSendsAndExpectsType() ->sendsAndExpectsType('application/x-www-form-urlencoded'); $this->assertEquals(Mime::FORM, $r->expected_type); $this->assertEquals(Mime::FORM, $r->content_type); + + $r = Request::init() + ->sendsAndExpectsType(Mime::CSV); + $this->assertEquals(Mime::CSV, $r->expected_type); + $this->assertEquals(Mime::CSV, $r->content_type); } function testIni() @@ -194,6 +211,17 @@ function testXMLResponseParse() $this->assertEquals("a string", (string) $string); } + function testCsvResponseParse() + { + $req = Request::init()->sendsAndExpects(Mime::CSV); + $response = new Response(self::SAMPLE_CSV_RESPONSE, self::SAMPLE_CSV_HEADER, $req); + + $this->assertEquals("Key1", $response->body[0][0]); + $this->assertEquals("Value1", $response->body[1][0]); + $this->assertInternalType('string', $response->body[2][0]); + $this->assertEquals("40.0", $response->body[2][0]); + } + function testParsingContentTypeCharset() { $req = Request::init()->sendsAndExpects(Mime::JSON);