This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
2 | ||||||||||||
3 | namespace DigitalWand\AdminHelper\Widget; |
|||||||||||
4 | ||||||||||||
5 | use Bitrix\Main\Localization\Loc; |
|||||||||||
6 | use DigitalWand\AdminHelper\Helper\AdminBaseHelper; |
|||||||||||
7 | use DigitalWand\AdminHelper\Helper\AdminEditHelper; |
|||||||||||
8 | use DigitalWand\AdminHelper\Helper\AdminListHelper; |
|||||||||||
9 | use Bitrix\Main\Entity\DataManager; |
|||||||||||
10 | ||||||||||||
11 | /** |
|||||||||||
12 | * Виджет - класс, отвечающий за внешний вид отдельно взятого поля сущности. Один виджет отвечает за: |
|||||||||||
13 | * <ul> |
|||||||||||
14 | * <li>Отображение поля на странице редактирования</li> |
|||||||||||
15 | * <li>Отображение ячейки поля в таблице списка - при просмотре и редактировании</li> |
|||||||||||
16 | * <li>Отображение фильтра по данному полю</li> |
|||||||||||
17 | * <li>Валидацию значения поля</li> |
|||||||||||
18 | * </ul> |
|||||||||||
19 | * |
|||||||||||
20 | * Также виджетами осуществляется предварительная обработка данных: |
|||||||||||
21 | * <ul> |
|||||||||||
22 | * <li>Перед сохранением значения поля в БД</li> |
|||||||||||
23 | * <li>После получения значения поля из БД</li> |
|||||||||||
24 | * <li>Модификация запроса перед фильтрацией</li> |
|||||||||||
25 | * <li>Модификация пуеДшые перед выборкой данных</li> |
|||||||||||
26 | * </ul> |
|||||||||||
27 | * |
|||||||||||
28 | * Для получения минимальной функциональности достаточно переопределить основные методы, отвечающие за отображение |
|||||||||||
29 | * виджета в списке и на детальной. |
|||||||||||
30 | * |
|||||||||||
31 | * Каждый виджет имеет ряд специфических настроек, некоторые из которых обязательны для заполнения. Подробную |
|||||||||||
32 | * документацию по настройкам стоит искать в документации к конкретному виджету. Настройки могут быть переданы в |
|||||||||||
33 | * виджет как при описании всего интерфейса в файле Interface.php, так и непосредственно во время исполнения, |
|||||||||||
34 | * внутри Helper-классов. |
|||||||||||
35 | * |
|||||||||||
36 | * При указании настроек типа "да"/"нет", нельзя использовать строковые обозначения "Y"/"N": |
|||||||||||
37 | * для этого есть булевы true и false. |
|||||||||||
38 | * |
|||||||||||
39 | * Настройки базового класса: |
|||||||||||
40 | * <ul> |
|||||||||||
41 | * <li><b>HIDE_WHEN_CREATE</b> - скрывает поле в форме редактирования, если создаётся новый элемент, а не открыт |
|||||||||||
42 | * существующий на редактирование.</li> |
|||||||||||
43 | * <li><b>TITLE</b> - название поля. Если не задано то возьмется значение title из DataManager::getMap() |
|||||||||||
44 | * через getField($code)->getTitle(). Будет использовано в фильтре, заголовке таблицы и в качестве подписи поля |
|||||||||||
45 | * на |
|||||||||||
46 | * странице редактирования.</li> |
|||||||||||
47 | * <li><b>REQUIRED</b> - является ли поле обязательным.</li> |
|||||||||||
48 | * <li><b>READONLY</b> - поле нельзя редактировать, предназначено только для чтения</li> |
|||||||||||
49 | * <li><b>FILTER</b> - позволяет указать способ фильтрации по полю. В базовом классе возможен только вариант "BETWEEN" |
|||||||||||
50 | * или "><". И в том и в другом случае это будет означать фильтрацию по диапазону значений. Количество возможных |
|||||||||||
51 | * вариантов этого параметра может быть расширено в наследуемых классах</li> |
|||||||||||
52 | * <li><b>UNIQUE</b> - поле должно содержать только уникальные значения</li> |
|||||||||||
53 | * <li><b>VIRTUAL</b> - особая настройка, отражается как на поведении виджета, так и на поведении хэлперов. Поле, |
|||||||||||
54 | * объявленное виртуальным, отображается в графическом интерфейче, однако не участвоует в запросах к БД. Опция |
|||||||||||
55 | * может быть полезной при реализации нестандартной логики, когда, к примеру, под именем одного поля могут |
|||||||||||
56 | * выводиться данные из нескольких полей сразу. </li> |
|||||||||||
57 | * <li><b>EDIT_IN_LIST</b> - параметр не обрабатывается непосредственно виджетом, однако используется хэлпером. |
|||||||||||
58 | * Указывает, можно ли редактировать данное поле в спискке</li> |
|||||||||||
59 | * <li><b>MULTIPLE</b> - bool является ли поле множественным</li> |
|||||||||||
60 | * <li><b>MULTIPLE_FIELDS</b> - bool поля используемые в хранилище множественных значений и их алиасы</li> |
|||||||||||
61 | * <li><b>LIST</b> - отображать ли поле в списке доступных в настройках столбцов таблицы (по-умолчанию true)</li> |
|||||||||||
62 | * <li><b>HEADER</b> - является ли столбец отображаемым по-умолчанию, если вывод столбцов таблицы не настроен (по-умолчанию true)</li> |
|||||||||||
63 | * </ul> |
|||||||||||
64 | * |
|||||||||||
65 | * Как сделать виджет множественным? |
|||||||||||
66 | * <ul> |
|||||||||||
67 | * <li>Реализуйте метод genMultipleEditHTML(). Метод должен выводить множественную форму ввода. Для реализации формы |
|||||||||||
68 | * ввода есть JS хелпер HelperWidget::jsHelper()</li> |
|||||||||||
69 | * <li>Опишите поля, которые будут переданы связи в EntityManager. Поля описываются в настройке "MULTIPLE_FIELDS" |
|||||||||||
70 | * виджета. По умолчанию множественный виджет использует поля ID, ENTITY_ID, VALUE</li> |
|||||||||||
71 | * <li>Полученные от виджета данные будут переданы в EntityManager и сохранены как связанные данные</li> |
|||||||||||
72 | * </ul> |
|||||||||||
73 | * Пример реализации можно увидеть в виджете StringWidget |
|||||||||||
74 | * |
|||||||||||
75 | * Как использовать множественный виджет? |
|||||||||||
76 | * <ul> |
|||||||||||
77 | * <li> |
|||||||||||
78 | * Создайте таблицу и модель, которая будет хранить данные поля |
|||||||||||
79 | * - Таблица обязательно должна иметь поля, которые требует виджет. |
|||||||||||
80 | * Обязательные поля виджета по умолчанию описаны в: HelperWidget::$settings['MULTIPLE_FIELDS'] |
|||||||||||
81 | * Если у виджета нестандартный набор полей, то они хранятся в: SomeWidget::$settings['MULTIPLE_FIELDS'] |
|||||||||||
82 | * - Если поля, которые требует виджет есть в вашей таблице, но они имеют другие названия, |
|||||||||||
83 | * можно настроить виджет для работы с вашими полями. |
|||||||||||
84 | * Для этого переопределите настройку MULTIPLE_FIELDS при объявлении поля в интерфейсе следующим способом: |
|||||||||||
85 | * ``` |
|||||||||||
86 | * 'RELATED_LINKS' => array( |
|||||||||||
87 | * 'WIDGET' => new StringWidget(), |
|||||||||||
88 | * 'TITLE' => 'Ссылки', |
|||||||||||
89 | * 'MULTIPLE' => true, |
|||||||||||
90 | * // Обратите внимание, именно тут переопределяются поля виджета |
|||||||||||
91 | * 'MULTIPLE_FIELDS' => array( |
|||||||||||
92 | * 'ID', // Должны быть прописаны все поля, даже те, которые не нужно переопределять |
|||||||||||
93 | * 'ENTITY_ID' => 'NEWS_ID', // ENTITY_ID - поле, которое требует виджет, NEWS_ID - пример поля, которое |
|||||||||||
94 | * будет использоваться вместо ENTITY_ID |
|||||||||||
95 | * 'VALUE' => 'LINK', // VALUE - поле, которое требует виджет, LINK - пример поля, которое будет |
|||||||||||
96 | * использоваться вместо VALUE |
|||||||||||
97 | * ) |
|||||||||||
98 | * ), |
|||||||||||
99 | * ``` |
|||||||||||
100 | * </li> |
|||||||||||
101 | * |
|||||||||||
102 | * <li> |
|||||||||||
103 | * Далее в основной модели (та, которая указана в AdminBaseHelper::$model) нужно прописать связь с моделью, |
|||||||||||
104 | * в которой вы хотите хранить данные поля |
|||||||||||
105 | * Пример объявления связи: |
|||||||||||
106 | * ``` |
|||||||||||
107 | * new Entity\ReferenceField( |
|||||||||||
108 | * 'RELATED_LINKS', |
|||||||||||
109 | * 'namespace\NewsLinksTable', |
|||||||||||
110 | * array('=this.ID' => 'ref.NEWS_ID'), |
|||||||||||
111 | * // Условия FIELD и ENTITY не обязательны, подробности смотрите в комментариях к классу @see EntityManager |
|||||||||||
112 | * 'ref.FIELD' => new DB\SqlExpression('?s', 'NEWS_LINKS'), |
|||||||||||
113 | * 'ref.ENTITY' => new DB\SqlExpression('?s', 'news'), |
|||||||||||
114 | * ), |
|||||||||||
115 | * ``` |
|||||||||||
116 | * </li> |
|||||||||||
117 | * |
|||||||||||
118 | * <li> |
|||||||||||
119 | * Что бы виджет работал во множественном режиме, нужно при описании интерфейса поля указать параметр MULTIPLE => true |
|||||||||||
120 | * ``` |
|||||||||||
121 | * 'RELATED_LINKS' => array( |
|||||||||||
122 | * 'WIDGET' => new StringWidget(), |
|||||||||||
123 | * 'TITLE' => 'Ссылки', |
|||||||||||
124 | * // Включаем режим множественного ввода |
|||||||||||
125 | * 'MULTIPLE' => true, |
|||||||||||
126 | * ) |
|||||||||||
127 | * ``` |
|||||||||||
128 | * </li> |
|||||||||||
129 | * |
|||||||||||
130 | * <li> |
|||||||||||
131 | * Готово :) |
|||||||||||
132 | * </li> |
|||||||||||
133 | * </ul> |
|||||||||||
134 | * |
|||||||||||
135 | * О том как сохраняются данные множественных виджетов можно узнать из комментариев |
|||||||||||
136 | * класса \DigitalWand\AdminHelper\EntityManager. |
|||||||||||
137 | * |
|||||||||||
138 | * @see EntityManager |
|||||||||||
139 | * @see HelperWidget::getEditHtml() |
|||||||||||
140 | * @see HelperWidget::generateRow() |
|||||||||||
141 | * @see showFilterHtml::showFilterHTML() |
|||||||||||
142 | * @see HelperWidget::setSetting() |
|||||||||||
143 | * |
|||||||||||
144 | * @author Nik Samokhvalov <[email protected]> |
|||||||||||
145 | * @author Dmitriy Baibuhtin <[email protected]> |
|||||||||||
146 | */ |
|||||||||||
147 | abstract class HelperWidget |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
148 | { |
|||||||||||
149 | const LIST_HELPER = 1; |
|||||||||||
150 | const EDIT_HELPER = 2; |
|||||||||||
151 | ||||||||||||
152 | /** |
|||||||||||
153 | * @var string Код поля. |
|||||||||||
154 | */ |
|||||||||||
155 | protected $code; |
|||||||||||
156 | /** |
|||||||||||
157 | * @var array $settings Настройки виджета для данной модели. |
|||||||||||
158 | */ |
|||||||||||
159 | protected $settings = array( |
|||||||||||
160 | // Поля множественного виджета по умолчанию (array('ОРИГИНАЛЬНОЕ НАЗВАНИЕ', 'ОРИГИНАЛЬНОЕ НАЗВАНИЕ' => 'АЛИАС')) |
|||||||||||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
42% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
||||||||||||
161 | 'MULTIPLE_FIELDS' => array('ID', 'VALUE', 'ENTITY_ID') |
|||||||||||
162 | ); |
|||||||||||
163 | /** |
|||||||||||
164 | * @var array Настройки "по-умолчанию" для модели. |
|||||||||||
165 | */ |
|||||||||||
166 | static protected $defaults; |
|||||||||||
167 | /** |
|||||||||||
168 | * @var DataManager Название класса модели. |
|||||||||||
169 | */ |
|||||||||||
170 | protected $entityName; |
|||||||||||
171 | /** |
|||||||||||
172 | * @var array Данные модели. |
|||||||||||
173 | */ |
|||||||||||
174 | protected $data; |
|||||||||||
175 | /** @var AdminBaseHelper|AdminListHelper|AdminEditHelper $helper Экземпляр хэлпера, вызывающий данный виджет. |
|||||||||||
176 | */ |
|||||||||||
177 | protected $helper; |
|||||||||||
178 | /** |
|||||||||||
179 | * @var bool Статус отображения JS хелпера. Используется для исключения дублирования JS-кода. |
|||||||||||
180 | */ |
|||||||||||
181 | protected $jsHelper = false; |
|||||||||||
182 | /** |
|||||||||||
183 | * @var array $validationErrors Ошибки валидации поля. |
|||||||||||
184 | */ |
|||||||||||
185 | protected $validationErrors = array(); |
|||||||||||
186 | /** |
|||||||||||
187 | * @var string Строка, добавляемая к полю name полей фильтра. |
|||||||||||
188 | */ |
|||||||||||
189 | protected $filterFieldPrefix = 'find_'; |
|||||||||||
190 | ||||||||||||
191 | /** |
|||||||||||
192 | * Эксемпляр виджета создаётся всего один раз, при описании настроек интерфейса. При создании есть возможность |
|||||||||||
193 | * сразу указать для него необходимые настройки. |
|||||||||||
194 | * |
|||||||||||
195 | * @param array $settings |
|||||||||||
196 | */ |
|||||||||||
197 | public function __construct(array $settings = array()) |
|||||||||||
198 | { |
|||||||||||
199 | Loc::loadMessages(__FILE__); |
|||||||||||
200 | ||||||||||||
201 | $this->settings = $settings; |
|||||||||||
202 | } |
|||||||||||
203 | ||||||||||||
204 | /** |
|||||||||||
205 | * Генерирует HTML для редактирования поля. |
|||||||||||
206 | * |
|||||||||||
207 | * @return string |
|||||||||||
208 | * |
|||||||||||
209 | * @api |
|||||||||||
210 | */ |
|||||||||||
211 | abstract protected function getEditHtml(); |
|||||||||||
212 | ||||||||||||
213 | /** |
|||||||||||
214 | * Генерирует HTML для редактирования поля в мульти-режиме. |
|||||||||||
215 | * |
|||||||||||
216 | * @return string |
|||||||||||
217 | * |
|||||||||||
218 | * @api |
|||||||||||
219 | */ |
|||||||||||
220 | protected function getMultipleEditHtml() |
|||||||||||
221 | { |
|||||||||||
222 | return Loc::getMessage('DIGITALWAND_AH_MULTI_NOT_SUPPORT'); |
|||||||||||
223 | } |
|||||||||||
224 | ||||||||||||
225 | /** |
|||||||||||
226 | * Оборачивает поле в HTML код, который в большинстве случаев менять не придется. Далее вызывается |
|||||||||||
227 | * кастомизируемая часть. |
|||||||||||
228 | * |
|||||||||||
229 | * @param bool $isPKField Является ли поле первичным ключом модели. |
|||||||||||
230 | * |
|||||||||||
231 | * @see HelperWidget::getEditHtml(); |
|||||||||||
232 | */ |
|||||||||||
233 | public function showBasicEditField($isPKField) |
|||||||||||
234 | { |
|||||||||||
235 | if ($this->getSettings('HIDE_WHEN_CREATE') AND !isset($this->data['ID'])) { |
|||||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
236 | return; |
|||||||||||
237 | } |
|||||||||||
238 | ||||||||||||
239 | // JS хелперы |
|||||||||||
240 | $this->jsHelper(); |
|||||||||||
241 | ||||||||||||
242 | if ($this->getSettings('USE_BX_API')) { |
|||||||||||
243 | $this->getEditHtml(); |
|||||||||||
244 | } else { |
|||||||||||
245 | print '<tr>'; |
|||||||||||
246 | $title = $this->getSettings('TITLE'); |
|||||||||||
247 | if ($this->getSettings('REQUIRED') === true) { |
|||||||||||
248 | $title = '<b>' . $title . '</b>'; |
|||||||||||
249 | } |
|||||||||||
250 | print '<td width="40%" style="vertical-align: top;">' . $title . ':</td>'; |
|||||||||||
251 | ||||||||||||
252 | $field = $this->getValue(); |
|||||||||||
253 | ||||||||||||
254 | if (is_null($field)) { |
|||||||||||
255 | $field = ''; |
|||||||||||
256 | } |
|||||||||||
257 | ||||||||||||
258 | $readOnly = $this->getSettings('READONLY'); |
|||||||||||
259 | ||||||||||||
260 | if (!$readOnly AND !$isPKField) { |
|||||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
261 | if ($this->getSettings('MULTIPLE')) { |
|||||||||||
262 | $field = $this->getMultipleEditHtml(); |
|||||||||||
263 | } else { |
|||||||||||
264 | $field = $this->getEditHtml(); |
|||||||||||
265 | } |
|||||||||||
266 | } else { |
|||||||||||
267 | if ($readOnly) { |
|||||||||||
268 | if ($this->getSettings('MULTIPLE')) { |
|||||||||||
269 | $field = $this->getMultipleValueReadonly(); |
|||||||||||
270 | } else { |
|||||||||||
271 | $field = $this->getValueReadonly(); |
|||||||||||
272 | } |
|||||||||||
273 | } |
|||||||||||
274 | } |
|||||||||||
275 | ||||||||||||
276 | print '<td width="60%">' . $field . '</td>'; |
|||||||||||
277 | print '</tr>'; |
|||||||||||
278 | } |
|||||||||||
279 | } |
|||||||||||
280 | ||||||||||||
281 | /** |
|||||||||||
282 | * Возвращает значение поля в форме "только для чтения" для не множественных свойств. |
|||||||||||
283 | * |
|||||||||||
284 | * @return mixed |
|||||||||||
285 | */ |
|||||||||||
286 | protected function getValueReadonly() |
|||||||||||
287 | { |
|||||||||||
288 | return static::prepareToOutput($this->getValue()); |
|||||||||||
289 | } |
|||||||||||
290 | ||||||||||||
291 | /** |
|||||||||||
292 | * Возвращает значения множественного поля. |
|||||||||||
293 | * |
|||||||||||
294 | * @return array |
|||||||||||
295 | */ |
|||||||||||
296 | protected function getMultipleValue() |
|||||||||||
297 | { |
|||||||||||
298 | $rsEntityData = null; |
|||||||||||
0 ignored issues
–
show
$rsEntityData is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
||||||||||||
299 | $values = array(); |
|||||||||||
300 | if (!empty($this->data['ID'])) { |
|||||||||||
301 | $entityName = $this->entityName; |
|||||||||||
302 | $rsEntityData = $entityName::getList(array( |
|||||||||||
303 | 'select' => array('REFERENCE_' => $this->getCode() . '.*'), |
|||||||||||
304 | 'filter' => array('=ID' => $this->data['ID']) |
|||||||||||
305 | )); |
|||||||||||
306 | ||||||||||||
307 | if ($rsEntityData) { |
|||||||||||
308 | while ($referenceData = $rsEntityData->fetch()) { |
|||||||||||
309 | if (empty($referenceData['REFERENCE_' . $this->getMultipleField('ID')])) { |
|||||||||||
310 | continue; |
|||||||||||
311 | } |
|||||||||||
312 | $values[] = $referenceData['REFERENCE_' . $this->getMultipleField('VALUE')]; |
|||||||||||
313 | } |
|||||||||||
314 | } |
|||||||||||
315 | } else { |
|||||||||||
316 | if ($this->data[$this->code]) { |
|||||||||||
317 | $values = $this->data[$this->code]; |
|||||||||||
318 | } |
|||||||||||
319 | } |
|||||||||||
320 | ||||||||||||
321 | return $values; |
|||||||||||
322 | } |
|||||||||||
323 | ||||||||||||
324 | /** |
|||||||||||
325 | * Возвращает значение поля в форме "только для чтения" для множественных свойств. |
|||||||||||
326 | * |
|||||||||||
327 | * @return string |
|||||||||||
328 | */ |
|||||||||||
329 | protected function getMultipleValueReadonly() |
|||||||||||
330 | { |
|||||||||||
331 | $values = $this->getMultipleValue(); |
|||||||||||
332 | ||||||||||||
333 | foreach ($values as &$value) { |
|||||||||||
334 | $value = static::prepareToOutput($value); |
|||||||||||
335 | } |
|||||||||||
336 | ||||||||||||
337 | return join('<br/>', $values); |
|||||||||||
338 | } |
|||||||||||
339 | ||||||||||||
340 | /** |
|||||||||||
341 | * Обработка строки для безопасного отображения. Если нужно отобразить текст как аттрибут тега, |
|||||||||||
342 | * используйте static::prepareToTag(). |
|||||||||||
343 | * |
|||||||||||
344 | * @param string $string |
|||||||||||
345 | * @param bool $hideTags Скрыть теги: |
|||||||||||
346 | * |
|||||||||||
347 | * - true - вырезать теги оставив содержимое. Результат обработки: <b>text</b> = text |
|||||||||||
348 | * |
|||||||||||
349 | * - false - отобразаить теги в виде текста. Результат обработки: <b>text</b> = <b>text</b> |
|||||||||||
350 | * |
|||||||||||
351 | * @return string |
|||||||||||
352 | */ |
|||||||||||
353 | public static function prepareToOutput($string, $hideTags = true) |
|||||||||||
354 | { |
|||||||||||
355 | if ($hideTags) { |
|||||||||||
356 | return preg_replace('/<.+>/mU', '', $string); |
|||||||||||
357 | } else { |
|||||||||||
358 | return htmlspecialchars($string, ENT_QUOTES, SITE_CHARSET); |
|||||||||||
359 | } |
|||||||||||
360 | } |
|||||||||||
361 | ||||||||||||
362 | /** |
|||||||||||
363 | * Подготовка строки для использования в аттрибутах тегов. Например: |
|||||||||||
364 | * ``` |
|||||||||||
365 | * <input name="test" value="<?= HelperWidget::prepareToTagAttr($value) ?>"/> |
|||||||||||
366 | * ``` |
|||||||||||
367 | * |
|||||||||||
368 | * @param string $string |
|||||||||||
369 | * |
|||||||||||
370 | * @return string |
|||||||||||
371 | */ |
|||||||||||
372 | public static function prepareToTagAttr($string) |
|||||||||||
373 | { |
|||||||||||
374 | // Не используйте addcslashes в этом методе, иначе в тегах будут дубли обратных слешей |
|||||||||||
375 | return htmlspecialchars($string, ENT_QUOTES, SITE_CHARSET); |
|||||||||||
376 | } |
|||||||||||
377 | ||||||||||||
378 | /** |
|||||||||||
379 | * Подготовка строки для использования в JS. |
|||||||||||
380 | * |
|||||||||||
381 | * @param string $string |
|||||||||||
382 | * |
|||||||||||
383 | * @return string |
|||||||||||
384 | */ |
|||||||||||
385 | public static function prepareToJs($string) |
|||||||||||
386 | { |
|||||||||||
387 | $string = htmlspecialchars($string, ENT_QUOTES, SITE_CHARSET); |
|||||||||||
388 | $string = addcslashes($string, "\r\n\"\\"); |
|||||||||||
389 | ||||||||||||
390 | return $string; |
|||||||||||
391 | } |
|||||||||||
392 | ||||||||||||
393 | /** |
|||||||||||
394 | * Генерирует HTML для поля в списке. |
|||||||||||
395 | * |
|||||||||||
396 | * @param \CAdminListRow $row |
|||||||||||
397 | * @param array $data Данные текущей строки. |
|||||||||||
398 | * |
|||||||||||
399 | * @return void |
|||||||||||
400 | * |
|||||||||||
401 | * @see AdminListHelper::addRowCell() |
|||||||||||
402 | * |
|||||||||||
403 | * @api |
|||||||||||
404 | */ |
|||||||||||
405 | abstract public function generateRow(&$row, $data); |
|||||||||||
406 | ||||||||||||
407 | /** |
|||||||||||
408 | * Генерирует HTML для поля фильтрации. |
|||||||||||
409 | * |
|||||||||||
410 | * @return void |
|||||||||||
411 | * |
|||||||||||
412 | * @see AdminListHelper::createFilterForm() |
|||||||||||
413 | * |
|||||||||||
414 | * @api |
|||||||||||
415 | */ |
|||||||||||
416 | abstract public function showFilterHtml(); |
|||||||||||
417 | ||||||||||||
418 | /** |
|||||||||||
419 | * Возвращает массив настроек данного виджета, либо значение отдельного параметра, если указано его имя. |
|||||||||||
420 | * |
|||||||||||
421 | * @param string $name Название конкретного параметра. |
|||||||||||
422 | * |
|||||||||||
423 | * @return array|mixed |
|||||||||||
424 | * |
|||||||||||
425 | * @api |
|||||||||||
426 | */ |
|||||||||||
427 | public function getSettings($name = '') |
|||||||||||
428 | { |
|||||||||||
429 | if (empty($name)) { |
|||||||||||
430 | return $this->settings; |
|||||||||||
431 | } else { |
|||||||||||
432 | if (isset($this->settings[$name])) { |
|||||||||||
433 | return $this->settings[$name]; |
|||||||||||
434 | } else { |
|||||||||||
435 | if (isset(static::$defaults[$name])) { |
|||||||||||
436 | return static::$defaults[$name]; |
|||||||||||
437 | } else { |
|||||||||||
438 | return false; |
|||||||||||
439 | } |
|||||||||||
440 | } |
|||||||||||
441 | } |
|||||||||||
442 | } |
|||||||||||
443 | ||||||||||||
444 | /** |
|||||||||||
445 | * Передаёт в виджет ссылку на вызывающий его объект. |
|||||||||||
446 | * |
|||||||||||
447 | * @param AdminBaseHelper $helper |
|||||||||||
448 | */ |
|||||||||||
449 | public function setHelper(&$helper) |
|||||||||||
450 | { |
|||||||||||
451 | $this->helper = $helper; |
|||||||||||
452 | } |
|||||||||||
453 | ||||||||||||
454 | /** |
|||||||||||
455 | * Возвращает текукщее значение поля фильтрации (спец. символы экранированы). |
|||||||||||
456 | * |
|||||||||||
457 | * @return bool|string |
|||||||||||
458 | */ |
|||||||||||
459 | protected function getCurrentFilterValue() |
|||||||||||
0 ignored issues
–
show
getCurrentFilterValue uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
||||||||||||
460 | { |
|||||||||||
461 | if (isset($GLOBALS[$this->filterFieldPrefix . $this->code])) { |
|||||||||||
462 | return htmlspecialcharsbx($GLOBALS[$this->filterFieldPrefix . $this->code]); |
|||||||||||
463 | } else { |
|||||||||||
464 | return false; |
|||||||||||
465 | } |
|||||||||||
466 | } |
|||||||||||
467 | ||||||||||||
468 | /** |
|||||||||||
469 | * Проверяет корректность введенных в фильтр значений |
|||||||||||
470 | * |
|||||||||||
471 | * @param string $operationType тип операции |
|||||||||||
472 | * @param mixed $value значение фильтра |
|||||||||||
473 | * |
|||||||||||
474 | * @see AdminListHelper::checkFilter(); |
|||||||||||
475 | * @return bool |
|||||||||||
476 | */ |
|||||||||||
477 | public function checkFilter($operationType, $value) |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
478 | { |
|||||||||||
479 | return true; |
|||||||||||
480 | } |
|||||||||||
481 | ||||||||||||
482 | /** |
|||||||||||
483 | * Позволяет модифицировать опции, передаваемые в getList, непосредственно перед выборкой. |
|||||||||||
484 | * Если в настройках явно указан способ фильтрации, до добавляет соответствующий префикс в $arFilter. |
|||||||||||
485 | * Если фильтр BETWEEN, то формирует сложную логику фильтрации. |
|||||||||||
486 | * |
|||||||||||
487 | * @param array $filter $arFilter целиком |
|||||||||||
488 | * @param array $select |
|||||||||||
489 | * @param $sort |
|||||||||||
490 | * @param array $raw $arSelect, $arFilter, $arSort до примененных к ним преобразований. |
|||||||||||
491 | * |
|||||||||||
492 | * @see AdlinListHelper::getData(); |
|||||||||||
493 | */ |
|||||||||||
494 | public function changeGetListOptions(&$filter, &$select, &$sort, $raw) |
|||||||||||
0 ignored issues
–
show
changeGetListOptions uses the super-global variable $_REQUEST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
||||||||||||
495 | { |
|||||||||||
496 | if ($this->isFilterBetween()) { |
|||||||||||
497 | $field = $this->getCode(); |
|||||||||||
498 | $from = $to = false; |
|||||||||||
499 | ||||||||||||
500 | if (isset($_REQUEST['find_' . $field . '_from'])) { |
|||||||||||
501 | $from = $_REQUEST['find_' . $field . '_from']; |
|||||||||||
502 | if (is_a($this, 'DateWidget')) { |
|||||||||||
503 | $from = date('Y-m-d H:i:s', strtotime($from)); |
|||||||||||
504 | } |
|||||||||||
505 | } |
|||||||||||
506 | if (isset($_REQUEST['find_' . $field . '_to'])) { |
|||||||||||
507 | $to = $_REQUEST['find_' . $field . '_to']; |
|||||||||||
508 | if (is_a($this, 'DateWidget')) { |
|||||||||||
509 | $to = date('Y-m-d 23:59:59', strtotime($to)); |
|||||||||||
510 | } else if ( |
|||||||||||
511 | is_a($this, '\DigitalWand\AdminHelper\Widget\DateTimeWidget') && |
|||||||||||
512 | !preg_match('/\d{2}:\d{2}:\d{2}/', $to) |
|||||||||||
513 | ) { |
|||||||||||
514 | $to = date('d.m.Y 23:59:59', strtotime($to)); |
|||||||||||
515 | } |
|||||||||||
516 | } |
|||||||||||
517 | ||||||||||||
518 | if ($from !== false AND $to !== false) { |
|||||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
519 | $filter['><' . $field] = array($from, $to); |
|||||||||||
520 | } else { |
|||||||||||
521 | if ($from !== false) { |
|||||||||||
522 | $filter['>' . $field] = $from; |
|||||||||||
523 | } else { |
|||||||||||
524 | if ($to !== false) { |
|||||||||||
525 | $filter['<' . $field] = $to; |
|||||||||||
526 | } |
|||||||||||
527 | } |
|||||||||||
528 | } |
|||||||||||
529 | } else { |
|||||||||||
530 | if ($filterPrefix = $this->getSettings('FILTER') AND $filterPrefix !== true AND isset($filter[$this->getCode()])) { |
|||||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
and instead of && is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
531 | $filter[$filterPrefix . $this->getCode()] = $filter[$this->getCode()]; |
|||||||||||
532 | unset($filter[$this->getCode()]); |
|||||||||||
533 | } |
|||||||||||
534 | } |
|||||||||||
535 | } |
|||||||||||
536 | ||||||||||||
537 | /** |
|||||||||||
538 | * Проверяет оператор фильтрации. |
|||||||||||
539 | * |
|||||||||||
540 | * @return bool |
|||||||||||
541 | */ |
|||||||||||
542 | protected function isFilterBetween() |
|||||||||||
543 | { |
|||||||||||
544 | return $this->getSettings('FILTER') === '><' OR $this->getSettings('FILTER') === 'BETWEEN'; |
|||||||||||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
Using logical operators such as
or instead of || is generally not recommended.
PHP has two types of connecting operators (logical operators, and boolean operators):
The difference between these is the order in which they are executed. In most cases,
you would want to use a boolean operator like Let’s take a look at a few examples: // Logical operators have lower precedence:
$f = false or true;
// is executed like this:
($f = false) or true;
// Boolean operators have higher precedence:
$f = false || true;
// is executed like this:
$f = (false || true);
Logical Operators are used for Control-FlowOne case where you explicitly want to use logical operators is for control-flow such as this: $x === 5
or die('$x must be 5.');
// Instead of
if ($x !== 5) {
die('$x must be 5.');
}
Since // The following is currently a parse error.
$x === 5
or throw new RuntimeException('$x must be 5.');
These limitations lead to logical operators rarely being of use in current PHP code. ![]() |
||||||||||||
545 | } |
|||||||||||
546 | ||||||||||||
547 | /** |
|||||||||||
548 | * Действия, выполняемые над полем в процессе редактирования элемента, до его сохранения. |
|||||||||||
549 | * По-умолчанию выполняется проверка обязательных полей и уникальности. |
|||||||||||
550 | * |
|||||||||||
551 | * @see AdminEditHelper::editAction(); |
|||||||||||
552 | * @see AdminListHelper::editAction(); |
|||||||||||
553 | */ |
|||||||||||
554 | public function processEditAction() |
|||||||||||
555 | { |
|||||||||||
556 | if (!$this->checkRequired()) { |
|||||||||||
557 | $this->addError('DIGITALWAND_AH_REQUIRED_FIELD_ERROR'); |
|||||||||||
558 | } |
|||||||||||
559 | if ($this->getSettings('UNIQUE') && !$this->isUnique()) { |
|||||||||||
560 | $this->addError('DIGITALWAND_AH_DUPLICATE_FIELD_ERROR'); |
|||||||||||
561 | } |
|||||||||||
562 | } |
|||||||||||
563 | ||||||||||||
564 | /** |
|||||||||||
565 | * В совсем экзотических случаях может потребоваться моджифицировать значение поля уже после его сохраненния в БД - |
|||||||||||
566 | * для последующей обработки каким-либо другим классом. |
|||||||||||
567 | */ |
|||||||||||
568 | public function processAfterSaveAction() |
|||||||||||
569 | { |
|||||||||||
570 | } |
|||||||||||
571 | ||||||||||||
572 | /** |
|||||||||||
573 | * Добавляет строку ошибки в массив ошибок. |
|||||||||||
574 | * |
|||||||||||
575 | * @param string $messageId Код сообщения об ошибке из лэнг-файла. Плейсхолдер #FIELD# будет заменён на значение |
|||||||||||
576 | * параметра TITLE. |
|||||||||||
577 | * @param array $replace Данные для замены. |
|||||||||||
578 | * |
|||||||||||
579 | * @see Loc::getMessage() |
|||||||||||
580 | */ |
|||||||||||
581 | protected function addError($messageId, $replace = array()) |
|||||||||||
582 | { |
|||||||||||
583 | $this->validationErrors[$this->getCode()] = Loc::getMessage( |
|||||||||||
584 | $messageId, |
|||||||||||
585 | array_merge(array('#FIELD#' => $this->getSettings('TITLE')), $replace) |
|||||||||||
586 | ); |
|||||||||||
587 | } |
|||||||||||
588 | ||||||||||||
589 | /** |
|||||||||||
590 | * Проверка заполненности обязательных полей. |
|||||||||||
591 | * Не должны быть null или содержать пустую строку. |
|||||||||||
592 | * |
|||||||||||
593 | * @return bool |
|||||||||||
594 | */ |
|||||||||||
595 | View Code Duplication | public function checkRequired() |
||||||||||
0 ignored issues
–
show
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. ![]() |
||||||||||||
596 | { |
|||||||||||
597 | if ($this->getSettings('REQUIRED') == true) { |
|||||||||||
598 | $value = $this->getValue(); |
|||||||||||
599 | ||||||||||||
600 | return !is_null($value) && !empty($value); |
|||||||||||
601 | } else { |
|||||||||||
602 | return true; |
|||||||||||
603 | } |
|||||||||||
604 | } |
|||||||||||
605 | ||||||||||||
606 | /** |
|||||||||||
607 | * Выставляет код для данного виджета при инициализации. Перегружает настройки. |
|||||||||||
608 | * |
|||||||||||
609 | * @param string $code |
|||||||||||
610 | */ |
|||||||||||
611 | public function setCode($code) |
|||||||||||
612 | { |
|||||||||||
613 | $this->code = $code; |
|||||||||||
614 | $this->loadSettings(); |
|||||||||||
615 | } |
|||||||||||
616 | ||||||||||||
617 | /** |
|||||||||||
618 | * @return mixed |
|||||||||||
619 | */ |
|||||||||||
620 | public function getCode() |
|||||||||||
621 | { |
|||||||||||
622 | return $this->code; |
|||||||||||
623 | } |
|||||||||||
624 | ||||||||||||
625 | /** |
|||||||||||
626 | * Устанавливает настройки интерфейса для текущего поля. |
|||||||||||
627 | * |
|||||||||||
628 | * @param string $code |
|||||||||||
629 | * |
|||||||||||
630 | * @return bool |
|||||||||||
631 | * |
|||||||||||
632 | * @see AdminBaseHelper::getInterfaceSettings() |
|||||||||||
633 | * @see AdminBaseHelper::setFields() |
|||||||||||
634 | */ |
|||||||||||
635 | public function loadSettings($code = null) |
|||||||||||
636 | { |
|||||||||||
637 | $interface = $this->helper->getInterfaceSettings(); |
|||||||||||
638 | ||||||||||||
639 | $code = is_null($code) ? $this->code : $code; |
|||||||||||
640 | ||||||||||||
641 | if (!isset($interface['FIELDS'][$code])) { |
|||||||||||
642 | return false; |
|||||||||||
643 | } |
|||||||||||
644 | unset($interface['FIELDS'][$code]['WIDGET']); |
|||||||||||
645 | $this->settings = array_merge($this->settings, $interface['FIELDS'][$code]); |
|||||||||||
646 | $this->setDefaultValue(); |
|||||||||||
647 | ||||||||||||
648 | return true; |
|||||||||||
649 | } |
|||||||||||
650 | ||||||||||||
651 | /** |
|||||||||||
652 | * Возвращает название сущности данной модели. |
|||||||||||
653 | * |
|||||||||||
654 | * @return string|DataManager |
|||||||||||
655 | */ |
|||||||||||
656 | public function getEntityName() |
|||||||||||
657 | { |
|||||||||||
658 | return $this->entityName; |
|||||||||||
659 | } |
|||||||||||
660 | ||||||||||||
661 | /** |
|||||||||||
662 | * @param string $entityName |
|||||||||||
663 | */ |
|||||||||||
664 | public function setEntityName($entityName) |
|||||||||||
665 | { |
|||||||||||
666 | $this->entityName = $entityName; |
|||||||||||
0 ignored issues
–
show
It seems like
$entityName of type string is incompatible with the declared type object<Bitrix\Main\Entity\DataManager> of property $entityName .
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.. ![]() |
||||||||||||
667 | $this->setDefaultValue(); |
|||||||||||
668 | } |
|||||||||||
669 | ||||||||||||
670 | /** |
|||||||||||
671 | * Устанавливает значение по-умолчанию для данного поля |
|||||||||||
672 | */ |
|||||||||||
673 | public function setDefaultValue() |
|||||||||||
674 | { |
|||||||||||
675 | if (isset($this->settings['DEFAULT']) && is_null($this->getValue())) { |
|||||||||||
676 | $this->setValue($this->settings['DEFAULT']); |
|||||||||||
677 | } |
|||||||||||
678 | } |
|||||||||||
679 | ||||||||||||
680 | /** |
|||||||||||
681 | * Передает ссылку на данные сущности в виджет |
|||||||||||
682 | * |
|||||||||||
683 | * @param $data |
|||||||||||
684 | */ |
|||||||||||
685 | public function setData(&$data) |
|||||||||||
686 | { |
|||||||||||
687 | $this->data = &$data; |
|||||||||||
688 | //FIXME: нелепый оверхэд ради того, чтобы можно было централизованно преобразовывать значение при записи |
|||||||||||
689 | $this->setValue($data[$this->getCode()]); |
|||||||||||
690 | } |
|||||||||||
691 | ||||||||||||
692 | /** |
|||||||||||
693 | * Возвращает текущее значение, хранимое в поле виджета |
|||||||||||
694 | * Если такого поля нет, возвращает null |
|||||||||||
695 | * |
|||||||||||
696 | * @return mixed|null |
|||||||||||
697 | */ |
|||||||||||
698 | public function getValue() |
|||||||||||
699 | { |
|||||||||||
700 | $code = $this->getCode(); |
|||||||||||
701 | ||||||||||||
702 | return isset($this->data[$code]) ? $this->data[$code] : null; |
|||||||||||
703 | } |
|||||||||||
704 | ||||||||||||
705 | /** |
|||||||||||
706 | * Устанавливает значение поля |
|||||||||||
707 | * |
|||||||||||
708 | * @param $value |
|||||||||||
709 | * |
|||||||||||
710 | * @return bool |
|||||||||||
711 | */ |
|||||||||||
712 | protected function setValue($value) |
|||||||||||
713 | { |
|||||||||||
714 | $code = $this->getCode(); |
|||||||||||
715 | $this->data[$code] = $value; |
|||||||||||
716 | ||||||||||||
717 | return true; |
|||||||||||
718 | } |
|||||||||||
719 | ||||||||||||
720 | /** |
|||||||||||
721 | * Получения названия поля таблицы, в которой хранятся множественные данные этого виджета |
|||||||||||
722 | * |
|||||||||||
723 | * @param string $fieldName Название поля |
|||||||||||
724 | * |
|||||||||||
725 | * @return bool|string |
|||||||||||
726 | */ |
|||||||||||
727 | public function getMultipleField($fieldName) |
|||||||||||
728 | { |
|||||||||||
729 | $fields = $this->getSettings('MULTIPLE_FIELDS'); |
|||||||||||
730 | if (empty($fields)) { |
|||||||||||
731 | return $fieldName; |
|||||||||||
732 | } |
|||||||||||
733 | ||||||||||||
734 | // Поиск алиаса названия поля |
|||||||||||
735 | if (isset($fields[$fieldName])) { |
|||||||||||
736 | return $fields[$fieldName]; |
|||||||||||
737 | } |
|||||||||||
738 | ||||||||||||
739 | // Поиск оригинального названия поля |
|||||||||||
740 | $fieldsFlip = array_flip($fields); |
|||||||||||
741 | ||||||||||||
742 | if (isset($fieldsFlip[$fieldName])) { |
|||||||||||
743 | return $fieldsFlip[$fieldName]; |
|||||||||||
744 | } |
|||||||||||
745 | ||||||||||||
746 | return $fieldName; |
|||||||||||
747 | } |
|||||||||||
748 | ||||||||||||
749 | /** |
|||||||||||
750 | * Выставляет значение отдельной настройки |
|||||||||||
751 | * |
|||||||||||
752 | * @param string $name |
|||||||||||
753 | * @param mixed $value |
|||||||||||
754 | */ |
|||||||||||
755 | public function setSetting($name, $value) |
|||||||||||
756 | { |
|||||||||||
757 | $this->settings[$name] = $value; |
|||||||||||
758 | } |
|||||||||||
759 | ||||||||||||
760 | /** |
|||||||||||
761 | * Возвращает собранные ошибки валидации |
|||||||||||
762 | * @return array |
|||||||||||
763 | */ |
|||||||||||
764 | public function getValidationErrors() |
|||||||||||
765 | { |
|||||||||||
766 | return $this->validationErrors; |
|||||||||||
767 | } |
|||||||||||
768 | ||||||||||||
769 | /** |
|||||||||||
770 | * Возвращает имена для атрибута name полей фильтра. |
|||||||||||
771 | * Если это фильтр BETWEEN, то вернёт массив с вариантами from и to. |
|||||||||||
772 | * |
|||||||||||
773 | * @return array|string |
|||||||||||
774 | */ |
|||||||||||
775 | protected function getFilterInputName() |
|||||||||||
776 | { |
|||||||||||
777 | if ($this->isFilterBetween()) { |
|||||||||||
778 | $baseName = $this->filterFieldPrefix . $this->code;; |
|||||||||||
779 | $inputNameFrom = $baseName . '_from'; |
|||||||||||
780 | $inputNameTo = $baseName . '_to'; |
|||||||||||
781 | ||||||||||||
782 | return array($inputNameFrom, $inputNameTo); |
|||||||||||
783 | } else { |
|||||||||||
784 | return $this->filterFieldPrefix . $this->code; |
|||||||||||
785 | } |
|||||||||||
786 | } |
|||||||||||
787 | ||||||||||||
788 | /** |
|||||||||||
789 | * Возвращает текст для атрибута name инпута редактирования. |
|||||||||||
790 | * |
|||||||||||
791 | * @param null $suffix опциональное дополнение к названию поля |
|||||||||||
792 | * |
|||||||||||
793 | * @return string |
|||||||||||
794 | */ |
|||||||||||
795 | protected function getEditInputName($suffix = null) |
|||||||||||
796 | { |
|||||||||||
797 | return 'FIELDS[' . $this->getCode() . $suffix . ']'; |
|||||||||||
798 | } |
|||||||||||
799 | ||||||||||||
800 | /** |
|||||||||||
801 | * Уникальный ID для DOM HTML |
|||||||||||
802 | * @return string |
|||||||||||
803 | */ |
|||||||||||
804 | protected function getEditInputHtmlId() |
|||||||||||
805 | { |
|||||||||||
806 | $htmlId = end(explode('\\', $this->entityName)) . '-' . $this->getCode(); |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
807 | ||||||||||||
808 | return strtolower(preg_replace('/[^A-z-]/', '-', $htmlId)); |
|||||||||||
809 | } |
|||||||||||
810 | ||||||||||||
811 | /** |
|||||||||||
812 | * Возвращает текст для атрибута name инпута редактирования поля в списке |
|||||||||||
813 | * @return string |
|||||||||||
814 | */ |
|||||||||||
815 | protected function getEditableListInputName() |
|||||||||||
816 | { |
|||||||||||
817 | $id = $this->data['ID']; |
|||||||||||
818 | ||||||||||||
819 | return 'FIELDS[' . $id . '][' . $this->getCode() . ']'; |
|||||||||||
820 | } |
|||||||||||
821 | ||||||||||||
822 | /** |
|||||||||||
823 | * Определяет тип вызывающего хэлпера, от чего может зависить поведение виджета. |
|||||||||||
824 | * |
|||||||||||
825 | * @return bool|int |
|||||||||||
826 | * @see HelperWidget::EDIT_HELPER |
|||||||||||
827 | * @see HelperWidget::LIST_HELPER |
|||||||||||
828 | */ |
|||||||||||
829 | protected function getCurrentViewType() |
|||||||||||
830 | { |
|||||||||||
831 | if (is_a($this->helper, 'DigitalWand\AdminHelper\Helper\AdminListHelper')) { |
|||||||||||
832 | return self::LIST_HELPER; |
|||||||||||
833 | } else { |
|||||||||||
834 | if (is_a($this->helper, 'DigitalWand\AdminHelper\Helper\AdminEditHelper')) { |
|||||||||||
835 | return self::EDIT_HELPER; |
|||||||||||
836 | } |
|||||||||||
837 | } |
|||||||||||
838 | ||||||||||||
839 | return false; |
|||||||||||
840 | } |
|||||||||||
841 | ||||||||||||
842 | /** |
|||||||||||
843 | * Проверяет значение поля на уникальность |
|||||||||||
844 | * @return bool |
|||||||||||
845 | */ |
|||||||||||
846 | private function isUnique() |
|||||||||||
847 | { |
|||||||||||
848 | if ($this->getSettings('VIRTUAL')) { |
|||||||||||
849 | return true; |
|||||||||||
850 | } |
|||||||||||
851 | ||||||||||||
852 | $value = $this->getValue(); |
|||||||||||
853 | if (empty($value)) { |
|||||||||||
854 | return true; |
|||||||||||
855 | } |
|||||||||||
856 | ||||||||||||
857 | /** @var DataManager $class */ |
|||||||||||
858 | $class = $this->entityName; |
|||||||||||
859 | $field = $this->getCode(); |
|||||||||||
860 | $idField = 'ID'; |
|||||||||||
861 | $id = $this->data[$idField]; |
|||||||||||
862 | ||||||||||||
863 | $filter = array( |
|||||||||||
864 | $field => $value, |
|||||||||||
865 | ); |
|||||||||||
866 | ||||||||||||
867 | if (!empty($id)) { |
|||||||||||
868 | $filter["!=" . $idField] = $id; |
|||||||||||
869 | } |
|||||||||||
870 | ||||||||||||
871 | $count = $class::getCount($filter); |
|||||||||||
872 | ||||||||||||
873 | if (!$count) { |
|||||||||||
874 | return true; |
|||||||||||
875 | } |
|||||||||||
876 | ||||||||||||
877 | return false; |
|||||||||||
878 | } |
|||||||||||
879 | ||||||||||||
880 | /** |
|||||||||||
881 | * Проверяет, не является ли текущий запрос попыткой выгрузить данные в Excel |
|||||||||||
882 | * @return bool |
|||||||||||
883 | */ |
|||||||||||
884 | protected function isExcelView() |
|||||||||||
0 ignored issues
–
show
isExcelView uses the super-global variable $_REQUEST which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
![]() |
||||||||||||
885 | { |
|||||||||||
886 | if (isset($_REQUEST['mode']) && $_REQUEST['mode'] == 'excel') { |
|||||||||||
887 | return true; |
|||||||||||
888 | } |
|||||||||||
889 | ||||||||||||
890 | return false; |
|||||||||||
891 | } |
|||||||||||
892 | ||||||||||||
893 | /** |
|||||||||||
894 | * @todo Вынести в ресурс (\CJSCore::Init()). |
|||||||||||
895 | * @todo Описать. |
|||||||||||
896 | */ |
|||||||||||
897 | protected function jsHelper() |
|||||||||||
898 | { |
|||||||||||
899 | if ($this->jsHelper == true) { |
|||||||||||
0 ignored issues
–
show
|
||||||||||||
900 | return true; |
|||||||||||
901 | } |
|||||||||||
902 | ||||||||||||
903 | $this->jsHelper = true; |
|||||||||||
904 | \CJSCore::Init(array("jquery")); |
|||||||||||
905 | ?> |
|||||||||||
906 | <script> |
|||||||||||
907 | /** |
|||||||||||
908 | * Менеджер множественных полей |
|||||||||||
909 | * Позволяет добавлять и удалять любой HTML код с возможность подстановки динамических данных |
|||||||||||
910 | * Инструкция: |
|||||||||||
911 | * - создайте контейнер, где будут хранится отображаться код |
|||||||||||
912 | * - создайте экземпляр MultipleWidgetHelper |
|||||||||||
913 | * Например: var multiple = MultipleWidgetHelper(селектор контейнера, шаблон) |
|||||||||||
914 | * шаблон - это HTML код, который можно будет добавлять и удалять в интерфейсе |
|||||||||||
915 | * В шаблон можно добавлять переменные, их нужно обрамлять фигурными скобками. Например {{entity_id}} |
|||||||||||
916 | * Если в шаблоне несколько полей, переменная {{field_id}} обязательна |
|||||||||||
917 | * Например <input type="text" name="image[{{field_id}}][SRC]"><input type="text" name="image[{{field_id}}][DESCRIPTION]"> |
|||||||||||
918 | * Если добавляемые поле не новое, то обязательно передавайте в addField переменную field_id с ID записи, |
|||||||||||
919 | * для новосозданных полей переменная заполнится автоматически |
|||||||||||
920 | */ |
|||||||||||
921 | function MultipleWidgetHelper(container, fieldTemplate) { |
|||||||||||
922 | this.$container = $(container); |
|||||||||||
923 | if (this.$container.size() == 0) { |
|||||||||||
924 | throw 'Главный контейнер полей не найден (' + container + ')'; |
|||||||||||
925 | } |
|||||||||||
926 | if (!fieldTemplate) { |
|||||||||||
927 | throw 'Не передан обязательный параметр fieldTemplate'; |
|||||||||||
928 | } |
|||||||||||
929 | this.fieldTemplate = fieldTemplate; |
|||||||||||
930 | this._init(); |
|||||||||||
931 | } |
|||||||||||
932 | ||||||||||||
933 | MultipleWidgetHelper.prototype = { |
|||||||||||
934 | /** |
|||||||||||
935 | * Основной контейнер |
|||||||||||
936 | */ |
|||||||||||
937 | $container: null, |
|||||||||||
938 | /** |
|||||||||||
939 | * Контейнер полей |
|||||||||||
940 | */ |
|||||||||||
941 | $fieldsContainer: null, |
|||||||||||
942 | /** |
|||||||||||
943 | * Шаблон поля |
|||||||||||
944 | */ |
|||||||||||
945 | fieldTemplate: null, |
|||||||||||
946 | /** |
|||||||||||
947 | * Счетчик добавлений полей |
|||||||||||
948 | */ |
|||||||||||
949 | fieldsCounter: 0, |
|||||||||||
950 | /** |
|||||||||||
951 | * Добавления поля |
|||||||||||
952 | * @param data object Данные для шаблона в виде ключ: значение |
|||||||||||
953 | */ |
|||||||||||
954 | addField: function (data) { |
|||||||||||
955 | // console.log('Добавление поля'); |
|||||||||||
956 | this.addFieldHtml(this.fieldTemplate, data); |
|||||||||||
957 | }, |
|||||||||||
958 | addFieldHtml: function (fieldTemplate, data) { |
|||||||||||
959 | this.fieldsCounter++; |
|||||||||||
960 | this.$fieldsContainer.append(this._generateFieldContent(fieldTemplate, data)); |
|||||||||||
961 | }, |
|||||||||||
962 | /** |
|||||||||||
963 | * Удаление поля |
|||||||||||
964 | * @param field string|object Селектор или jQuery объект |
|||||||||||
965 | */ |
|||||||||||
966 | deleteField: function (field) { |
|||||||||||
967 | // console.log('Удаление поля'); |
|||||||||||
968 | $(field).remove(); |
|||||||||||
969 | if (this.$fieldsContainer.find('> *').size() == 0) { |
|||||||||||
970 | this.addField(); |
|||||||||||
971 | } |
|||||||||||
972 | }, |
|||||||||||
973 | _init: function () { |
|||||||||||
974 | this.$container.append('<div class="fields-container"></div>'); |
|||||||||||
975 | this.$fieldsContainer = this.$container.find('.fields-container'); |
|||||||||||
976 | this.$container.append(this._getAddButton()); |
|||||||||||
977 | ||||||||||||
978 | this._trackEvents(); |
|||||||||||
979 | }, |
|||||||||||
980 | /** |
|||||||||||
981 | * Генерация контента контейнера поля |
|||||||||||
982 | * @param data |
|||||||||||
983 | * @returns {string} |
|||||||||||
984 | * @private |
|||||||||||
985 | */ |
|||||||||||
986 | _generateFieldContent: function (fieldTemplate, data) { |
|||||||||||
987 | return '<div class="field-container" style="margin-bottom: 5px;">' |
|||||||||||
988 | + this._generateFieldTemplate(fieldTemplate, data) + this._getDeleteButton() |
|||||||||||
989 | + '</div>'; |
|||||||||||
990 | }, |
|||||||||||
991 | /** |
|||||||||||
992 | * Генерация шаблона поля |
|||||||||||
993 | * @param data object Данные для подстановки |
|||||||||||
994 | * @returns {null} |
|||||||||||
995 | * @private |
|||||||||||
996 | */ |
|||||||||||
997 | _generateFieldTemplate: function (fieldTemplate, data) { |
|||||||||||
998 | if (!data) { |
|||||||||||
999 | data = {}; |
|||||||||||
1000 | } |
|||||||||||
1001 | ||||||||||||
1002 | if (typeof data.field_id == 'undefined') { |
|||||||||||
1003 | data.field_id = 'new_' + this.fieldsCounter; |
|||||||||||
1004 | } |
|||||||||||
1005 | ||||||||||||
1006 | $.each(data, function (key, value) { |
|||||||||||
1007 | // Подставление значений переменных |
|||||||||||
1008 | fieldTemplate = fieldTemplate.replace(new RegExp('\{\{' + key + '\}\}', ['g']), value); |
|||||||||||
1009 | }); |
|||||||||||
1010 | ||||||||||||
1011 | // Удаление из шаблона необработанных переменных |
|||||||||||
1012 | fieldTemplate = fieldTemplate.replace(/\{\{.+?\}\}/g, ''); |
|||||||||||
1013 | ||||||||||||
1014 | return fieldTemplate; |
|||||||||||
1015 | }, |
|||||||||||
1016 | /** |
|||||||||||
1017 | * Кнопка удаления |
|||||||||||
1018 | * @returns {string} |
|||||||||||
1019 | * @private |
|||||||||||
1020 | */ |
|||||||||||
1021 | _getDeleteButton: function () { |
|||||||||||
1022 | return '<input type="button" value="-" class="delete-field-button" style="margin-left: 5px;">'; |
|||||||||||
1023 | }, |
|||||||||||
1024 | /** |
|||||||||||
1025 | * Кнопка добавления |
|||||||||||
1026 | * @returns {string} |
|||||||||||
1027 | * @private |
|||||||||||
1028 | */ |
|||||||||||
1029 | _getAddButton: function () { |
|||||||||||
1030 | return '<input type="button" value="Добавить..." class="add-field-button">'; |
|||||||||||
1031 | }, |
|||||||||||
1032 | /** |
|||||||||||
1033 | * Отслеживание событий |
|||||||||||
1034 | * @private |
|||||||||||
1035 | */ |
|||||||||||
1036 | _trackEvents: function () { |
|||||||||||
1037 | var context = this; |
|||||||||||
1038 | // Добавление поля |
|||||||||||
1039 | this.$container.find('.add-field-button').on('click', function () { |
|||||||||||
1040 | context.addField(); |
|||||||||||
1041 | }); |
|||||||||||
1042 | // Удаление поля |
|||||||||||
1043 | this.$container.on('click', '.delete-field-button', function () { |
|||||||||||
1044 | context.deleteField($(this).parents('.field-container')); |
|||||||||||
1045 | }); |
|||||||||||
1046 | } |
|||||||||||
1047 | }; |
|||||||||||
1048 | </script> |
|||||||||||
1049 | <? |
|||||||||||
0 ignored issues
–
show
It is not recommend to use PHP's short opening tag
<? , better use <?php , or <?= in case of outputting.
Short opening tags are disabled in PHP’s default configuration. In such a case, all content of this file is output verbatim to the browser without being parsed, or executed. As a precaution to avoid these problems better use the long opening tag ![]() |
||||||||||||
1050 | } |
|||||||||||
1051 | } |
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.