1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
undo.php
См. документацию.
1<?php
2
4
6
7class CUndo
8{
9 public static function Add($params = array())
10 {
11 global $DB, $USER, $CACHE_MANAGER;
12
13 $ID = '1'.md5(uniqid(rand(), true));
14 $strContent = serialize($params['arContent']);
15 $userID = $USER->GetId();
16
18 'ID' => $ID,
19 'MODULE_ID' => $params['module'],
20 'UNDO_TYPE' => $params['undoType'],
21 'UNDO_HANDLER' => $params['undoHandler'],
22 'CONTENT' => $strContent,
23 'USER_ID' => $userID,
24 'TIMESTAMP_X' => time(),
25 );
26
27 $DB->Add("b_undo", $arFields, Array("CONTENT"));
28
29 $CACHE_MANAGER->Clean(mb_substr($ID, 0, 3), "b_undo");
30
31 return $ID;
32 }
33
34 public static function Escape($ID)
35 {
36 global $USER, $CACHE_MANAGER;
37 if (!isset($USER) || !is_object($USER) || !$USER->IsAuthorized())
38 return false;
39
40 $arUndo = null;
41 $cacheId = mb_substr($ID, 0, 3);
42 if ($CACHE_MANAGER->Read(48 * 3600, $cacheId, "b_undo"))
43 {
44 $arUndoCache = $CACHE_MANAGER->Get($cacheId);
45 }
46 else
47 {
48 $arUndoCache = array();
49 $arUndoList = CUndo::GetList(array('arFilter' => array('%ID' => $cacheId."%")));
50 foreach ($arUndoList as $ar)
51 {
52 if (!isset($arUndoCache[$ar["ID"]]) && !isset($arUndoCache[$ar["ID"]][$ar["USER_ID"]]))
53 $arUndoCache[$ar["ID"]][$ar["USER_ID"]] = $ar;
54 }
55 $CACHE_MANAGER->Set($cacheId, $arUndoCache);
56 }
57 $arUndo = $arUndoCache[$ID][$USER->GetId()] ?? false;
58
59 if (!$arUndo)
60 return false;
61
62 // Include module
63 if ($arUndo['MODULE_ID'] && $arUndo['MODULE_ID'] <> '')
64 {
65 if (!CModule::IncludeModule($arUndo['MODULE_ID']))
66 return false;
67 }
68
69 // Get params for Escaping
70 $arParams = unserialize($arUndo['CONTENT'], ['allowed_classes' => false]);
71
72 // Check and call Undo handler
73 $p = mb_strpos($arUndo['UNDO_HANDLER'], "::");
74 if ($p === false)
75 {
76 if (function_exists($arUndo['UNDO_HANDLER'])) // function
77 {
78 call_user_func($arUndo['UNDO_HANDLER'], array($arParams, $arUndo['UNDO_TYPE']));
79 }
80 }
81 else
82 {
83 $className = mb_substr($arUndo['UNDO_HANDLER'], 0, $p);
84 if (class_exists($className)) //class
85 {
86 $methodName = mb_substr($arUndo['UNDO_HANDLER'], $p + 2);
87 if (method_exists($className, $methodName)) //static method
88 {
89 call_user_func_array(array($className, $methodName), array($arParams, $arUndo['UNDO_TYPE']));
90 }
91 }
92 }
93
94 // Del entry
96 return true;
97 }
98
99 public static function GetList($Params = array())
100 {
101 global $DB;
102
103 $arFilter = $Params['arFilter'];
104 $arOrder = $Params['arOrder'] ?? array('ID' => 'asc');
105
107 "ID" => array("FIELD_NAME" => "U.ID", "FIELD_TYPE" => "string"),
108 "MODULE_ID" => array("FIELD_NAME" => "U.MODULE_ID", "FIELD_TYPE" => "string"),
109 "UNDO_TYPE" => array("FIELD_NAME" => "U.UNDO_TYPE", "FIELD_TYPE" => "string"),
110 "UNDO_HANDLER" => array("FIELD_NAME" => "U.UNDO_HANDLER", "FIELD_TYPE" => "string"),
111 "CONTENT" => array("FIELD_NAME" => "U.CONTENT", "FIELD_TYPE" => "string"),
112 "USER_ID" => array("FIELD_NAME" => "U.USER_ID", "FIELD_TYPE" => "int"),
113 "TIMESTAMP_X" => array("FIELD_NAME" => "U.TIMESTAMP_X", "FIELD_TYPE" => "int"),
114 );
115
116 $arSqlSearch = array();
117
118 if (is_array($arFilter))
119 {
120 foreach ($arFilter as $key => $val)
121 {
122 $n = mb_strtoupper($key);
123 if ($n == '%ID')
124 $arSqlSearch[] = "(U.ID like '".$DB->ForSql($val)."')";
125 elseif ($n == 'ID' || $n == 'USER_ID')
126 $arSqlSearch[] = GetFilterQuery("U.".$n, $val, 'N');
127 elseif (isset($arFields[$n]))
128 $arSqlSearch[] = GetFilterQuery($arFields[$n]["FIELD_NAME"], $val);
129 }
130 }
131
132 $strOrderBy = '';
133 foreach ($arOrder as $by => $order)
134 {
135 $by = mb_strtoupper($by);
136 if (isset($arFields[$by]))
137 {
138 $strOrderBy .= $arFields[$by]["FIELD_NAME"].' '.(mb_strtolower($order) == 'desc'? 'desc': 'asc').',';
139 }
140 }
141
142 if ($strOrderBy)
143 {
144 $strOrderBy = "ORDER BY ".rtrim($strOrderBy, ",");
145 }
146
147 $strSqlSearch = GetFilterSqlSearch($arSqlSearch);
148 $strSql = "
149 SELECT
150 U.*
151 FROM
152 b_undo U
153 WHERE
154 $strSqlSearch
155 $strOrderBy";
156
157 $res = $DB->Query($strSql);
158 $arResult = array();
159 while ($arRes = $res->Fetch())
160 $arResult[] = $arRes;
161
162 return $arResult;
163 }
164
165 public static function Delete($ID)
166 {
167 global $DB, $CACHE_MANAGER;
168
169 $DB->Query("DELETE FROM b_undo WHERE ID='".$DB->ForSql($ID)."'");
170
171 $CACHE_MANAGER->Clean(mb_substr($ID, 0, 3), "b_undo");
172 }
173
174 public static function CleanUpOld()
175 {
176 global $DB, $CACHE_MANAGER;
177
178 // All entries older than one day
179 $timestamp = mktime(date("H"), date("i"), 0, date("m"), date("d") - 1, date("Y"));
180 $DB->Query("delete from b_undo where TIMESTAMP_X <= ".$timestamp);
181
182 $CACHE_MANAGER->CleanDir("b_undo");
183
184 return "CUndo::CleanUpOld();";
185 }
186
187 public static function ShowUndoMessage($ID)
188 {
189 \Bitrix\Main\Application::getInstance()->getSession()['BX_UNDO_ID'] = $ID;
190 }
191
192 public static function CheckNotifyMessage()
193 {
194 global $USER, $APPLICATION;
195 $session = \Bitrix\Main\Application::getInstance()->getSession();
196 if (!$session->isStarted() || !$session->has('BX_UNDO_ID'))
197 return;
198
199 $ID = $session['BX_UNDO_ID'];
200 unset($session['BX_UNDO_ID']);
201
202 $arUndoList = CUndo::GetList(array('arFilter' => array('ID' => $ID, 'USER_ID' => $USER->GetId())));
203 if (!$arUndoList)
204 return;
205
206 $arUndo = $arUndoList[0];
207 $detail = GetMessage('MAIN_UNDO_TYPE_'.mb_strtoupper($arUndo['UNDO_TYPE']));
208
209 $s = "
210<script>
211window.BXUndoLastChanges = function()
212{
213 if (!confirm(\"".GetMessage("MAIN_UNDO_ESCAPE_CHANGES_CONFIRM")."\"))
214 return;
215
216 BX.ajax.get(\"/bitrix/admin/public_undo.php?undo=".$ID."&".bitrix_sessid_get()."\", null, function(result)
217 {
218 if (result && result.toUpperCase().indexOf(\"ERROR\") != -1)
219 BX.admin.panel.Notify(\"".GetMessage("MAIN_UNDO_ESCAPE_ERROR")."\");
220 else
221 window.location = window.location;
222 });
223};
224BX.ready(function()
225{
226 setTimeout(function()
227 {
228 BX.admin.panel.Notify('".$detail." <a href=\"javascript: void(0);\" onclick=\"window.BXUndoLastChanges(); return false;\" title=\"".GetMessage("MAIN_UNDO_ESCAPE_CHANGES_TITLE")."\">".GetMessage("MAIN_UNDO_ESCAPE_CHANGES")."</a>');
229 }, 100);
230});
231</script>";
232
233 $APPLICATION->AddHeadString($s);
234 }
235}
236
238{
239 /*'ID', 'COPY_ID', 'ENTITY_ID', 'mid', 'WEB_FORM_ID', 'CONTRACT_ID', 'COURSE_ID', 'IBLOCK_SECTION_ID', 'IBLOCK_ID', 'CHANNEL_ID', 'VOTE_ID', 'DICTIONARY_ID', 'CHAPTER_ID', 'LESSON_ID', */
240
241 private $formId = '';
242 private $autosaveId = '';
243
244 private $bInited = false;
245
246 private $bSkipRestore = false;
247
248 private static $bAllowed = null;
249 private static $arImportantParams = array(
250 'LANG' => 1,
251 'SITE' => 1,
252 'PATH' => 1,
253 'TYPE' => 1,
254 'EVENT_NAME' => 1,
255 'SHOW_ERROR' => 1,
256 'NAME' => 1,
257 'FULL_SRC' => 1,
258 'ACTION' => 1,
259 'LOGICAL' => 1,
260 'ADMIN' => 1,
261 'ADDITIONAL' => 1,
262 'NEW' => 1,
263 'MODE' => 1,
264 'CONDITION' => 1,
265 'QUESTION_TYPE' => 1,
266 );
267
268 public function __construct()
269 {
270 global $USER;
271
272 if ($USER->IsAuthorized())
273 {
274 if (isset($_REQUEST['autosave_id']) && mb_strlen($_REQUEST['autosave_id']) == 33)
275 {
276 $this->bSkipRestore = true;
277 $this->autosaveId = preg_replace("/[^a-z0-9_]/i", "", $_REQUEST['autosave_id']);
278 }
279 else
280 {
281 $this->formId = self::_GetFormID();
282 }
283
284 addEventHandler('main', 'OnBeforeLocalRedirect', array($this, 'Reset'));
285
286 if (!defined('BX_PUBLIC_MODE'))
287 {
288 CJSCore::Init(array('autosave'));
289 }
290 }
291 }
292
293 public function Init($admin = true)
294 {
295 global $USER;
296
297 if (!$USER->IsAuthorized())
298 return false;
299
300 if (!$this->bInited)
301 {
302 $DISABLE_STANDARD_NOTIFY = ($admin? 'false': 'true');
303
304 if (defined('BX_PUBLIC_MODE') && BX_PUBLIC_MODE == 1)
305 echo CJSCore::GetHTML(array('autosave'));
306 ?>
307 <input type="hidden" name="autosave_id" id="autosave_marker_<?=$this->GetID()?>" value="<?=$this->GetID()?>"/>
308 <script>window.autosave_<?=$this->GetID()?> = new top.BX.CAutoSave({
309 form_marker: 'autosave_marker_<?=$this->GetID()?>',
310 form_id: '<?=$this->GetID()?>',
311 DISABLE_STANDARD_NOTIFY: <?=$DISABLE_STANDARD_NOTIFY?>
312 });
313 </script>
314 <?
315 $this->checkRestore();
316
317 $this->bInited = true;
318 }
319 return true;
320 }
321
322 public function checkRestore()
323 {
324 $key = addEventHandler('main', 'OnAutoSaveRestore', array($this, 'Restore'));
325 CUndo::Escape($this->GetID());
326 removeEventHandler('main', 'OnAutoSaveRestore', $key);
327 }
328
329 public function Reset()
330 {
331 global $USER, $DB, $CACHE_MANAGER;
332
333 if (!$USER->IsAuthorized())
334 return false;
335
336 $ID = $this->GetID();
337 $DB->Query("DELETE FROM b_undo WHERE ID='".$DB->ForSQL($ID)."' AND USER_ID='".$USER->GetID()."'");
338
339 $CACHE_MANAGER->Clean(mb_substr($ID, 0, 3), "b_undo");
340
341 return true;
342 }
343
344 public function Set($data)
345 {
346 global $DB, $USER, $CACHE_MANAGER;
347
348 if (!$USER->IsAuthorized())
349 return false;
350
351 if (!is_array($data) || empty($data))
352 return false;
353
354 $ID = $this->GetID();
356 'MODULE_ID' => 'main',
357 'UNDO_TYPE' => 'autosave',
358 'UNDO_HANDLER' => 'CAutoSave::_Restore',
359 'CONTENT' => serialize($data),
360 'USER_ID' => $USER->GetID(),
361 'TIMESTAMP_X' => time(),
362 );
363 $arBinds = array(
364 "CONTENT" => $arFields["CONTENT"],
365 );
366
367 $strUpdate = $DB->PrepareUpdate("b_undo", $arFields);
368 $rs = $DB->QueryBind("UPDATE b_undo SET ".$strUpdate." WHERE ID = '".$DB->ForSQL($ID)."'", $arBinds);
369 if ($rs->AffectedRowsCount() == 0)
370 {
371 $arFields['ID'] = $ID;
372 $DB->Add("b_undo", $arFields, array("CONTENT"), "", true);
373 }
374
375 $CACHE_MANAGER->Clean(mb_substr($ID, 0, 3), "b_undo");
376 return true;
377 }
378
379 public function Restore($arFields)
380 {
381 if (is_array($arFields))
382 {
383?>
384<script>BX.ready(function(){
385 if (window.autosave_<?=$this->GetID();?>)
386 {
387 window.autosave_<?=$this->GetID();?>.Restore(<?= Json::encode($arFields); ?>);
388 }
389});</script>
390<?
391 }
392 }
393
394 public function GetID()
395 {
396 global $USER;
397
398 if (!$this->autosaveId)
399 {
400 $this->autosaveId = '2'.md5($this->formId.'|'.$USER->GetID());
401 }
402
403 return $this->autosaveId;
404 }
405
406 private static function _GetFormID()
407 {
408 global $APPLICATION;
409
410 $arParams = array();
411 foreach ($_GET as $param => $value)
412 {
413 $param = strtoupper($param);
414
415 if (substr($param, -2) == 'ID' || array_key_exists($param, self::$arImportantParams))
416 $arParams[$param] = $value;
417 }
418
419 ksort($arParams);
420
421 $url = mb_strtolower($APPLICATION->GetCurPage()).'?';
422 foreach ($arParams as $param => $value)
423 {
424 if (is_array($value))
425 $value = implode('|', $value);
426
427 $url .= urlencode($param).'='.urlencode($value).'&';
428 }
429
430 return $url;
431 }
432
433 public static function _Restore($arFields)
434 {
435 foreach (GetModuleEvents("main", "OnAutoSaveRestore", true) as $arEvent)
436 {
438 }
439 }
440
441 public static function Allowed()
442 {
443 global $USER, $APPLICATION;
444
445 if (!$USER->IsAuthorized())
446 return false;
447
448 if (self::$bAllowed == null)
449 {
450 $arOpt = CUserOptions::GetOption('global', 'settings', []);
451 self::$bAllowed = (!isset($arOpt['autosave']) || $arOpt['autosave'] != 'N') && $APPLICATION->GetCurPage() != '/bitrix/admin/update_system.php';
452 }
453
454 return self::$bAllowed;
455 }
456}
$arParams
Определения access_dialog.php:21
global $APPLICATION
Определения include.php:80
$arResult
Определения generate_coupon.php:16
static getInstance()
Определения application.php:98
Определения json.php:9
Определения undo.php:238
__construct()
Определения undo.php:268
Restore($arFields)
Определения undo.php:379
static _Restore($arFields)
Определения undo.php:433
Set($data)
Определения undo.php:344
checkRestore()
Определения undo.php:322
Reset()
Определения undo.php:329
GetID()
Определения undo.php:394
static Allowed()
Определения undo.php:441
Init($admin=true)
Определения undo.php:293
static Init($arExt=array(), $bReturn=false)
Определения jscore.php:66
static GetHTML($arExt)
Определения jscore.php:269
Определения undo.php:8
static ShowUndoMessage($ID)
Определения undo.php:187
static CheckNotifyMessage()
Определения undo.php:192
static Delete($ID)
Определения undo.php:165
static Add($params=array())
Определения undo.php:9
static GetList($Params=array())
Определения undo.php:99
static Escape($ID)
Определения undo.php:34
static CleanUpOld()
Определения undo.php:174
global $CACHE_MANAGER
Определения clear_component_cache.php:7
$arFields
Определения dblapprove.php:5
$data['IS_AVAILABLE']
Определения .description.php:13
const BX_PUBLIC_MODE
Определения file_edit.php:2
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
bx_acc_lim_group_list limitGroupList[] multiple<?=$group[ 'ID']?> ID selected margin top
Определения file_new.php:657
$res
Определения filter_act.php:7
GetFilterSqlSearch($arSqlSearch=array(), $FilterLogic="FILTER_logic")
Определения filter_tools.php:397
GetFilterQuery($field, $val, $procent="Y", $ex_sep=array(), $clob="N", $div_fields="Y", $clob_upper="N")
Определения filter_tools.php:383
$_REQUEST["admin_mnu_menu_id"]
Определения get_menu.php:8
if($ajaxMode) $ID
Определения get_user.php:27
$p
Определения group_list_element_edit.php:23
global $DB
Определения cron_frame.php:29
global $USER
Определения csv_new_run.php:40
ExecuteModuleEventEx($arEvent, $arParams=[])
Определения tools.php:5214
GetModuleEvents($MODULE_ID, $MESSAGE_ID, $bReturnArray=false)
Определения tools.php:5177
IncludeModuleLangFile($filepath, $lang=false, $bReturnArray=false)
Определения tools.php:3778
GetMessage($name, $aReplace=null)
Определения tools.php:3397
bitrix_sessid_get($varname='sessid')
Определения tools.php:4695
$value
Определения Param.php:39
$order
Определения payment.php:8
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
$ar
Определения options.php:199
if(empty($signedUserToken)) $key
Определения quickway.php:257
if($inWords) echo htmlspecialcharsbx(Number2Word_Rus(roundEx($totalVatSum $params['CURRENCY']
Определения template.php:799
$val
Определения options.php:1793
$arRes
Определения options.php:104
$rs
Определения action.php:82
$n
Определения update_log.php:107
$arFilter
Определения user_search.php:106
$url
Определения iframe.php:7