Passed
Push — developer ( 8c317e...75b69c )
by Radosław
34:12
created

AbstractListView::getCustomViews()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 0
1
<?php
2
/**
3
 * The file contains: Abstract class ListView.
4
 *
5
 * @package Model
6
 *
7
 * @copyright YetiForce Sp. z o.o.
8
 * @license YetiForce Public License 3.0 (licenses/LicenseEN.txt or yetiforce.com)
9
 * @author Arkadiusz Adach <[email protected]>
10
 * @author    Mariusz Krzaczkowski <[email protected]>
11
 * @author    Radosław Skrzypczak <[email protected]>
12
 */
13
14
namespace YF\Modules\Base\Model;
15
16
/**
17
 * Abstract class ListView.
18
 */
19
abstract class AbstractListView
20
{
21
	/** @var string Module name. */
22
	protected $moduleName;
23
24
	/** @var string[] Column fields */
25
	protected $fields = [];
26
27
	/** @var array Records list from api. */
28
	protected $recordsList = [];
29
30
	/** @var int Current page. */
31
	private $page = 1;
32
33
	/** @var int The number of items on the page. */
34
	protected $limit = 0;
35
36
	/** @var int Offset. */
37
	protected $offset = 0;
38
39
	/** @var string Sorting direction. */
40
	protected $order;
41
42
	/** @var string Sets the ORDER BY part of the query record list. */
43
	protected $orderField;
44
45
	/** @var array Conditions. */
46
	protected $conditions = [];
47
48
	/** @var bool Use raw data. */
49
	protected $rawData = false;
50
51
	protected $actionName = 'RecordsList';
52
53
	/** @var array Custom views */
54
	protected $customViews;
55
56
	/** @var int Custom view ID */
57
	protected $cvId;
58
59
	/**
60
	 * Get instance.
61
	 *
62
	 * @param string $moduleName
63
	 * @param string $viewName
64
	 *
65
	 * @return self
0 ignored issues
show
Documentation introduced by
Should the return type not be \self?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
66
	 */
67
	public static function getInstance(string $moduleName, string $viewName = 'ListView'): self
68
	{
69
		$handlerModule = \App\Loader::getModuleClassName($moduleName, 'Model', $viewName);
70
		$self = new $handlerModule();
71
		$self->moduleName = $moduleName;
72
		$self->limit = \App\Config::$itemsPrePage ?: 15;
73
		return $self;
74
	}
75
76
	/**
77
	 * Function to get the Module Model.
78
	 *
79
	 * @return string
80
	 */
81
	public function getModuleName(): string
82
	{
83
		return $this->moduleName;
84
	}
85
86
	/**
87
	 * Function to set raw data.
88
	 *
89
	 * @param bool $rawData
90
	 *
91
	 * @return self
92
	 */
93
	public function setRawData(bool $rawData): self
94
	{
95
		$this->rawData = $rawData;
96
		return $this;
97
	}
98
99
	/**
100
	 * Set custom fields.
101
	 *
102
	 * @param array $fields
103
	 *
104
	 * @return self
105
	 */
106
	public function setFields(array $fields): self
107
	{
108
		$this->fields = $fields;
109
		return $this;
110
	}
111
112
	/**
113
	 * Set limit.
114
	 *
115
	 * @param int $limit
116
	 *
117
	 * @return self
118
	 */
119
	public function setLimit(int $limit): self
120
	{
121
		$this->limit = $limit;
122
		return $this;
123
	}
124
125
	/**
126
	 * Set offset.
127
	 *
128
	 * @param int $offset
129
	 *
130
	 * @return self
131
	 */
132
	public function setOffset(int $offset): self
133
	{
134
		$this->offset = $offset;
135
		return $this;
136
	}
137
138
	/**
139
	 * Set order.
140
	 *
141
	 * @param string $field
142
	 * @param string $direction
143
	 *
144
	 * @return self
145
	 */
146
	public function setOrder(string $field, string $direction): self
147
	{
148
		$this->orderField = $field;
149
		$this->order = $direction;
150
		return $this;
151
	}
152
153
	/**
154
	 * Set conditions.
155
	 *
156
	 * @param array $conditions
157
	 *
158
	 * @return void
159
	 */
160
	public function setConditions(array $conditions)
161
	{
162
		$this->conditions = $conditions;
163
	}
164
165
	/**
166
	 * Undocumented function.
167
	 *
168
	 * @param int $cvId
169
	 *
170
	 * @return $this
171
	 */
172
	public function setCvId(int $cvId): self
173
	{
174
		$this->cvId = $cvId;
175
		return $this;
176
	}
177
178
	/**
179
	 * Load a list of records from the API.
180
	 *
181
	 * @return self
182
	 */
183
	public function loadRecordsList(): self
184
	{
185
		$this->recordsList = $this->getFromApi($this->getApiHeaders());
186
		return $this;
187
	}
188
189
	/**
190
	 * Gets headers for api.
191
	 *
192
	 * @return array
193
	 */
194
	public function getApiHeaders(): array
195
	{
196
		$headers = [
197
			'x-row-count' => 1,
198
			'x-row-limit' => $this->limit,
199
			'x-row-offset' => $this->offset
200
		];
201
		if (!empty($this->fields)) {
202
			$headers['x-fields'] = \App\Json::encode($this->fields);
203
		}
204
		if (!empty($this->conditions)) {
205
			$headers['x-condition'] = \App\Json::encode($this->conditions);
206
		}
207
		if ($this->rawData) {
208
			$headers['x-raw-data'] = 1;
209
		}
210
		if (!empty($this->order)) {
211
			$headers['x-row-order-field'] = $this->orderField;
212
			$headers['x-row-order'] = $this->order;
213
		}
214
		if ($cvId = $this->getDefaultCustomView()) {
215
			$headers['x-cv-id'] = $cvId;
216
		}
217
		return $headers;
218
	}
219
220
	/**
221
	 * Get data from api.
222
	 *
223
	 * @param array $headers
224
	 *
225
	 * @return array
226
	 */
227
	protected function getFromApi(array $headers): array
228
	{
229
		$api = \App\Api::getInstance();
230
		$api->setCustomHeaders($headers);
231
		return $api->call($this->getModuleName() . '/' . $this->actionName);
232
	}
233
234
	/**
235
	 * Get records list model.
236
	 *
237
	 * @return Record[]
238
	 */
239
	public function getRecordsListModel(): array
240
	{
241
		$recordsModel = [];
242
		if (!empty($this->recordsList['records'])) {
243
			foreach ($this->recordsList['records'] as $id => $value) {
244
				$recordModel = Record::getInstance($this->getModuleName());
245
				if (isset($value['recordLabel'])) {
246
					$recordModel->setName($value['recordLabel']);
247
					unset($value['recordLabel']);
248
				}
249
				$recordModel->setData($value)->setId($id);
250
				$recordsModel[$id] = $recordModel;
251
			}
252
		}
253
		if (!empty($this->recordsList['rawData'])) {
254
			foreach ($this->recordsList['rawData'] as $id => $value) {
255
				$recordsModel[$id]->setRawData($value);
256
			}
257
		}
258
		return $recordsModel;
259
	}
260
261
	/**
262
	 * Get headers of list.
263
	 *
264
	 * @return array
265
	 */
266
	public function getHeaders(): array
267
	{
268
		if (empty($this->recordsList)) {
269
			$headers = ['x-only-column' => 1];
270
			if ($cvId = $this->getDefaultCustomView()) {
271
				$headers['x-cv-id'] = $cvId;
272
			}
273
			$this->recordsList = $this->getFromApi($headers);
274
		}
275
		return $this->recordsList['headers'] ?? [];
276
	}
277
278
	/**
279
	 * Gets custom views.
280
	 *
281
	 * @return array
282
	 */
283
	public function getCustomViews(): array
284
	{
285
		if (null === $this->customViews) {
286
			$this->customViews = \App\Api::getInstance()->call($this->getModuleName() . '/CustomView') ?: [];
287
		}
288
		return $this->customViews;
289
	}
290
291
	/**
292
	 * Get default custom view ID.
293
	 *
294
	 * @return int|null
0 ignored issues
show
Documentation introduced by
Should the return type not be integer|string?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
295
	 */
296
	public function getDefaultCustomView(): ?int
297
	{
298
		if (!$this->cvId) {
299
			foreach ($this->getCustomViews() as $cvId => $cvData) {
300
				if ($cvData['isDefault']) {
301
					$this->cvId = $cvId;
0 ignored issues
show
Documentation Bug introduced by
It seems like $cvId can also be of type string. However, the property $cvId is declared as type integer. 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...
302
					break;
303
				}
304
			}
305
		}
306
		return $this->cvId;
307
	}
308
309
	/**
310
	 * Get all rows count.
311
	 *
312
	 * @return int
313
	 */
314
	public function getCount(): int
315
	{
316
		return $this->recordsList['numberOfAllRecords'] ?? 0;
317
	}
318
319
	/**
320
	 * Get current page.
321
	 *
322
	 * @return int
323
	 */
324
	public function getPage(): int
325
	{
326
		if (!$this->page) {
327
			$this->page = floor($this->recordsList['numberOfRecords'] / ($this->recordsList['numberOfAllRecords'] ?: 1)) ?: 1;
0 ignored issues
show
Documentation Bug introduced by
It seems like floor($this->recordsList...llRecords'] ?: 1)) ?: 1 can also be of type double. However, the property $page is declared as type integer. 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...
328
		}
329
		return $this->page;
330
	}
331
332
	/**
333
	 * Sets page number.
334
	 *
335
	 * @param int $page
336
	 *
337
	 * @return $this
338
	 */
339
	public function setPage(int $page)
340
	{
341
		$this->page = $page;
342
		return $this;
343
	}
344
345
	/**
346
	 * Is there more pages.
347
	 *
348
	 * @return bool
349
	 */
350
	public function isMorePages(): bool
351
	{
352
		return $this->recordsList['isMorePages'] ?? false;
353
	}
354
}
355