1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
namespace DigitalWand\AdminHelper\Helper; |
4
|
|
|
|
5
|
|
|
use Bitrix\Main\Localization\Loc; |
6
|
|
|
use DigitalWand\AdminHelper\EntityManager; |
7
|
|
|
use DigitalWand\AdminHelper\Widget\HelperWidget; |
8
|
|
|
use Bitrix\Main\Entity\DataManager; |
9
|
|
|
|
10
|
|
|
Loc::loadMessages(__FILE__); |
11
|
|
|
|
12
|
|
|
/** |
13
|
|
|
* Базовый класс для реализации детальной страницы админки. |
14
|
|
|
* При создании своего класса необходимо переопределить следующие переменные: |
15
|
|
|
* <ul> |
16
|
|
|
* <li> static protected $model</li> |
17
|
|
|
* </ul> |
18
|
|
|
* |
19
|
|
|
* Этого будет дастаточно для получения минимальной функциональности. |
20
|
|
|
* |
21
|
|
|
* @package AdminHelper |
22
|
|
|
* |
23
|
|
|
* @see AdminBaseHelper::$model |
24
|
|
|
* @see AdminBaseHelper::$module |
25
|
|
|
* @see AdminBaseHelper::$listViewName |
26
|
|
|
* @see AdminBaseHelper::$viewName |
27
|
|
|
* |
28
|
|
|
* @author Nik Samokhvalov <[email protected]> |
29
|
|
|
* @author Artem Yarygin <[email protected]> |
30
|
|
|
*/ |
31
|
|
|
abstract class AdminEditHelper extends AdminBaseHelper |
32
|
|
|
{ |
33
|
|
|
const OP_SHOW_TAB_ELEMENTS = 'AdminEditHelper::showTabElements'; |
34
|
|
|
const OP_EDIT_ACTION_BEFORE = 'AdminEditHelper::editAction_before'; |
35
|
|
|
const OP_EDIT_ACTION_AFTER = 'AdminEditHelper::editAction_after'; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var array Данные сущности, редактируемой в данный момент. Ключи ассива — названия полей в БД. |
39
|
|
|
* @api |
40
|
|
|
*/ |
41
|
|
|
protected $data; |
42
|
|
|
/** |
43
|
|
|
* @var array Вкладки страницы редактирования. |
44
|
|
|
*/ |
45
|
|
|
protected $tabs = array(); |
46
|
|
|
/** |
47
|
|
|
* @var array Элементы верхнего меню страницы. |
48
|
|
|
* @see AdminEditHelper::fillMenu() |
49
|
|
|
*/ |
50
|
|
|
protected $menu = array(); |
51
|
|
|
/** |
52
|
|
|
* @var \CAdminForm |
53
|
|
|
*/ |
54
|
|
|
protected $tabControl; |
55
|
|
|
|
56
|
|
|
/** |
57
|
|
|
* Производится инициализация переменных, обработка запросов на редактирование |
58
|
|
|
* |
59
|
|
|
* @param array $fields |
60
|
|
|
* @param array $tabs |
61
|
|
|
*/ |
62
|
|
|
public function __construct(array $fields, array $tabs = array()) |
|
|
|
|
63
|
|
|
{ |
64
|
|
|
$this->tabs = $tabs; |
65
|
|
|
|
66
|
|
|
if (empty($this->tabs)) { |
67
|
|
|
$this->tabs = array( |
68
|
|
|
array( |
69
|
|
|
'DIV' => 'DEFAULT_TAB', |
70
|
|
|
'TAB' => Loc::getMessage('DEFAULT_TAB'), |
71
|
|
|
'ICON' => 'main_user_edit', |
72
|
|
|
'TITLE' => Loc::getMessage('DEFAULT_TAB'), |
73
|
|
|
'VISIBLE' => true, |
74
|
|
|
) |
75
|
|
|
); |
76
|
|
|
} |
77
|
|
|
else { |
78
|
|
|
if (!is_array(reset($this->tabs))) { |
79
|
|
|
$converted = array(); |
80
|
|
|
|
81
|
|
|
foreach ($this->tabs as $tabCode => $tabName) { |
82
|
|
|
$tabVisible = true; |
83
|
|
|
|
84
|
|
|
if (is_array($tabName)) { |
85
|
|
|
$tabVisible = isset($tabName['VISIBLE']) ? $tabName['VISIBLE'] : $tabVisible; |
86
|
|
|
$tabName = $tabName['TITLE']; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
$converted[] = array( |
90
|
|
|
'DIV' => $tabCode, |
91
|
|
|
'TAB' => $tabName, |
92
|
|
|
'ICON' => '', |
93
|
|
|
'TITLE' => $tabName, |
94
|
|
|
'VISIBLE' => $tabVisible, |
95
|
|
|
); |
96
|
|
|
} |
97
|
|
|
$this->tabs = $converted; |
98
|
|
|
} |
99
|
|
|
} |
100
|
|
|
|
101
|
|
|
parent::__construct($fields, $tabs); |
102
|
|
|
|
103
|
|
|
$this->tabControl = new \CAdminForm(str_replace("\\", "", get_called_class()), $this->tabs); |
104
|
|
|
|
105
|
|
|
if (isset($_REQUEST['apply']) OR isset($_REQUEST['save'])) { |
|
|
|
|
106
|
|
|
if ( |
107
|
|
|
isset($_SERVER["HTTP_BX_AJAX"]) |
108
|
|
|
|| |
109
|
|
|
isset($_SERVER["HTTP_X_REQUESTED_WITH"]) && $_SERVER["HTTP_X_REQUESTED_WITH"] === "XMLHttpRequest" |
110
|
|
|
) { |
111
|
|
|
\CUtil::JSPostUnescape(); |
112
|
|
|
} |
113
|
|
|
$this->data = $_REQUEST['FIELDS']; |
114
|
|
|
|
115
|
|
|
if (isset($_REQUEST[$this->pk()])) { |
116
|
|
|
//Первичный ключ проставляем отдельно, чтобы не вынуждать всегда указывать его в настройках интерфейса. |
117
|
|
|
$this->data[$this->pk()] = $_REQUEST[$this->pk()]; |
118
|
|
|
} |
119
|
|
|
|
120
|
|
|
foreach ($fields as $code => $settings) { |
121
|
|
|
if (isset($_REQUEST[$code])) { |
122
|
|
|
$this->data[$code] = $_REQUEST[$code]; |
123
|
|
|
} |
124
|
|
|
} |
125
|
|
|
|
126
|
|
|
if ($this->editAction()) { |
127
|
|
|
if (isset($_REQUEST['apply'])) { |
128
|
|
|
$id = $this->data[$this->pk()]; |
129
|
|
|
$url = $this->app->GetCurPageParam($this->pk() . '=' . (is_array($id) ? $id[$this->pk()] : $id), array('ID')); |
130
|
|
|
} |
131
|
|
|
else { |
132
|
|
|
if (isset($_REQUEST['save'])) { |
133
|
|
|
$listHelperClass = static::getHelperClass(AdminListHelper::className()); |
134
|
|
|
$url = $listHelperClass::getUrl(array_merge($this->additionalUrlParams, |
135
|
|
|
array( |
136
|
|
|
'restore_query' => 'Y' |
137
|
|
|
))); |
138
|
|
|
} |
139
|
|
|
} |
140
|
|
|
} |
141
|
|
|
else { |
142
|
|
|
if (isset($this->data[$this->pk()])) { |
143
|
|
|
$id = $this->data[$this->pk()]; |
144
|
|
|
$url = $this->app->GetCurPageParam($this->pk() . '=' . $id); |
145
|
|
|
} |
146
|
|
|
else { |
147
|
|
|
unset($this->data); |
148
|
|
|
$this->data = $_REQUEST['FIELDS']; //Заполняем, чтобы в случае ошибки сохранения поля не были пустыми |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
if (isset($url)) { |
153
|
|
|
$this->setAppException($this->app->GetException()); |
154
|
|
|
LocalRedirect($url); |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
else { |
158
|
|
|
$helperFields = $this->getFields(); |
159
|
|
|
$select = array_keys($helperFields); |
160
|
|
|
|
161
|
|
|
foreach ($select as $key => $field) { |
162
|
|
|
if (isset($helperFields[$field]['VIRTUAL']) |
163
|
|
|
AND $helperFields[$field]['VIRTUAL'] == true |
|
|
|
|
164
|
|
|
AND (!isset($helperFields[$field]['FORCE_SELECT']) OR $helperFields[$field]['FORCE_SELECT'] = false) |
|
|
|
|
165
|
|
|
) { |
166
|
|
|
unset($select[$key]); |
167
|
|
|
} |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$this->data = $this->loadElement($select); |
|
|
|
|
171
|
|
|
|
172
|
|
|
$id = isset($_REQUEST[$this->pk()]) ? $_REQUEST[$this->pk()] : null; |
173
|
|
|
|
174
|
|
|
if ($this->data === false && !is_null($id)) { |
175
|
|
|
$this->show404(); |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
if (isset($_REQUEST['action']) || isset($_REQUEST['action_button'])) { |
179
|
|
|
$action = isset($_REQUEST['action']) ? $_REQUEST['action'] : $_REQUEST['action_button']; |
180
|
|
|
$this->customActions($action, $this->getPk()); |
|
|
|
|
181
|
|
|
} |
182
|
|
|
} |
183
|
|
|
|
184
|
|
|
$this->setElementTitle(); |
185
|
|
|
} |
186
|
|
|
|
187
|
|
|
/** |
188
|
|
|
* Возвращает верхнее меню страницы. |
189
|
|
|
* По-умолчанию две кнопки: |
190
|
|
|
* <ul> |
191
|
|
|
* <li> Возврат в список</li> |
192
|
|
|
* <li> Удаление элемента</li> |
193
|
|
|
* </ul> |
194
|
|
|
* |
195
|
|
|
* Добавляя новые кнопки, нужно указывать параметр URl "action", который будет обрабатываться в |
196
|
|
|
* AdminEditHelper::customActions() |
197
|
|
|
* |
198
|
|
|
* @param bool $showDeleteButton Управляет видимостью кнопки удаления элемента. |
199
|
|
|
* |
200
|
|
|
* @return array |
201
|
|
|
* |
202
|
|
|
* @see AdminEditHelper::$menu |
203
|
|
|
* @see AdminEditHelper::customActions() |
204
|
|
|
* |
205
|
|
|
* @api |
206
|
|
|
*/ |
207
|
|
|
protected function getMenu($showDeleteButton = true) |
208
|
|
|
{ |
209
|
|
|
$listHelper = static::getHelperClass(AdminListHelper::className()); |
210
|
|
|
|
211
|
|
|
$menu = array( |
212
|
|
|
$this->getButton('RETURN_TO_LIST', array( |
213
|
|
|
'LINK' => $listHelper::getUrl(array_merge($this->additionalUrlParams, |
214
|
|
|
array('restore_query' => 'Y') |
215
|
|
|
)), |
216
|
|
|
'ICON' => 'btn_list', |
217
|
|
|
)) |
218
|
|
|
); |
219
|
|
|
|
220
|
|
|
$arSubMenu = array(); |
221
|
|
|
|
222
|
|
|
if (isset($this->data[$this->pk()]) && $this->hasWriteRights()) { |
223
|
|
|
$arSubMenu[] = $this->getButton('ADD_ELEMENT', array( |
224
|
|
|
'LINK' => static::getUrl(array_merge($this->additionalUrlParams, |
225
|
|
|
array( |
226
|
|
|
'action' => 'add', |
227
|
|
|
'lang' => LANGUAGE_ID, |
228
|
|
|
'restore_query' => 'Y', |
229
|
|
|
))), |
230
|
|
|
'ICON' => 'edit' |
231
|
|
|
)); |
232
|
|
|
} |
233
|
|
|
|
234
|
|
|
if ($showDeleteButton && isset($this->data[$this->pk()]) && $this->hasDeleteRights()) { |
235
|
|
|
$arSubMenu[] = $this->getButton('DELETE_ELEMENT', array( |
236
|
|
|
'ONCLICK' => "if(confirm('" . Loc::getMessage('DIGITALWAND_ADMIN_HELPER_EDIT_DELETE_CONFIRM') . "')) location.href='" . |
237
|
|
|
static::getUrl(array_merge($this->additionalUrlParams, |
238
|
|
|
array( |
239
|
|
|
'ID' => $this->data[$this->pk()], |
240
|
|
|
'action' => 'delete', |
241
|
|
|
'lang' => LANGUAGE_ID, |
242
|
|
|
'restore_query' => 'Y', |
243
|
|
|
))) . "'", |
244
|
|
|
'ICON' => 'delete' |
245
|
|
|
)); |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
if (count($arSubMenu)) { |
249
|
|
|
$menu[] = array('SEPARATOR' => 'Y'); |
250
|
|
|
$menu[] = $this->getButton('ACTIONS', array( |
251
|
|
|
'MENU' => $arSubMenu, |
252
|
|
|
'ICON' => 'btn_new' |
253
|
|
|
)); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
return $menu; |
257
|
|
|
} |
258
|
|
|
|
259
|
|
|
/** |
260
|
|
|
* {@inheritdoc} |
261
|
|
|
*/ |
262
|
|
|
public function show() |
|
|
|
|
263
|
|
|
{ |
264
|
|
|
if (!$this->hasReadRights()) { |
265
|
|
|
$this->addErrors(Loc::getMessage('DIGITALWAND_ADMIN_HELPER_ACCESS_FORBIDDEN')); |
266
|
|
|
$this->showMessages(); |
267
|
|
|
|
268
|
|
|
return false; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
$context = new \CAdminContextMenu($this->getMenu()); |
272
|
|
|
$context->Show(); |
273
|
|
|
|
274
|
|
|
$this->tabControl->BeginPrologContent(); |
275
|
|
|
$this->showMessages(); |
276
|
|
|
$this->showProlog(); |
277
|
|
|
$this->tabControl->EndPrologContent(); |
278
|
|
|
|
279
|
|
|
$this->tabControl->BeginEpilogContent(); |
280
|
|
|
$this->showEpilog(); |
281
|
|
|
$this->tabControl->EndEpilogContent(); |
282
|
|
|
|
283
|
|
|
$query = $this->additionalUrlParams; |
284
|
|
|
|
285
|
|
|
if (isset($_REQUEST[$this->pk()])) { |
286
|
|
|
$query[$this->pk()] = $_REQUEST[$this->pk()]; |
287
|
|
|
} |
288
|
|
|
elseif (isset($_REQUEST['SECTION_ID']) && $_REQUEST['SECTION_ID']) { |
289
|
|
|
$this->data[static::getSectionField()] = $_REQUEST['SECTION_ID']; |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
$this->tabControl->Begin(array( |
293
|
|
|
'FORM_ACTION' => static::getUrl($query) |
294
|
|
|
)); |
295
|
|
|
|
296
|
|
|
foreach ($this->tabs as $tabSettings) { |
297
|
|
|
if ($tabSettings['VISIBLE']) { |
298
|
|
|
$this->showTabElements($tabSettings); |
299
|
|
|
} |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
$this->showEditPageButtons(); |
303
|
|
|
$this->tabControl->ShowWarnings('editform', array()); //TODO: дописать |
304
|
|
|
$this->tabControl->Show(); |
305
|
|
|
} |
306
|
|
|
|
307
|
|
|
/** |
308
|
|
|
* Отображение кнопок для управления элементом на странице редактирования. |
309
|
|
|
*/ |
310
|
|
|
protected function showEditPageButtons() |
311
|
|
|
{ |
312
|
|
|
$listHelper = static::getHelperClass(AdminListHelper::className()); |
313
|
|
|
|
314
|
|
|
$this->tabControl->Buttons(array( |
315
|
|
|
'back_url' => $listHelper::getUrl(array_merge($this->additionalUrlParams, |
316
|
|
|
array( |
317
|
|
|
'lang' => LANGUAGE_ID, |
318
|
|
|
'restore_query' => 'Y', |
319
|
|
|
))) |
320
|
|
|
)); |
321
|
|
|
} |
322
|
|
|
|
323
|
|
|
/** |
324
|
|
|
* Отрисовка верхней части страницы. |
325
|
|
|
* |
326
|
|
|
* @api |
327
|
|
|
*/ |
328
|
|
|
protected function showProlog() |
329
|
|
|
{ |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
/** |
333
|
|
|
* Отрисовка нижней части страницы. По-умолчанию рисует все поля, которые не попали в вывод, как input hidden. |
334
|
|
|
* |
335
|
|
|
* @api |
336
|
|
|
*/ |
337
|
|
|
protected function showEpilog() |
338
|
|
|
{ |
339
|
|
|
echo bitrix_sessid_post(); |
340
|
|
|
|
341
|
|
|
$interfaceSettings = static::getInterfaceSettings(); |
342
|
|
|
|
343
|
|
|
foreach ($interfaceSettings['FIELDS'] as $code => $settings) { |
344
|
|
|
if (!isset($settings['TAB']) AND isset($settings['FORCE_SELECT']) AND $settings['FORCE_SELECT'] == true) { |
|
|
|
|
345
|
|
|
print '<input type="hidden" name="FIELDS[' . $code . ']" value="' . $this->data[$code] . '" />'; |
346
|
|
|
} |
347
|
|
|
} |
348
|
|
|
} |
349
|
|
|
|
350
|
|
|
/** |
351
|
|
|
* Отрисовывает вкладку со всеми привязанными к ней полями. |
352
|
|
|
* |
353
|
|
|
* @param $tabSettings |
354
|
|
|
* |
355
|
|
|
* @internal |
356
|
|
|
*/ |
357
|
|
|
private function showTabElements($tabSettings) |
358
|
|
|
{ |
359
|
|
|
$this->setContext(AdminEditHelper::OP_SHOW_TAB_ELEMENTS); |
360
|
|
|
$this->tabControl->BeginNextFormTab(); |
361
|
|
|
|
362
|
|
|
foreach ($this->getFields() as $code => $fieldSettings) { |
363
|
|
|
$widget = $this->createWidgetForField($code, $this->data); |
364
|
|
|
$fieldTab = $widget->getSettings('TAB'); |
365
|
|
|
$fieldOnCurrentTab = ($fieldTab == $tabSettings['DIV'] OR $tabSettings['DIV'] == 'DEFAULT_TAB'); |
|
|
|
|
366
|
|
|
|
367
|
|
|
if (!$fieldOnCurrentTab) { |
368
|
|
|
continue; |
369
|
|
|
} |
370
|
|
|
|
371
|
|
|
$fieldSettings = $widget->getSettings(); |
372
|
|
|
|
373
|
|
|
if (isset($fieldSettings['VISIBLE']) && $fieldSettings['VISIBLE'] === false) { |
374
|
|
|
continue; |
375
|
|
|
} |
376
|
|
|
|
377
|
|
|
$this->tabControl->BeginCustomField($code, $widget->getSettings('TITLE')); |
378
|
|
|
$pkField = ($code == $this->pk()); |
379
|
|
|
$widget->showBasicEditField($pkField); |
380
|
|
|
$this->tabControl->EndCustomField($code); |
381
|
|
|
} |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* Обработка запроса редактирования страницы. Этапы: |
386
|
|
|
* <ul> |
387
|
|
|
* <li> Проверка прав пользователя</li> |
388
|
|
|
* <li> Создание виджетов для каждого поля</li> |
389
|
|
|
* <li> Удаление значений для READONLY и HIDE_WHEN_CREATE полей</li> |
390
|
|
|
* <li> Изменение данных модели каждым виджетом (исходя из его внутренней логики)</li> |
391
|
|
|
* <li> Валидация значений каждого поля соответствующим виджетом</li> |
392
|
|
|
* <li> Проверка на ошибики валидации</li> |
393
|
|
|
* <li> В случае неудачи - выход из функции</li> |
394
|
|
|
* <li> В случае успеха - обновление или добавление элемента в БД</li> |
395
|
|
|
* <li> Постобработка данных модели каждым виджетом</li> |
396
|
|
|
* </ul> |
397
|
|
|
* |
398
|
|
|
* @return bool |
399
|
|
|
* |
400
|
|
|
* @see HelperWidget::processEditAction(); |
401
|
|
|
* @see HelperWidget::processAfterSaveAction(); |
402
|
|
|
* |
403
|
|
|
* @internal |
404
|
|
|
*/ |
405
|
|
|
protected function editAction() |
406
|
|
|
{ |
407
|
|
|
$this->setContext(AdminEditHelper::OP_EDIT_ACTION_BEFORE); |
408
|
|
|
|
409
|
|
|
if (!$this->hasWriteRights()) { |
410
|
|
|
$this->addErrors(Loc::getMessage('DIGITALWAND_ADMIN_HELPER_EDIT_WRITE_FORBIDDEN')); |
411
|
|
|
|
412
|
|
|
return false; |
413
|
|
|
} |
414
|
|
|
|
415
|
|
|
$allWidgets = array(); |
416
|
|
|
|
417
|
|
|
foreach ($this->getFields() as $code => $settings) { |
418
|
|
|
if ($settings['READONLY'] && $code !== $this->pk()) { |
419
|
|
|
unset($this->data[$code]); |
420
|
|
|
} |
421
|
|
|
} |
422
|
|
|
|
423
|
|
|
foreach ($this->getFields() as $code => $settings) { |
424
|
|
|
$widget = $this->createWidgetForField($code, $this->data); |
425
|
|
|
$widget->processEditAction(); |
426
|
|
|
$this->validationErrors = array_merge($this->validationErrors, $widget->getValidationErrors()); |
427
|
|
|
$allWidgets[] = $widget; |
428
|
|
|
|
429
|
|
|
if ($widget->getSettings('READONLY') || empty($this->data[$this->pk()]) |
430
|
|
|
&& $widget->getSettings('HIDE_WHEN_CREATE')) { |
431
|
|
|
unset($this->data[$code]); |
432
|
|
|
} |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
$this->addErrors($this->validationErrors); |
436
|
|
|
$success = empty($this->validationErrors); |
437
|
|
|
|
438
|
|
|
if ($success) { |
439
|
|
|
$this->setContext(AdminEditHelper::OP_EDIT_ACTION_AFTER); |
440
|
|
|
$existing = false; |
441
|
|
|
$id = $this->getPk(); |
442
|
|
|
|
443
|
|
|
if ($id) { |
444
|
|
|
/** @var DataManager $className */ |
445
|
|
|
$className = static::getModel(); |
446
|
|
|
// Если имеется primary key, то модель уже существующая, пытаемся найти ее в БД |
447
|
|
|
$existing = $className::getById($id)->fetch(); |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
if ($existing) { |
451
|
|
|
$result = $this->saveElement($id); |
|
|
|
|
452
|
|
|
} |
453
|
|
|
else { |
454
|
|
|
$result = $this->saveElement(); |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
if ($result) { |
458
|
|
|
if (!$result->isSuccess()) { |
459
|
|
|
$this->addErrors($result->getErrorMessages()); |
460
|
|
|
|
461
|
|
|
return false; |
462
|
|
|
} |
463
|
|
|
} |
464
|
|
|
else { |
465
|
|
|
// TODO Вывод ошибки |
466
|
|
|
return false; |
467
|
|
|
} |
468
|
|
|
|
469
|
|
|
$this->data[$this->pk()] = $result->getId(); |
470
|
|
|
|
471
|
|
|
foreach ($allWidgets as $widget) { |
472
|
|
|
/** @var HelperWidget $widget */ |
473
|
|
|
$widget->setData($this->data); |
474
|
|
|
$widget->processAfterSaveAction(); |
475
|
|
|
} |
476
|
|
|
|
477
|
|
|
return true; |
478
|
|
|
} |
479
|
|
|
|
480
|
|
|
return false; |
481
|
|
|
} |
482
|
|
|
|
483
|
|
|
/** |
484
|
|
|
* Функция загрузки элемента из БД. Можно переопределить, если требуется сложная логика и нет возможности |
485
|
|
|
* определить её в модели. |
486
|
|
|
* |
487
|
|
|
* @param array $select |
488
|
|
|
* |
489
|
|
|
* @return bool |
490
|
|
|
* @api |
491
|
|
|
*/ |
492
|
|
|
protected function loadElement($select = array()) |
|
|
|
|
493
|
|
|
{ |
494
|
|
|
if ($this->getPk() !== null) { |
495
|
|
|
$className = static::getModel(); |
496
|
|
|
$result = $className::getById($this->getPk()); |
497
|
|
|
|
498
|
|
|
return $result->fetch(); |
499
|
|
|
} |
500
|
|
|
|
501
|
|
|
return false; |
502
|
|
|
} |
503
|
|
|
|
504
|
|
|
/** |
505
|
|
|
* Сохранение элемента. Можно переопределить, если требуется сложная логика и нет возможности определить её |
506
|
|
|
* в модели. |
507
|
|
|
* |
508
|
|
|
* Операциями сохранения модели занимается EntityManager. |
509
|
|
|
* |
510
|
|
|
* @param bool $id |
511
|
|
|
* |
512
|
|
|
* @return \Bitrix\Main\Entity\AddResult|\Bitrix\Main\Entity\UpdateResult |
513
|
|
|
* |
514
|
|
|
* @throws \Exception |
515
|
|
|
* |
516
|
|
|
* @see EntityManager |
517
|
|
|
* |
518
|
|
|
* @api |
519
|
|
|
*/ |
520
|
|
|
protected function saveElement($id = null) |
521
|
|
|
{ |
522
|
|
|
/** @var EntityManager $entityManager */ |
523
|
|
|
$entityManager = new static::$entityManager(static::getModel(), empty($this->data) ? array() : $this->data, $id, $this); |
524
|
|
|
$saveResult = $entityManager->save(); |
525
|
|
|
$this->addNotes($entityManager->getNotes()); |
526
|
|
|
|
527
|
|
|
return $saveResult; |
528
|
|
|
} |
529
|
|
|
|
530
|
|
|
/** |
531
|
|
|
* Удаление элемента. Можно переопределить, если требуется сложная логика и нет возможности определить её в модели. |
532
|
|
|
* |
533
|
|
|
* @param $id |
534
|
|
|
* |
535
|
|
|
* @return bool|\Bitrix\Main\Entity\DeleteResult |
536
|
|
|
* |
537
|
|
|
* @throws \Exception |
538
|
|
|
* |
539
|
|
|
* @api |
540
|
|
|
*/ |
541
|
|
|
protected function deleteElement($id) |
542
|
|
|
{ |
543
|
|
|
if (!$this->hasDeleteRights()) { |
544
|
|
|
$this->addErrors(Loc::getMessage('DIGITALWAND_ADMIN_HELPER_EDIT_DELETE_FORBIDDEN')); |
545
|
|
|
|
546
|
|
|
return false; |
547
|
|
|
} |
548
|
|
|
|
549
|
|
|
/** @var EntityManager $entityManager */ |
550
|
|
|
$entityManager = new static::$entityManager(static::getModel(), empty($this->data) ? array() : $this->data, $id, $this); |
551
|
|
|
|
552
|
|
|
$deleteResult = $entityManager->delete(); |
553
|
|
|
$this->addNotes($entityManager->getNotes()); |
554
|
|
|
|
555
|
|
|
return $deleteResult; |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
/** |
559
|
|
|
* Выполнение кастомных операций над объектом в процессе редактирования. |
560
|
|
|
* |
561
|
|
|
* @param string $action Название операции. |
562
|
|
|
* @param int|null $id ID элемента. |
563
|
|
|
* |
564
|
|
|
* @see AdminEditHelper::fillMenu() |
565
|
|
|
* |
566
|
|
|
* @api |
567
|
|
|
*/ |
568
|
|
|
protected function customActions($action, $id = null) |
569
|
|
|
{ |
570
|
|
|
if ($action == 'delete' AND !is_null($id)) { |
|
|
|
|
571
|
|
|
$result = $this->deleteElement($id); |
572
|
|
|
|
573
|
|
|
if(!$result->isSuccess()){ |
574
|
|
|
$this->addErrors($result->getErrorMessages()); |
575
|
|
|
} |
576
|
|
|
|
577
|
|
|
$listHelper = static::getHelperClass(AdminListHelper::className()); |
578
|
|
|
$redirectUrl = $listHelper::getUrl(array_merge( |
579
|
|
|
$this->additionalUrlParams, |
580
|
|
|
array('restore_query' => 'Y') |
581
|
|
|
)); |
582
|
|
|
|
583
|
|
|
LocalRedirect($redirectUrl); |
584
|
|
|
} |
585
|
|
|
} |
586
|
|
|
|
587
|
|
|
/** |
588
|
|
|
* Устанавливает заголовок исходя из данных текущего элемента. |
589
|
|
|
* |
590
|
|
|
* @see $data |
591
|
|
|
* @see AdminBaseHelper::setTitle() |
592
|
|
|
* |
593
|
|
|
* @api |
594
|
|
|
*/ |
595
|
|
|
protected function setElementTitle() |
596
|
|
|
{ |
597
|
|
|
if (!empty($this->data)) { |
598
|
|
|
$title = Loc::getMessage('DIGITALWAND_ADMIN_HELPER_EDIT_TITLE', array('#ID#' => $this->data[$this->pk()])); |
599
|
|
|
} |
600
|
|
|
else { |
601
|
|
|
$title = Loc::getMessage('DIGITALWAND_ADMIN_HELPER_NEW_ELEMENT'); |
602
|
|
|
} |
603
|
|
|
|
604
|
|
|
$this->setTitle($title); |
605
|
|
|
} |
606
|
|
|
|
607
|
|
|
/** |
608
|
|
|
* @return \CAdminForm |
609
|
|
|
*/ |
610
|
|
|
public function getTabControl() |
611
|
|
|
{ |
612
|
|
|
return $this->tabControl; |
613
|
|
|
} |
614
|
|
|
|
615
|
|
|
/** |
616
|
|
|
* @inheritdoc |
617
|
|
|
*/ |
618
|
|
|
public static function getUrl(array $params = array()) |
619
|
|
|
{ |
620
|
|
|
return static::getViewURL(static::getViewName(), static::$editPageUrl, $params); |
621
|
|
|
} |
622
|
|
|
} |
623
|
|
|
|
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.