LazyResource   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 145
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
dl 0
loc 145
rs 10
c 0
b 0
f 0
wmc 14
lcom 1
cbo 2

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setParams() 0 6 1
A getParams() 0 4 1
isInitialized() 0 1 ?
A init() 0 21 5
A fetchData() 0 4 1
A onData() 0 3 1
A getData() 0 4 1
A exists() 0 9 2
urlBase() 0 1 ?
A url() 0 12 2
1
<?php
2
3
namespace Scriptotek\Alma\Model;
4
5
use Danmichaelo\QuiteSimpleXMLElement\QuiteSimpleXMLElement;
6
use Scriptotek\Alma\Exception\ResourceNotFound;
7
8
/**
9
 * A LazyResource is anything that has its own URL and therefore can be lazy-loaded.
10
 * This class implements the basic ghost model functionality.
11
 *
12
 * The $initialized property indicates if the model is loaded or not.
13
 */
14
abstract class LazyResource extends Model
15
{
16
    /**
17
     * This class is a ghost object that lazy loads the full record only when needed.
18
     * If $initialized is false, it means we haven't yet loaded the full record.
19
     * We can still have incomplete data from a search response.
20
     */
21
    protected $initialized = false;
22
23
    /**
24
     * @var array Query string parameters
25
     */
26
    protected $params = [];
27
28
    /**
29
     * Set request query string parameters.
30
     *
31
     * @param $params array
32
     *
33
     * @return $this
34
     */
35
    public function setParams($params)
36
    {
37
        $this->params = $params;
38
39
        return $this;
40
    }
41
42
    /**
43
     * Get the request query string parameters.
44
     *
45
     * @return array
46
     */
47
    public function getParams()
48
    {
49
        return $this->params;
50
    }
51
52
    /**
53
     * Check if we have the full representation of our data object.
54
     *
55
     * @param \stdClass $data
56
     *
57
     * @return bool
58
     */
59
    abstract protected function isInitialized($data);
60
61
    /**
62
     * Load data onto this object. Chainable method.
63
     *
64
     * @param \stdClass|QuiteSimpleXMLElement $data
65
     *
66
     * @return $this
67
     */
68
    public function init($data = null)
69
    {
70
        if ($this->initialized) {
71
            return $this;
72
        }
73
74
        if (is_null($data)) {
75
            $data = $this->fetchData();
76
        }
77
78
        if ($this->isInitialized($data)) {
79
            $this->initialized = true;
80
        }
81
82
        $this->data = $data;
0 ignored issues
show
Documentation Bug introduced by
It seems like $data can also be of type object<Danmichaelo\Quite...\QuiteSimpleXMLElement>. However, the property $data is declared as type object<stdClass>|array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
83
        if ($this->initialized) {
84
            $this->onData($data);
85
        }
86
87
        return $this;
88
    }
89
90
    /**
91
     * Get and return the model data.
92
     *
93
     * @return object
94
     */
95
    protected function fetchData()
96
    {
97
        return $this->client->getJSON($this->url());
98
    }
99
100
    /**
101
     * Called when data is available on the object.
102
     * The resource classes can use this method to process the data.
103
     *
104
     * @param mixed $data
105
     */
106
    protected function onData($data)
107
    {
108
    }
109
110
    /**
111
     * Get the raw data object.
112
     */
113
    public function getData()
114
    {
115
        return $this->init()->data;
116
    }
117
118
    /**
119
     * Check if the object exists.
120
     */
121
    public function exists()
122
    {
123
        try {
124
            $this->init();
125
        } catch (ResourceNotFound $ex) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
126
        }
127
128
        return $this->initialized;
129
    }
130
131
    /**
132
     * Generate the base URL for this resource.
133
     *
134
     * @return string
135
     */
136
    abstract protected function urlBase();
137
138
    /**
139
     * Build a relative URL for a resource.
140
     *
141
     * @param string $path
142
     * @param array  $query
143
     *
144
     * @return string
145
     */
146
    protected function url($path = '', $query = [])
147
    {
148
        $path = $this->urlBase() . $path;
149
        $query = http_build_query(array_merge($this->params, $query));
150
151
        $url = $path;
152
        if (!empty($query)) {
153
            $url .= '?' . $query;
154
        }
155
156
        return $url;
157
    }
158
}
159