Test Failed
Pull Request — main (#64)
by Lode
08:15
created

Document::setJsonapiObject()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
1
<?php
2
3
namespace alsvanzelf\jsonapi;
4
5
use alsvanzelf\jsonapi\exceptions\Exception;
6
use alsvanzelf\jsonapi\exceptions\InputException;
7
use alsvanzelf\jsonapi\helpers\AtMemberManager;
8
use alsvanzelf\jsonapi\helpers\Converter;
9
use alsvanzelf\jsonapi\helpers\HttpStatusCodeManager;
10
use alsvanzelf\jsonapi\helpers\LinksManager;
11
use alsvanzelf\jsonapi\helpers\Validator;
12
use alsvanzelf\jsonapi\interfaces\DocumentInterface;
13
use alsvanzelf\jsonapi\interfaces\ProfileInterface;
14
use alsvanzelf\jsonapi\objects\JsonapiObject;
15
use alsvanzelf\jsonapi\objects\LinkObject;
16
use alsvanzelf\jsonapi\objects\LinksObject;
17
use alsvanzelf\jsonapi\objects\MetaObject;
18
use alsvanzelf\jsonapi\objects\ProfileLinkObject;
19
20
/**
21
 * @see ResourceDocument, CollectionDocument, ErrorsDocument or MetaDocument
22
 */
0 ignored issues
show
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
Coding Style introduced by
Missing @author tag in class comment
Loading history...
Coding Style introduced by
Missing @category tag in class comment
Loading history...
23
abstract class Document implements DocumentInterface, \JsonSerializable {
24
	use AtMemberManager, HttpStatusCodeManager, LinksManager;
25
	
26
	const JSONAPI_VERSION_1_0 = '1.0';
27
	const JSONAPI_VERSION_1_1 = '1.1';
28
	const JSONAPI_VERSION_LATEST = Document::JSONAPI_VERSION_1_1;
29
	
30
	const CONTENT_TYPE_OFFICIAL = 'application/vnd.api+json';
31
	const CONTENT_TYPE_DEBUG    = 'application/json';
32
	const CONTENT_TYPE_JSONP    = 'application/javascript';
33
	
34
	const LEVEL_ROOT     = 'root';
35
	const LEVEL_JSONAPI  = 'jsonapi';
36
	const LEVEL_RESOURCE = 'resource';
37
	
38
	/** @var MetaObject */
39
	protected $meta;
40
	/** @var JsonapiObject */
41
	protected $jsonapi;
42
	/** @var ProfileInterface[] */
43
	protected $profiles = [];
44
	/** @var array */
45
	protected static $defaults = [
46
		/**
47
		 * encode to json with these default options
48
		 */
49
		'encodeOptions' => JSON_UNESCAPED_SLASHES|JSON_UNESCAPED_UNICODE,
50
		
51
		/**
52
		 * encode to human-readable json, useful when debugging
53
		 */
54
		'prettyPrint' => false,
55
		
56
		/**
57
		 * send out the official jsonapi content-type header
58
		 * overwrite for jsonp or if clients don't support it
59
		 */
60
		'contentType' => Document::CONTENT_TYPE_OFFICIAL,
61
		
62
		/**
63
		 * overwrite the array to encode to json
64
		 */
65
		'array' => null,
66
		
67
		/**
68
		 * overwrite the json to send as response
69
		 */
70
		'json' => null,
71
		
72
		/**
73
		 * set the callback for jsonp responses
74
		 */
75
		'jsonpCallback' => null,
76
	];
77
	
78
	public function __construct() {
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function __construct()
Loading history...
79
		$this->setHttpStatusCode(200);
80
		$this->setJsonapiObject(new JsonapiObject());
81
	}
82
	
83
	/**
84
	 * human api
85
	 */
86
	
87
	/**
88
	 * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
89
	 * @param string $href
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
90
	 * @param array  $meta optional, if given a LinkObject is added, otherwise a link string is added
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
91
	 * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT
92
	 * 
93
	 * @throws InputException if the $level is Document::LEVEL_JSONAPI, Document::LEVEL_RESOURCE, or unknown
94
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
95
	public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT) {
96
		if ($level === Document::LEVEL_ROOT) {
97
			if ($this->links === null) {
98
				$this->setLinksObject(new LinksObject());
99
			}
100
			
101
			$this->links->add($key, $href, $meta);
102
		}
103
		elseif ($level === Document::LEVEL_JSONAPI) {
104
			throw new InputException('level "jsonapi" can not be used for links');
105
		}
106
		elseif ($level === Document::LEVEL_RESOURCE) {
107
			throw new InputException('level "resource" can only be set on a ResourceDocument');
108
		}
109
		else {
110
			throw new InputException('unknown level "'.$level.'"');
111
		}
112
	}
113
	
114
	/**
115
	 * set the self link on the document
116
	 * 
117
	 * @param string $href
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
118
	 * @param array  $meta optional, if given a LinkObject is added, otherwise a link string is added
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 1 found
Loading history...
119
	 * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT
120
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
121
	public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_ROOT) {
122
		$this->addLink('self', $href, $meta, $level);
123
	}
124
	
125
	/**
126
	 * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
127
	 * @param mixed  $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
128
	 * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT
129
	 * 
130
	 * @throws InputException if the $level is unknown
131
	 * @throws InputException if the $level is Document::LEVEL_RESOURCE
132
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
133
	public function addMeta($key, $value, $level=Document::LEVEL_ROOT) {
134
		if ($level === Document::LEVEL_ROOT) {
135
			if ($this->meta === null) {
136
				$this->setMetaObject(new MetaObject());
137
			}
138
			
139
			$this->meta->add($key, $value);
140
		}
141
		elseif ($level === Document::LEVEL_JSONAPI) {
142
			if ($this->jsonapi === null) {
143
				$this->setJsonapiObject(new JsonapiObject());
144
			}
145
			
146
			$this->jsonapi->addMeta($key, $value);
147
		}
148
		elseif ($level === Document::LEVEL_RESOURCE) {
149
			throw new InputException('level "resource" can only be set on a ResourceDocument');
150
		}
151
		else {
152
			throw new InputException('unknown level "'.$level.'"');
153
		}
154
	}
155
	
156
	/**
157
	 * spec api
158
	 */
159
	
160
	/**
161
	 * @param MetaObject $metaObject
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
162
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
163
	public function setMetaObject(MetaObject $metaObject) {
164
		$this->meta = $metaObject;
165
	}
166
	
167
	/**
168
	 * @param JsonapiObject $jsonapiObject
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
169
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
170
	public function setJsonapiObject(JsonapiObject $jsonapiObject) {
171
		$this->jsonapi = $jsonapiObject;
172
	}
173
	
174
	/**
175
	 * hide that this api supports jsonapi, or which version it is using
176
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
177
	public function unsetJsonapiObject() {
178
		$this->jsonapi = null;
179
	}
180
	
181
	/**
182
	 * apply a profile which adds the link and sets a correct content-type
183
	 * 
184
	 * note that the rules from the profile are not automatically enforced
185
	 * applying the rules, and applying them correctly, is manual
186
	 * however the $profile could have custom methods to help
187
	 * 
188
	 * @see https://jsonapi.org/format/1.1/#profiles
189
	 * 
190
	 * @param ProfileInterface $profile
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
191
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
192
	public function applyProfile(ProfileInterface $profile) {
193
		$this->profiles[] = $profile;
194
		
195
		if ($this->links === null) {
196
			$this->setLinksObject(new LinksObject());
197
		}
198
		
199
		$link = $profile->getAliasedLink();
200
		if ($link instanceof LinkObject) {
201
			$this->links->appendLinkObject('profile', $link);
202
		}
203
		else {
204
			$this->links->append('profile', $link);
205
		}
206
	}
207
	
208
	/**
209
	 * DocumentInterface
210
	 */
211
	
212
	/**
213
	 * @inheritDoc
214
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
215 View Code Duplication
	public function toArray() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
216
		$array = $this->getAtMembers();
217
		
218
		if ($this->jsonapi !== null && $this->jsonapi->isEmpty() === false) {
219
			$array['jsonapi'] = $this->jsonapi->toArray();
220
		}
221
		if ($this->links !== null && $this->links->isEmpty() === false) {
222
			$array['links'] = $this->links->toArray();
223
		}
224
		if ($this->meta !== null && $this->meta->isEmpty() === false) {
225
			$array['meta'] = $this->meta->toArray();
226
		}
227
		
228
		return $array;
229
	}
230
	
231
	/**
0 ignored issues
show
Coding Style introduced by
Parameter $options should have a doc-comment as per coding-style.
Loading history...
232
	 * @inheritDoc
233
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
234
	public function toJson(array $options=[]) {
235
		$options = array_merge(self::$defaults, $options);
236
		
237
		$array = ($options['array'] !== null) ? $options['array'] : $this->toArray();
238
		
239
		if ($options['prettyPrint']) {
240
			$options['encodeOptions'] |= JSON_PRETTY_PRINT;
241
		}
242
		
243
		$json = json_encode($array, $options['encodeOptions']);
244
		if ($json === false) {
245
			throw new Exception('failed to generate json: '.json_last_error_msg());
246
		}
247
		
248
		if ($options['jsonpCallback'] !== null) {
249
			$json = $options['jsonpCallback'].'('.$json.')';
250
		}
251
		
252
		return $json;
253
	}
254
	
255
	/**
0 ignored issues
show
Coding Style introduced by
Parameter $options should have a doc-comment as per coding-style.
Loading history...
256
	 * @inheritDoc
257
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
258
	public function sendResponse(array $options=[]) {
259
		$options = array_merge(self::$defaults, $options);
260
		
261
		if ($this->httpStatusCode === 204) {
262
			http_response_code($this->httpStatusCode);
263
			return;
264
		}
265
		
266
		$json = ($options['json'] !== null) ? $options['json'] : $this->toJson($options);
267
		
268
		http_response_code($this->httpStatusCode);
269
		
270
		$contentType = Converter::mergeProfilesInContentType($options['contentType'], $this->profiles);
271
		header('Content-Type: '.$contentType);
272
		
273
		echo $json;
274
	}
275
	
276
	/**
277
	 * JsonSerializable
278
	 */
0 ignored issues
show
Coding Style introduced by
There must be no blank lines after the function comment
Loading history...
Coding Style introduced by
Missing @return tag in function comment
Loading history...
279
	
280
	public function jsonSerialize() {
281
		return $this->toArray();
282
	}
283
}
284