Skip to content

Commit b322ab2

Browse files
authored
Merge pull request #286 from alleyinteractive/assert-json
Assert Json Structure and other testing improvements
2 parents 4b3c6fd + 15620d1 commit b322ab2

File tree

7 files changed

+615
-116
lines changed

7 files changed

+615
-116
lines changed

src/mantle/http/class-response.php

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,100 @@
77

88
namespace Mantle\Http;
99

10+
use ArrayObject;
11+
use InvalidArgumentException;
12+
use JsonSerializable;
13+
use Mantle\Contracts\Support\Arrayable;
14+
use Mantle\Contracts\Support\Htmlable;
15+
use Mantle\Contracts\Support\Jsonable;
1016
use Symfony\Component\HttpFoundation\Response as HttpFoundationResponse;
17+
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
1118

1219
/**
1320
* HTTP Response
1421
*/
15-
class Response extends HttpFoundationResponse { }
22+
class Response extends HttpFoundationResponse {
23+
/**
24+
* The original content of the response.
25+
*
26+
* @var mixed
27+
*/
28+
public $original;
29+
30+
/**
31+
* Constructor.
32+
*
33+
* @param mixed $content Response content.
34+
* @param int $status Response status code.
35+
* @param array<string, string> $headers Response headers.
36+
*
37+
* @throws InvalidArgumentException When the HTTP status code is not valid.
38+
*/
39+
public function __construct( $content = '', int $status = 200, array $headers = [] ) {
40+
$this->headers = new ResponseHeaderBag( $headers );
41+
$this->setContent( $content );
42+
$this->setStatusCode( $status );
43+
$this->setProtocolVersion( '1.0' );
44+
}
45+
46+
/**
47+
* Set the content on the response.
48+
*
49+
* @param mixed $content
50+
* @return $this
51+
*
52+
* @throws InvalidArgumentException When the HTTP status code is not valid.
53+
*/
54+
public function setContent( $content ) {
55+
$this->original = $content;
56+
57+
// If the content is "JSONable" we will set the appropriate header and convert
58+
// the content to JSON. This is useful when returning something like models
59+
// from routes that will be automatically transformed to their JSON form.
60+
if ( $this->should_be_json( $content ) ) {
61+
$this->headers->set( 'Content-Type', 'application/json' );
62+
63+
$content = $this->morph_to_json( $content );
64+
65+
if ( false === $content ) {
66+
throw new InvalidArgumentException( json_last_error_msg() );
67+
}
68+
} elseif ( $content instanceof Htmlable ) {
69+
$content = $content->to_html();
70+
}
71+
72+
parent::setContent( $content );
73+
74+
return $this;
75+
}
76+
77+
/**
78+
* Determine if the given content should be turned into JSON.
79+
*
80+
* @param Arrayable|Jsonable|ArrayObject|JsonSerializable|array|mixed $content
81+
* @return bool
82+
*/
83+
protected function should_be_json( $content ): bool {
84+
return $content instanceof Arrayable ||
85+
$content instanceof Jsonable ||
86+
$content instanceof ArrayObject ||
87+
$content instanceof JsonSerializable ||
88+
is_array( $content );
89+
}
90+
91+
/**
92+
* Morph the given content into JSON.
93+
*
94+
* @param Arrayable|Jsonable|ArrayObject|JsonSerializable|array|mixed $content
95+
* @return string
96+
*/
97+
protected function morph_to_json( $content ) {
98+
if ( $content instanceof Jsonable ) {
99+
return $content->to_json();
100+
} elseif ( $content instanceof Arrayable ) {
101+
return json_encode( $content->to_array() ); // phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
102+
}
103+
104+
return json_encode( $content ); // phpcs:ignore WordPress.WP.AlternativeFunctions.json_encode_json_encode
105+
}
106+
}

0 commit comments

Comments
 (0)