mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-05 13:18:22 +08:00
Added Xmlable and implememt Response->xml()
This commit is contained in:
parent
c6f2853758
commit
80c010ee35
@ -14,6 +14,7 @@ namespace Hyperf\HttpServer\Contract;
|
||||
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Jsonable;
|
||||
use Hyperf\Utils\Contracts\Xmlable;
|
||||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
|
||||
|
||||
interface ResponseInterface
|
||||
@ -25,6 +26,14 @@ interface ResponseInterface
|
||||
*/
|
||||
public function json($data): PsrResponseInterface;
|
||||
|
||||
/**
|
||||
* Format data to XML and return data with Content-Type:application/xml header.
|
||||
*
|
||||
* @param array|Arrayable|Xmlable $data
|
||||
* @param string $root The name of the root node.
|
||||
*/
|
||||
public function xml($data, string $root = 'root'): PsrResponseInterface;
|
||||
|
||||
/**
|
||||
* Format data to a string and return data with Content-Type:text/plain header.
|
||||
* @param mixed $data
|
||||
|
@ -22,10 +22,12 @@ use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Context;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Jsonable;
|
||||
use Hyperf\Utils\Contracts\Xmlable;
|
||||
use Hyperf\Utils\Str;
|
||||
use Hyperf\Utils\Traits\Macroable;
|
||||
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use SimpleXMLElement;
|
||||
use Swoole\Http\Response as SwooleResponse;
|
||||
use function get_class;
|
||||
|
||||
@ -72,6 +74,19 @@ class Response extends ServerResponse implements ResponseInterface
|
||||
->withBody(new SwooleStream($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format data to XML and return data with Content-Type:application/xml header.
|
||||
*
|
||||
* @param array|Arrayable|Xmlable $data
|
||||
*/
|
||||
public function xml($data, string $root = 'root'): PsrResponseInterface
|
||||
{
|
||||
$data = $this->toXml($data, $root);
|
||||
return $this->getResponse()
|
||||
->withAddedHeader('content-type', 'application/xml; charset=utf-8')
|
||||
->withBody(new SwooleStream($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Format data to a string and return data with content-type:text/plain header.
|
||||
*
|
||||
@ -361,6 +376,41 @@ class Response extends ServerResponse implements ResponseInterface
|
||||
throw new HttpException('Error encoding response data to JSON.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|Arrayable|Xmlable $data
|
||||
* @param null|mixed $parentNode
|
||||
* @param mixed $root
|
||||
* @throws HttpException when the data encoding error
|
||||
*/
|
||||
protected function toXml($data, $parentNode = null, $root = 'root')
|
||||
{
|
||||
if ($data instanceof Xmlable) {
|
||||
return (string) $data;
|
||||
}
|
||||
if ($data instanceof Arrayable) {
|
||||
$data = $data->toArray();
|
||||
} else {
|
||||
$data = (array) $data;
|
||||
}
|
||||
if ($parentNode === null) {
|
||||
$xml = new SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?>' . "<{$root}></{$root}>");
|
||||
} else {
|
||||
$xml = $parentNode;
|
||||
}
|
||||
foreach ($data as $key => $value) {
|
||||
if (is_array($value)) {
|
||||
$this->toXml($value, $xml->addChild($key));
|
||||
} else {
|
||||
if (is_numeric($key)) {
|
||||
$xml->addChild('item' . $key, (string) $value);
|
||||
} else {
|
||||
$xml->addChild($key, (string) $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return trim($xml->asXML());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the response object from context.
|
||||
*
|
||||
|
@ -15,6 +15,8 @@ namespace HyperfTest\HttpServer;
|
||||
use Hyperf\HttpServer\Response;
|
||||
use Hyperf\Utils\ApplicationContext;
|
||||
use Hyperf\Utils\Context;
|
||||
use Hyperf\Utils\Contracts\Arrayable;
|
||||
use Hyperf\Utils\Contracts\Xmlable;
|
||||
use Mockery;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Container\ContainerInterface;
|
||||
@ -52,4 +54,79 @@ class ResponseTest extends TestCase
|
||||
$this->assertSame(302, $res->getStatusCode());
|
||||
$this->assertSame('http://www.baidu.com', $res->getHeaderLine('Location'));
|
||||
}
|
||||
|
||||
public function testToXml()
|
||||
{
|
||||
$container = Mockery::mock(ContainerInterface::class);
|
||||
ApplicationContext::setContainer($container);
|
||||
|
||||
$psrResponse = new \Hyperf\HttpMessage\Base\Response();
|
||||
Context::set(PsrResponseInterface::class, $psrResponse);
|
||||
|
||||
$response = new Response();
|
||||
$reflectionClass = new \ReflectionClass(Response::class);
|
||||
$reflectionMethod = $reflectionClass->getMethod('toXml');
|
||||
$reflectionMethod->setAccessible(true);
|
||||
|
||||
$expected = '<?xml version="1.0" encoding="utf-8"?>
|
||||
<root><kstring>string</kstring><kint1>1</kint1><kint0>0</kint0><kfloat>0.12345</kfloat><kfalse/><ktrue>1</ktrue><karray><kstring>string</kstring><kint1>1</kint1><kint0>0</kint0><kfloat>0.12345</kfloat><kfalse/><ktrue>1</ktrue></karray></root>';
|
||||
|
||||
// Array
|
||||
$this->assertSame($expected, $reflectionMethod->invoke($response, [
|
||||
'kstring' => 'string',
|
||||
'kint1' => 1,
|
||||
'kint0' => 0,
|
||||
'kfloat' => 0.12345,
|
||||
'kfalse' => false,
|
||||
'ktrue' => true,
|
||||
'karray' => [
|
||||
'kstring' => 'string',
|
||||
'kint1' => 1,
|
||||
'kint0' => 0,
|
||||
'kfloat' => 0.12345,
|
||||
'kfalse' => false,
|
||||
'ktrue' => true,
|
||||
],
|
||||
]));
|
||||
|
||||
// Arrayable
|
||||
$arrayable = new class() implements Arrayable {
|
||||
public function toArray(): array
|
||||
{
|
||||
return [
|
||||
'kstring' => 'string',
|
||||
'kint1' => 1,
|
||||
'kint0' => 0,
|
||||
'kfloat' => 0.12345,
|
||||
'kfalse' => false,
|
||||
'ktrue' => true,
|
||||
'karray' => [
|
||||
'kstring' => 'string',
|
||||
'kint1' => 1,
|
||||
'kint0' => 0,
|
||||
'kfloat' => 0.12345,
|
||||
'kfalse' => false,
|
||||
'ktrue' => true,
|
||||
],
|
||||
];
|
||||
}
|
||||
};
|
||||
$this->assertSame($expected, $reflectionMethod->invoke($response, $arrayable));
|
||||
|
||||
// Xmlable
|
||||
$xmlable = new class($expected) implements Xmlable {
|
||||
private $result;
|
||||
public function __construct($result)
|
||||
{
|
||||
$this->result = $result;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
};
|
||||
$this->assertSame($expected, $reflectionMethod->invoke($response, $xmlable));
|
||||
}
|
||||
|
||||
}
|
||||
|
18
src/utils/src/Contracts/Xmlable.php
Normal file
18
src/utils/src/Contracts/Xmlable.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* This file is part of Hyperf.
|
||||
*
|
||||
* @link https://www.hyperf.io
|
||||
* @document https://doc.hyperf.io
|
||||
* @contact group@hyperf.io
|
||||
* @license https://github.com/hyperf-cloud/hyperf/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
namespace Hyperf\Utils\Contracts;
|
||||
|
||||
interface Xmlable
|
||||
{
|
||||
public function __toString(): string;
|
||||
}
|
Loading…
Reference in New Issue
Block a user