1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace DigitalWand\AdminHelper\Widget; |
4
|
|
|
|
5
|
|
|
use Bitrix\Main\ArgumentTypeException; |
6
|
|
|
use Bitrix\Main\Localization\Loc; |
7
|
|
|
use DigitalWand\AdminHelper\Helper\AdminBaseHelper; |
8
|
|
|
|
9
|
|
|
Loc::loadMessages(__FILE__); |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Виджет выбора записей из ORM. |
13
|
|
|
* |
14
|
|
|
* Настройки: |
15
|
|
|
* - `HELPER` — (string) класс хелпера, из которого будет производиться поиск записией. Должен быть |
16
|
|
|
* наследником `\DigitalWand\AdminHelper\Helper\AdminBaseHelper`. |
17
|
|
|
* - `ADDITIONAL_URL_PARAMS` — (array) дополнительные параметры для URL с попапом выбора записи. |
18
|
|
|
* - `TEMPLATE` — (string) шаблон отображения виджета, может принимать значения select и radio, по-умолчанию — select. |
19
|
|
|
* - `INPUT_SIZE` — (int) значение атрибута size для input. |
20
|
|
|
* - `WINDOW_WIDTH` — (int) значение width для всплывающего окна выбора элемента. |
21
|
|
|
* - `WINDOW_HEIGHT` — (int) значение height для всплывающего окна выбора элемента. |
22
|
|
|
* - `TITLE_FIELD_NAME` — (string) название поля, из которого выводить имя элемента. |
23
|
|
|
* |
24
|
|
|
* @author Nik Samokhvalov <[email protected]> |
25
|
|
|
*/ |
26
|
|
|
class OrmElementWidget extends NumberWidget |
|
|
|
|
27
|
|
|
{ |
28
|
|
|
protected static $defaults = array( |
29
|
|
|
'FILTER' => '=', |
30
|
|
|
'INPUT_SIZE' => 5, |
31
|
|
|
'WINDOW_WIDTH' => 600, |
32
|
|
|
'WINDOW_HEIGHT' => 500, |
33
|
|
|
'TITLE_FIELD_NAME' => 'TITLE', |
34
|
|
|
'TEMPLATE' => 'select', |
35
|
|
|
'ADDITIONAL_URL_PARAMS' => array() |
36
|
|
|
); |
37
|
|
|
|
38
|
|
|
/** |
39
|
|
|
* @inheritdoc |
40
|
|
|
*/ |
41
|
|
|
public function loadSettings($code = null) |
42
|
|
|
{ |
43
|
|
|
$load = parent::loadSettings($code); |
44
|
|
|
|
45
|
|
|
if (!is_subclass_of($this->getSettings('HELPER'), '\DigitalWand\AdminHelper\Helper\AdminBaseHelper')) |
46
|
|
|
{ |
47
|
|
|
throw new ArgumentTypeException('HELPER', '\DigitalWand\AdminHelper\Helper\AdminBaseHelper'); |
48
|
|
|
} |
49
|
|
|
|
50
|
|
|
if (!is_array($this->getSettings('ADDITIONAL_URL_PARAMS'))) |
51
|
|
|
{ |
52
|
|
|
throw new ArgumentTypeException('ADDITIONAL_URL_PARAMS', 'array'); |
53
|
|
|
} |
54
|
|
|
|
55
|
|
|
return $load; |
56
|
|
|
} |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* @inheritdoc |
60
|
|
|
*/ |
61
|
|
|
public function getEditHtml() |
62
|
|
|
{ |
63
|
|
|
if ($this->getSettings('TEMPLATE') == 'radio') { |
64
|
|
|
$html = $this->genEditHtmlInputs(); |
65
|
|
|
} else { |
66
|
|
|
$html = $this->getEditHtmlSelect(); |
67
|
|
|
} |
68
|
|
|
|
69
|
|
|
return $html; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* Генерирует HTML с выбором элемента во вcплывающем окне, шаблон select. |
74
|
|
|
* |
75
|
|
|
* @return string |
76
|
|
|
*/ |
77
|
|
|
protected function getEditHtmlSelect() |
78
|
|
|
{ |
79
|
|
|
/** |
80
|
|
|
* @var AdminBaseHelper $linkedHelper |
81
|
|
|
*/ |
82
|
|
|
$linkedHelper = $this->getSettings('HELPER'); |
83
|
|
|
$inputSize = (int) $this->getSettings('INPUT_SIZE'); |
84
|
|
|
$windowWidth = (int) $this->getSettings('WINDOW_WIDTH'); |
85
|
|
|
$windowHeight = (int) $this->getSettings('WINDOW_HEIGHT'); |
86
|
|
|
|
87
|
|
|
$name = 'FIELDS'; |
88
|
|
|
$key = $this->getCode(); |
89
|
|
|
|
90
|
|
|
$entityData = $this->getOrmElementData(); |
91
|
|
|
|
92
|
|
|
if (!empty($entityData)) { |
93
|
|
|
$elementId = $entityData['ID']; |
94
|
|
|
$elementName = $entityData[$this->getSettings('TITLE_FIELD_NAME')] ? |
95
|
|
|
$entityData[$this->getSettings('TITLE_FIELD_NAME')] : |
96
|
|
|
Loc::getMessage('IBLOCK_ELEMENT_NOT_FOUND'); |
97
|
|
|
} else { |
98
|
|
|
$elementId = ''; |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
$popupUrl = $linkedHelper::getUrl(array_merge( |
102
|
|
|
array( |
103
|
|
|
'popup' => 'Y', |
104
|
|
|
'eltitle' => $this->getSettings('TITLE_FIELD_NAME'), |
105
|
|
|
'n' => $name, |
106
|
|
|
'k' => $key |
107
|
|
|
), |
108
|
|
|
$this->getSettings('ADDITIONAL_URL_PARAMS') |
109
|
|
|
)); |
110
|
|
|
|
111
|
|
|
return '<input name="' . $this->getEditInputName() . '" |
112
|
|
|
id="' . $name . '[' . $key . ']" |
113
|
|
|
value="' . $elementId . '" |
114
|
|
|
size="' . $inputSize . '" |
115
|
|
|
type="text">' . |
116
|
|
|
'<input type="button" |
117
|
|
|
value="..." onClick="jsUtils.OpenWindow(\''. $popupUrl . '\', ' . $windowWidth . ', ' |
118
|
|
|
. $windowHeight . ');">' . ' <span id="sp_' . md5($name) . '_' . $key . '" >' . |
119
|
|
|
static::prepareToOutput($elementName) |
|
|
|
|
120
|
|
|
. '</span>'; |
121
|
|
|
} |
122
|
|
|
|
123
|
|
|
/** |
124
|
|
|
* Генерирует HTML с выбором элемента в виде радио инпутов. |
125
|
|
|
* |
126
|
|
|
* @return string |
127
|
|
|
*/ |
128
|
|
|
public function genEditHtmlInputs() |
129
|
|
|
{ |
130
|
|
|
$return = ''; |
131
|
|
|
|
132
|
|
|
$elementList = $this->getOrmElementList(); |
133
|
|
|
|
134
|
|
|
if (!is_null($elementList)) { |
135
|
|
|
foreach ($elementList as $key => $element) { |
136
|
|
|
$return .= InputType("radio", $this->getEditInputName(), $element['ID'], $this->getValue(), false, $element['TITLE']); |
137
|
|
|
} |
138
|
|
|
} else { |
139
|
|
|
$return = Loc::getMessage('DIGITALWAND_AH_ORM_MISSING_ELEMENTS'); |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
return $return; |
143
|
|
|
} |
144
|
|
|
|
145
|
|
|
/** |
146
|
|
|
* @inheritdoc |
147
|
|
|
*/ |
148
|
|
|
public function getMultipleEditHtml() |
149
|
|
|
{ |
150
|
|
|
/** |
151
|
|
|
* @var AdminBaseHelper $linkedHelper |
152
|
|
|
*/ |
153
|
|
|
$linkedHelper = $this->getSettings('HELPER'); |
154
|
|
|
$inputSize = (int)$this->getSettings('INPUT_SIZE'); |
155
|
|
|
$windowWidth = (int)$this->getSettings('WINDOW_WIDTH'); |
156
|
|
|
$windowHeight = (int)$this->getSettings('WINDOW_HEIGHT'); |
157
|
|
|
|
158
|
|
|
$name = 'FIELDS'; |
159
|
|
|
$key = $this->getCode(); |
160
|
|
|
|
161
|
|
|
$uniqueId = $this->getEditInputHtmlId(); |
162
|
|
|
|
163
|
|
|
$entityListData = $this->getOrmElementData(); |
164
|
|
|
|
165
|
|
|
$popupUrl = $linkedHelper::getUrl(array_merge( |
166
|
|
|
array( |
167
|
|
|
'popup' => 'Y', |
168
|
|
|
'eltitle' => $this->getSettings('TITLE_FIELD_NAME'), |
169
|
|
|
'n' => $name, |
170
|
|
|
'k' => '{{field_id}}' |
171
|
|
|
), |
172
|
|
|
$this->getSettings('ADDITIONAL_URL_PARAMS') |
173
|
|
|
)); |
174
|
|
|
|
175
|
|
|
ob_start(); |
176
|
|
|
?> |
177
|
|
|
|
178
|
|
|
<div id="<?= $uniqueId ?>-field-container" class="<?= $uniqueId ?>"></div> |
179
|
|
|
|
180
|
|
|
<script> |
181
|
|
|
var multiple = new MultipleWidgetHelper( |
182
|
|
|
'#<?= $uniqueId ?>-field-container', |
183
|
|
|
'<input name="<?=$key?>[{{field_id}}][VALUE]"' + |
184
|
|
|
'id="<?=$name?>[{{field_id}}]"' + |
185
|
|
|
'value="{{value}}"' + |
186
|
|
|
'size="<?=$inputSize?>"' + |
187
|
|
|
'type="text">' + |
188
|
|
|
'<input type="button"' + |
189
|
|
|
'value="..."' + |
190
|
|
|
'onClick="jsUtils.OpenWindow(\'<?=$popupUrl?>\', <?=$windowWidth?>, <?=$windowHeight?>);">' + |
191
|
|
|
' <span id="sp_<?=md5($name)?>_{{field_id}}" >{{element_title}}</span>' |
192
|
|
|
); |
193
|
|
|
<? |
|
|
|
|
194
|
|
|
if (!empty($entityListData)) |
195
|
|
|
{ |
196
|
|
|
foreach($entityListData as $referenceData) |
197
|
|
|
{ |
198
|
|
|
$elementId = $referenceData['ID']; |
199
|
|
|
$elementName = $referenceData[$this->getSettings('TITLE_FIELD_NAME')] ? |
200
|
|
|
$referenceData[$this->getSettings('TITLE_FIELD_NAME')] : |
201
|
|
|
Loc::getMessage('IBLOCK_ELEMENT_NOT_FOUND'); |
202
|
|
|
|
203
|
|
|
?> |
204
|
|
|
multiple.addField({ |
205
|
|
|
value: '<?= $elementId ?>', |
206
|
|
|
field_id: <?= $elementId ?>, |
207
|
|
|
element_title: '<?= static::prepareToJs($elementName) ?>' |
208
|
|
|
}); |
209
|
|
|
<? |
210
|
|
|
} |
211
|
|
|
} |
212
|
|
|
?> |
213
|
|
|
multiple.addField(); |
214
|
|
|
</script> |
215
|
|
|
<? |
216
|
|
|
return ob_get_clean(); |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
/** |
220
|
|
|
* @inheritdoc |
221
|
|
|
*/ |
222
|
|
|
public function getValueReadonly() |
223
|
|
|
{ |
224
|
|
|
$entityData = $this->getOrmElementData(); |
225
|
|
|
|
226
|
|
|
if (!empty($entityData)) { |
227
|
|
|
$entityName = $entityData[$this->getSettings('TITLE_FIELD_NAME')] ? |
228
|
|
|
$entityData[$this->getSettings('TITLE_FIELD_NAME')] : |
229
|
|
|
Loc::getMessage('IBLOCK_ELEMENT_NOT_FOUND'); |
230
|
|
|
|
231
|
|
|
return '[' . $entityData['ID'] . ']' . static::prepareToOutput($entityName); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
return ''; |
235
|
|
|
} |
236
|
|
|
|
237
|
|
|
/** |
238
|
|
|
* @inheritdoc |
239
|
|
|
*/ |
240
|
|
|
public function getMultipleValueReadonly() |
241
|
|
|
{ |
242
|
|
|
$entityListData = $this->getOrmElementData(); |
243
|
|
|
|
244
|
|
|
if (!empty($entityListData)) { |
245
|
|
|
$multipleData = array(); |
246
|
|
|
|
247
|
|
|
foreach ($entityListData as $entityData) { |
248
|
|
|
$entityName = $entityData[$this->getSettings('TITLE_FIELD_NAME')] ? |
249
|
|
|
$entityData[$this->getSettings('TITLE_FIELD_NAME')] : |
250
|
|
|
Loc::getMessage('IBLOCK_ELEMENT_NOT_FOUND'); |
251
|
|
|
|
252
|
|
|
$multipleData[] = '[' . $entityData['ID'] . ']' . static::prepareToOutput($entityName); |
253
|
|
|
} |
254
|
|
|
|
255
|
|
|
return implode('<br />', $multipleData); |
256
|
|
|
} |
257
|
|
|
|
258
|
|
|
return ''; |
259
|
|
|
} |
260
|
|
|
|
261
|
|
|
/** |
262
|
|
|
* @inheritdoc |
263
|
|
|
*/ |
264
|
|
|
public function generateRow(&$row, $data) |
265
|
|
|
{ |
266
|
|
|
if ($this->getSettings('MULTIPLE')) { |
267
|
|
|
$strElement = $this->getMultipleValueReadonly(); |
268
|
|
|
} else { |
269
|
|
|
$strElement = $this->getValueReadonly(); |
270
|
|
|
} |
271
|
|
|
|
272
|
|
|
$row->AddViewField($this->getCode(), $strElement); |
273
|
|
|
} |
274
|
|
|
|
275
|
|
|
/** |
276
|
|
|
* @inheritdoc |
277
|
|
|
*/ |
278
|
|
|
public function showFilterHtml() |
279
|
|
|
{ |
280
|
|
|
/** |
281
|
|
|
* @var AdminBaseHelper $linkedHelper |
282
|
|
|
*/ |
283
|
|
|
$linkedHelper = $this->getSettings('HELPER'); |
284
|
|
|
|
285
|
|
|
if ($this->getSettings('MULTIPLE')) { |
286
|
|
|
|
287
|
|
|
} else { |
288
|
|
|
$inputSize = (int) $this->getSettings('INPUT_SIZE'); |
289
|
|
|
$windowWidth = (int) $this->getSettings('WINDOW_WIDTH'); |
290
|
|
|
$windowHeight = (int) $this->getSettings('WINDOW_HEIGHT'); |
291
|
|
|
|
292
|
|
|
$name = 'FIND'; |
293
|
|
|
$key = $this->getCode(); |
294
|
|
|
|
295
|
|
|
print '<tr>'; |
296
|
|
|
print '<td>' . $this->getSettings('TITLE') . '</td>'; |
297
|
|
|
|
298
|
|
|
$popupUrl = $linkedHelper::getUrl(array_merge( |
299
|
|
|
array( |
300
|
|
|
'popup' => 'Y', |
301
|
|
|
'eltitle' => $this->getSettings('TITLE_FIELD_NAME'), |
302
|
|
|
'n' => $name, |
303
|
|
|
'k' => $key |
304
|
|
|
), |
305
|
|
|
$this->getSettings('ADDITIONAL_URL_PARAMS') |
306
|
|
|
)); |
307
|
|
|
|
308
|
|
|
$editStr = '<input name="' . $this->getFilterInputName() . '" |
309
|
|
|
id="' . $name . '[' . $key . ']" |
310
|
|
|
value="' . $this->getCurrentFilterValue() . '" |
311
|
|
|
size="' . $inputSize . '" |
312
|
|
|
type="text">' . |
313
|
|
|
'<input type="button" |
314
|
|
|
value="..." |
315
|
|
|
onClick="jsUtils.OpenWindow(\'' . $popupUrl . '\', ' . $windowWidth . ', ' . $windowHeight . ');">'; |
316
|
|
|
|
317
|
|
|
print '<td>' . $editStr . '</td>'; |
318
|
|
|
|
319
|
|
|
print '</tr>'; |
320
|
|
|
} |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Получает информацию о записях, к которым осуществлена привязка. |
325
|
|
|
* |
326
|
|
|
* @return array |
327
|
|
|
* @throws \Bitrix\Main\ArgumentException |
328
|
|
|
*/ |
329
|
|
|
protected function getOrmElementData() |
330
|
|
|
{ |
331
|
|
|
$refInfo = array(); |
332
|
|
|
$valueList = null; |
333
|
|
|
$linkedModel = $this->getLinkedModel(); |
334
|
|
|
|
335
|
|
|
if ($this->getSettings('MULTIPLE')) { |
336
|
|
|
$entityName = $this->entityName; |
337
|
|
|
|
338
|
|
|
$rsMultEntity = $entityName::getList(array( |
339
|
|
|
'select' => array('REFERENCE_' => $this->getCode() . '.*'), |
340
|
|
|
'filter' => array('=ID' => $this->data['ID']) |
341
|
|
|
)); |
342
|
|
|
|
343
|
|
|
while ($multEntity = $rsMultEntity->fetch()) { |
344
|
|
|
$valueList[$multEntity['REFERENCE_VALUE']] = $multEntity['REFERENCE_VALUE']; |
345
|
|
|
} |
346
|
|
|
} else { |
347
|
|
|
$value = $this->getValue(); |
348
|
|
|
|
349
|
|
|
if (!empty($value)) { |
350
|
|
|
$valueList[$value] = $value; |
351
|
|
|
} |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
if ($valueList) { |
355
|
|
|
$rsEntity = $linkedModel::getList(array( |
356
|
|
|
'filter' => array('ID' => $valueList) |
357
|
|
|
)); |
358
|
|
|
|
359
|
|
|
while ($entity = $rsEntity->fetch()) { |
360
|
|
|
if (in_array($entity['ID'], $valueList)) { |
361
|
|
|
unset($valueList[$entity['ID']]); |
362
|
|
|
} |
363
|
|
|
|
364
|
|
|
if ($this->getSettings('MULTIPLE')) { |
365
|
|
|
$refInfo[] = $entity; |
366
|
|
|
} else { |
367
|
|
|
$refInfo = $entity; |
368
|
|
|
break; |
369
|
|
|
} |
370
|
|
|
} |
371
|
|
|
|
372
|
|
|
foreach ($valueList as $entityId) { |
373
|
|
|
if ($this->getSettings('MULTIPLE')) { |
374
|
|
|
$refInfo[] = array('ID' => $entityId); |
375
|
|
|
} else { |
376
|
|
|
$refInfo = array('ID' => $entityId); |
377
|
|
|
break; |
378
|
|
|
} |
379
|
|
|
} |
380
|
|
|
} |
381
|
|
|
|
382
|
|
|
return $refInfo; |
383
|
|
|
} |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Получает информацию о всех активных элементах для их выбора в виджете. |
387
|
|
|
* |
388
|
|
|
* @return array |
389
|
|
|
* |
390
|
|
|
* @throws \Bitrix\Main\ArgumentException |
391
|
|
|
*/ |
392
|
|
|
protected function getOrmElementList() |
393
|
|
|
{ |
394
|
|
|
$valueList = null; |
395
|
|
|
$linkedModel = $this->getLinkedModel(); |
396
|
|
|
|
397
|
|
|
$rsEntity = $linkedModel::getList(array( |
398
|
|
|
'filter' => array( |
399
|
|
|
'ACTIVE' => 1 |
400
|
|
|
), |
401
|
|
|
'select' => array( |
402
|
|
|
'ID', |
403
|
|
|
'TITLE' |
404
|
|
|
) |
405
|
|
|
)); |
406
|
|
|
|
407
|
|
|
while ($entity = $rsEntity->fetch()) { |
408
|
|
|
$valueList[] = $entity; |
409
|
|
|
} |
410
|
|
|
|
411
|
|
|
return $valueList; |
412
|
|
|
} |
413
|
|
|
|
414
|
|
|
/** |
415
|
|
|
* Возвращает связанную модель. |
416
|
|
|
* |
417
|
|
|
* @return \Bitrix\Main\Entity\DataManager |
418
|
|
|
*/ |
419
|
|
|
protected function getLinkedModel() |
420
|
|
|
{ |
421
|
|
|
/** |
422
|
|
|
* @var \DigitalWand\AdminHelper\Helper\AdminBaseHelper $linkedHelper |
423
|
|
|
*/ |
424
|
|
|
$linkedHelper = $this->getSettings('HELPER'); |
425
|
|
|
|
426
|
|
|
return $linkedHelper::getModel(); |
427
|
|
|
} |
428
|
|
|
} |
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.