Request   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 35
c 1
b 0
f 0
dl 0
loc 122
rs 10
wmc 14

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 3
A validate() 0 19 3
A getBody() 0 12 4
A getPath() 0 3 1
A getQuery() 0 10 3
1
<?php
2
3
namespace alekciy\ofd;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Valitron\Validator;
8
9
/**
10
 * Класс запроса к провайдеру.
11
 */
12
abstract class Request
13
{
14
	/** @var string HTTP метод */
15
	public $method = '';
16
17
	/** @var string Путь до документа */
18
	protected $path = '';
19
20
	public $debug = false;
21
22
	/**
23
	 * @param array $init Массив значений свойств инициализации.
24
	 * @throws Exception
25
	 */
26
	public function __construct(array $init)
27
	{
28
		foreach ($init as $propertyName => $propertyValue) {
29
			if (property_exists($this, $propertyName)) {
30
				$this->$propertyName = $propertyValue;
31
			}
32
		}
33
		$this->validate();
34
	}
35
36
	/**
37
	 * В потомках вызывать родительский метод и делать array_merge().
38
	 * Карта соответствия имени свойства (ключ) объекта и имени перенной в API (значение). Все свойства которые должны
39
	 * передаваться при запросе в API должны быть тут перечислены. При этом значение это массив:
40
	 *   ключ - куда уходит переменная: query (в URL), body (тело запроса);
41
	 *   значение - имя переменной в API
42
	 * Пример: ['pageNumber' => ['query' => 'pn'].
43
	 *
44
	 * @var array
45
	 */
46
	abstract protected function getPropertyMap(): array;
47
48
	/**
49
	 * Правила валидации в виде массива: ключ - имя правила, значение - массив с именами свойств для которых правило будет
50
	 * проверяться. Например, свойство method является обязательным для заполнения: ['method', ['required']]
51
	 *
52
	 * @see https://github.com/vlucas/valitron#built-in-validation-rules
53
	 * @return array
54
	 */
55
	abstract protected function getRuleList(): array;
56
57
	/**
58
	 * Выполнить проверку корректности запроса.
59
	 *
60
	 * @param string $lang Язык на котором выводятся сообщения с ошибками валидации.
61
	 * @return void
62
	 * @throws Exception
63
	 * @throws InvalidArgumentException
64
	 */
65
	public function validate($lang = 'ru')
66
	{
67
		Validator::lang($lang);
68
		$validator = new Validator(get_object_vars($this));
69
		// Задаем правила валидации
70
		$validator->mapFieldRules('method', [
71
			'required',
72
			['in', ['POST', 'GET']],
73
		]);
74
		$validator->mapFieldRules('path', ['required']);
75
		$validator->mapFieldRules('debug', ['boolean']);
76
		// Правила валидации дочерних классов
77
		$validator->mapFieldsRules($this->getRuleList());
78
		if (!$validator->validate()) {
79
			$messageList = [];
80
			foreach ($validator->errors() as  $propertyName => $errorList) {
81
				$messageList[] = get_class($this) . '.' . $propertyName . ': ' . implode(', ', $errorList);
82
			}
83
			throw new Exception(implode('. ', $messageList));
84
		}
85
	}
86
87
	/**
88
	 * Получить тело запроса для отправки в API.
89
	 *
90
	 * @return array
91
	 * @throws Exception
92
	 */
93
	public function getBody(): array
94
	{
95
		$result = [];
96
		foreach ($this->getPropertyMap() as $propertyName => $filter) {
97
			if (!isset($filter['body'])) {
98
				continue;
99
			}
100
			if (!empty($this->$propertyName)) {
101
				$result[$filter['body']] = $this->$propertyName;
102
			}
103
		}
104
		return $result;
105
	}
106
107
	/**
108
	 * Получить параметры запроса.
109
	 *
110
	 * @return array
111
	 * @throws Exception
112
	 */
113
	public function getQuery(): array
114
	{
115
		$result = [];
116
		foreach ($this->getPropertyMap() as $propertyName => $filter) {
117
			if (!isset($filter['query'])) {
118
				continue;
119
			}
120
			$result[$filter['query']] = $this->$propertyName;
121
		}
122
		return $result;
123
	}
124
125
	/**
126
	 * Путь до документа. В потомках следует переопределить если путь представляет собой вычисляемую строку (например,
127
	 * если там содержиться идентификатор).
128
	 *
129
	 * @return string
130
	 */
131
	public function getPath(): string
132
	{
133
		return $this->path;
134
	}
135
}