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

ResourceDocument::toArray()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
cc 3
nc 2
nop 0
1
<?php
2
3
namespace alsvanzelf\jsonapi;
4
5
use alsvanzelf\jsonapi\CollectionDocument;
6
use alsvanzelf\jsonapi\DataDocument;
7
use alsvanzelf\jsonapi\Document;
8
use alsvanzelf\jsonapi\exceptions\Exception;
9
use alsvanzelf\jsonapi\exceptions\InputException;
10
use alsvanzelf\jsonapi\helpers\Converter;
11
use alsvanzelf\jsonapi\interfaces\RecursiveResourceContainerInterface;
12
use alsvanzelf\jsonapi\interfaces\ResourceInterface;
13
use alsvanzelf\jsonapi\objects\AttributesObject;
14
use alsvanzelf\jsonapi\objects\RelationshipObject;
15
use alsvanzelf\jsonapi\objects\RelationshipsObject;
16
use alsvanzelf\jsonapi\objects\ResourceIdentifierObject;
17
use alsvanzelf\jsonapi\objects\ResourceObject;
18
19
/**
20
 * this document represents an entity or other resource of the api
21
 * it can contain other Resources as relationships
22
 * a CollectionDocument should be used if the primary Resource is (or can be) a set
23
 */
0 ignored issues
show
Coding Style introduced by
Missing @package tag in class comment
Loading history...
Coding Style introduced by
Missing @author 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 @category tag in class comment
Loading history...
24
class ResourceDocument extends DataDocument implements ResourceInterface {
25
	/** @var ResourceIdentifierObject|ResourceObject */
26
	protected $resource;
27
	/** @var array */
28
	protected static $defaults = [
29
		/**
30
		 * add resources inside relationships to /included when adding resources to the collection
31
		 */
32
		'includeContainedResources' => true,
33
	];
34
	
35
	/**
36
	 * @note $type and $id are optional to pass during construction
37
	 *       however they are required for a valid ResourceDocument
38
	 *       so use ->setPrimaryResource() if not passing them during construction
39
	 * 
40
	 * @param string     $type optional
41
	 * @param string|int $id   optional
42
	 */
43
	public function __construct($type=null, $id=null) {
44
		parent::__construct();
45
		
46
		$this->setPrimaryResource(new ResourceObject($type, $id));
47
	}
48
	
49
	/**
50
	 * human api
51
	 */
52
	
53
	/**
54
	 * @param  array      $attributes
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
55
	 * @param  string     $type       optional
56
	 * @param  string|int $id         optional
57
	 * @param  array      $options    optional {@see ResourceDocument::$defaults} {@see ResourceObject::$defaults}
58
	 * @return ResourceDocument
59
	 */
60
	public static function fromArray(array $attributes, $type=null, $id=null, array $options=[]) {
61
		$resourceDocument = new self();
62
		$resourceDocument->setPrimaryResource(ResourceObject::fromArray($attributes, $type, $id, $options), $options);
63
		
64
		return $resourceDocument;
65
	}
66
	
67
	/**
68
	 * @param  object     $attributes
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
69
	 * @param  string     $type       optional
70
	 * @param  string|int $id         optional
71
	 * @param  array      $options    optional {@see ResourceDocument::$defaults}
72
	 * @return ResourceDocument
73
	 */
74
	public static function fromObject($attributes, $type=null, $id=null, array $options=[]) {
75
		$array = Converter::objectToArray($attributes);
76
		
77
		return self::fromArray($array, $type, $id, $options);
78
	}
79
	
80
	/**
81
	 * add key-value pairs to the resource's attributes
82
	 * 
83
	 * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
84
	 * @param mixed  $value   objects will be converted using `get_object_vars()`
85
	 * @param array  $options optional {@see ResourceDocument::$defaults}
86
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
87
	public function add($key, $value, array $options=[]) {
88
		$this->ensureResourceObject();
89
		
90
		$this->resource->add($key, $value, $options);
0 ignored issues
show
Bug introduced by
The method add does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
91
	}
92
	
93
	/**
94
	 * add a relation to the resource
95
	 * 
96
	 * adds included resources if found inside the relation, unless $options['includeContainedResources'] is set to false
97
	 * 
98
	 * @param string  $key
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter type; 2 found
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
99
	 * @param mixed   $relation ResourceInterface | ResourceInterface[] | CollectionDocument
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 3 found
Loading history...
100
	 * @param array   $links    optional
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 3 found
Loading history...
101
	 * @param array   $meta     optional
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 3 found
Loading history...
102
	 * @param array   $options  optional {@see ResourceDocument::$defaults}
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter type; 3 found
Loading history...
103
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
104
	public function addRelationship($key, $relation, array $links=[], array $meta=[], array $options=[]) {
105
		$this->ensureResourceObject();
106
		
107
		$options = array_merge(self::$defaults, $options);
108
		
109
		$relationshipObject = $this->resource->addRelationship($key, $relation, $links, $meta);
0 ignored issues
show
Bug introduced by
The method addRelationship does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
110
		
111
		if ($options['includeContainedResources']) {
112
			$this->addIncludedResourceObject(...$relationshipObject->getNestedContainedResourceObjects());
113
		}
114
	}
115
	
116
	/**
117
	 * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
118
	 * @param string $href
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
119
	 * @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...
120
	 * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT
121
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
122 View Code Duplication
	public function addLink($key, $href, array $meta=[], $level=Document::LEVEL_ROOT) {
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...
123
		$this->ensureResourceObject();
124
		
125
		if ($level === Document::LEVEL_RESOURCE) {
126
			$this->resource->addLink($key, $href, $meta);
0 ignored issues
show
Bug introduced by
The method addLink does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
127
		}
128
		else {
129
			parent::addLink($key, $href, $meta, $level);
130
		}
131
	}
132
	
133
	/**
0 ignored issues
show
Coding Style introduced by
Parameter $level should have a doc-comment as per coding-style.
Loading history...
134
	 * set the self link on the resource
135
	 * 
136
	 * @param string $href
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
137
	 * @param array  $meta optional
138
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
139 View Code Duplication
	public function setSelfLink($href, array $meta=[], $level=Document::LEVEL_RESOURCE) {
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...
140
		$this->ensureResourceObject();
141
		
142
		if ($level === Document::LEVEL_RESOURCE) {
143
			$this->resource->setSelfLink($href, $meta);
0 ignored issues
show
Bug introduced by
The method setSelfLink does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
144
		}
145
		else {
146
			parent::setSelfLink($href, $meta, $level);
147
		}
148
	}
149
	
150
	/**
151
	 * @param string $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
152
	 * @param mixed  $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
153
	 * @param string $level one of the Document::LEVEL_* constants, optional, defaults to Document::LEVEL_ROOT
154
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
155
	public function addMeta($key, $value, $level=Document::LEVEL_ROOT) {
156
		if ($level === Document::LEVEL_RESOURCE) {
157
			$this->resource->addMeta($key, $value);
158
		}
159
		else {
160
			parent::addMeta($key, $value, $level);
161
		}
162
	}
163
	
164
	/**
165
	 * wrapping ResourceObject spec api
166
	 */
167
	
168
	/**
169
	 * @param string $type
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
170
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
171
	public function setType($type) {
172
		$this->resource->setType($type);
173
	}
174
	
175
	/**
176
	 * @param string|int $id will be casted to a string
177
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
178
	public function setId($id) {
179
		$this->resource->setId($id);
180
	}
181
	
182
	/**
183
	 * @param AttributesObject $attributesObject
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
184
	 * @param array            $options          optional {@see ResourceObject::$defaults}
185
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
186
	public function setAttributesObject(AttributesObject $attributesObject, array $options=[]) {
187
		$this->ensureResourceObject();
188
		
189
		$this->resource->setAttributesObject($attributesObject, $options);
0 ignored issues
show
Bug introduced by
The method setAttributesObject does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
190
	}
191
	
192
	/**
193
	 * add a RelationshipObject to the resource
194
	 * 
195
	 * adds included resources if found inside the RelationshipObject, unless $options['includeContainedResources'] is set to false
196
	 * 
197
	 * @param string             $key
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
198
	 * @param RelationshipObject $relationshipObject
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
199
	 * @param array              $options            optional {@see ResourceDocument::$defaults}
200
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
201 View Code Duplication
	public function addRelationshipObject($key, RelationshipObject $relationshipObject, array $options=[]) {
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...
202
		$this->ensureResourceObject();
203
		
204
		$options = array_merge(self::$defaults, $options);
205
		
206
		$this->resource->addRelationshipObject($key, $relationshipObject);
0 ignored issues
show
Bug introduced by
The method addRelationshipObject does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
207
		
208
		if ($options['includeContainedResources']) {
209
			$this->addIncludedResourceObject(...$relationshipObject->getNestedContainedResourceObjects());
210
		}
211
	}
212
	
213
	/**
214
	 * set the RelationshipsObject to the resource
215
	 * 
216
	 * adds included resources if found inside the RelationshipObjects inside the RelationshipsObject, unless $options['includeContainedResources'] is set to false
217
	 * 
218
	 * @param RelationshipsObject $relationshipsObject
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
219
	 * @param array               $options             optional {@see ResourceDocument::$defaults}
220
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
221 View Code Duplication
	public function setRelationshipsObject(RelationshipsObject $relationshipsObject, array $options=[]) {
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...
222
		$this->ensureResourceObject();
223
		
224
		$options = array_merge(self::$defaults, $options);
225
		
226
		$this->resource->setRelationshipsObject($relationshipsObject);
0 ignored issues
show
Bug introduced by
The method setRelationshipsObject does only exist in alsvanzelf\jsonapi\objects\ResourceObject, but not in alsvanzelf\jsonapi\objec...esourceIdentifierObject.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
227
		
228
		if ($options['includeContainedResources']) {
229
			$this->addIncludedResourceObject(...$relationshipsObject->getNestedContainedResourceObjects());
230
		}
231
	}
232
	
233
	/**
234
	 * spec api
235
	 */
236
	
237
	/**
238
	 * overwrites the primary resource
239
	 * 
240
	 * adds included resources if found inside the resource's relationships, unless $options['includeContainedResources'] is set to false
241
	 * 
242
	 * @param ResourceInterface $resource
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
243
	 * @param array             $options  optional {@see ResourceDocument::$defaults}
244
	 * 
245
	 * @throws InputException if the $resource is a ResourceDocument itself
246
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
247
	public function setPrimaryResource(ResourceInterface $resource, array $options=[]) {
248
		if ($resource instanceof ResourceDocument) {
249
			throw new InputException('does not make sense to set a document inside a document, use ResourceObject or ResourceIdentifierObject instead');
250
		}
251
		
252
		$options = array_merge(self::$defaults, $options);
253
		
254
		$this->resource = $resource;
0 ignored issues
show
Documentation Bug introduced by
It seems like $resource of type object<alsvanzelf\jsonap...aces\ResourceInterface> is incompatible with the declared type object<alsvanzelf\jsonap...objects\ResourceObject> of property $resource.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
255
		
256
		if ($options['includeContainedResources'] && $this->resource instanceof RecursiveResourceContainerInterface) {
257
			$this->addIncludedResourceObject(...$this->resource->getNestedContainedResourceObjects());
258
		}
259
	}
260
	
261
	/**
262
	 * internal api
263
	 */
264
	
265
	/**
266
	 * @internal
267
	 * 
268
	 * @throws Exception
269
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
270
	private function ensureResourceObject() {
271
		if ($this->resource instanceof ResourceObject === false) {
272
			throw new Exception('the resource is an identifier-only object');
273
		}
274
	}
275
	
276
	/**
277
	 * DocumentInterface
278
	 */
279
	
280
	/**
281
	 * @inheritDoc
282
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
283
	public function toArray() {
284
		$array = parent::toArray();
285
		
286
		$array['data'] = null;
287
		if ($this->resource !== null && $this->resource->isEmpty() === false) {
288
			$array['data'] = $this->resource->toArray();
289
		}
290
		
291
		return $array;
292
	}
293
	
294
	/**
295
	 * ResourceInterface
296
	 */
297
	
298
	/**
0 ignored issues
show
Coding Style introduced by
Parameter $identifierOnly should have a doc-comment as per coding-style.
Loading history...
299
	 * @inheritDoc
300
	 */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
301
	public function getResource($identifierOnly=false) {
302
		return $this->resource->getResource($identifierOnly);
303
	}
304
}
305