1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
stepper.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\Update;
4
5use Bitrix\Main;
6use Bitrix\Main\HttpApplication;
7use Bitrix\Main\Web\Json;
8use Bitrix\Main\Config\Option;
9use Bitrix\Main\Context;
10use Bitrix\Main\Localization\Loc;
11
28abstract class Stepper
29{
30 const CONTINUE_EXECUTION = true;
31 const FINISH_EXECUTION = false;
32 const THRESHOLD_TIME = 20.0;
33 const DELAY_COEFFICIENT = 0.5;
34
35 protected static $moduleId = "main";
36 private static $countId = 0;
37
38 protected $outerParams = [];
39
46 public static function getHtml($ids = [], $title = "")
47 {
48 if (static::class !== __CLASS__)
49 {
50 $title = static::getTitle();
51 $ids = [static::$moduleId => [static::class]];
52 return call_user_func([__CLASS__, "getHtml"], $ids, $title);
53 }
54
55 $return = [];
56 $count = 0;
57 $steps = 0;
58
59 if (is_string($ids))
60 {
61 $ids = [$ids => null];
62 }
63
64 foreach ($ids as $moduleId => $classesId)
65 {
66 $options = [];
67 $category = "main.stepper." . $moduleId;
68
69 if (is_string($classesId))
70 {
71 $classesId = [$classesId];
72 }
73 if (is_array($classesId))
74 {
75 foreach ($classesId as $classId)
76 {
77 if (($option = Option::get($category, $classId)) !== "")
78 {
79 $options[$classId] = $option;
80 }
81 }
82 }
83 elseif (is_null($classesId))
84 {
85 $options = Option::getForModule($category);
86 }
87
88 foreach ($options as $classId => $option)
89 {
90 $option = unserialize($option, ['allowed_classes' => false]);
91 if (is_array($option))
92 {
93 $return[] = [
94 "moduleId" => $moduleId,
95 "class" => $classId,
96 "title" => $option["title"] ?? '',
97 "steps" => $option["steps"],
98 "count" => $option["count"],
99 ];
100 $count += $option["count"];
101 $steps += ($option["count"] > $option["steps"] ? $option["steps"] : $option["count"]);
102 }
103 }
104 }
105
106 $result = '';
107 if (!empty($return))
108 {
109 $id = ++self::$countId;
110 \CJSCore::Init(['update_stepper']);
111 $title = empty($title) ? self::getTitle() : $title;
112 $progress = $count > 0 ? intval($steps * 100 / $count) : 0;
113 $result .= <<<HTML
114<div class="main-stepper main-stepper-show" id="{$id}-container" data-bx-steps-count="{$count}">
115 <div class="main-stepper-info" id="{$id}-title">{$title}</div>
116 <div class="main-stepper-inner">
117 <div class="main-stepper-bar">
118 <div class="main-stepper-bar-line" id="{$id}-bar" style="width:{$progress}%;"></div>
119 </div>
120 <div class="main-stepper-steps"><span id="{$id}-steps">{$steps}</span> / <span id="{$id}-count">{$count}</span></div>
121 <div class="main-stepper-error-text" id="{$id}-error"></div>
122 </div>
123</div>
124HTML;
125 $return = Json::encode($return);
126 $result = <<<HTML
127<div class="main-stepper-block">{$result}
128<script>BX.ready(function(){ if (BX && BX["UpdateStepperRegister"]) { BX.UpdateStepperRegister({$id}, {$return}); }});</script>
129</div>
130HTML;
131 }
132 return $result;
133 }
134
135 public static function getTitle()
136 {
137 return Loc::getMessage("STEPPER_TITLE");
138 }
139
144 public static function execAgent()
145 {
146 global $pPERIOD;
147
148 $updater = self::createInstance();
149 $className = get_class($updater);
150
151 $option = Option::get("main.stepper." . $updater->getModuleId(), $className);
152 if ($option !== "")
153 {
154 $option = unserialize($option, ['allowed_classes' => false]);
155 }
156 $option = is_array($option) ? $option : [];
157
158 $updater->setOuterParams(func_get_args());
159
160 $startTime = microtime(true);
161
162 if ($updater->execute($option) === self::CONTINUE_EXECUTION)
163 {
164 $executeTime = microtime(true) - $startTime;
165 $threshold = (float)($option["thresholdTime"] ?? self::THRESHOLD_TIME);
166
167 if ($executeTime > $threshold)
168 {
169 // delaying next execution time proportionally to the last execution time
170 $delayCoefficient = (float)($option["delayCoefficient"] ?? self::DELAY_COEFFICIENT);
171
173 $pPERIOD = (int)round($executeTime + $executeTime * $delayCoefficient);
174 }
175
176 $option["steps"] = (int)($option["steps"] ?? 0);
177 $option["count"] = (int)($option["count"] ?? 0);
178 $option["lastTime"] = $executeTime;
179 $option["totalTime"] = (float)($option["totalTime"] ?? 0.0) + $executeTime;
180 $option["title"] = $updater::getTitle();
181
182 Option::set("main.stepper." . $updater->getModuleId(), $className, serialize($option));
183
184 return $className . '::execAgent(' . $updater::makeArguments($updater->getOuterParams()) . ');';
185 }
186
187 Option::delete('main.stepper.' . $updater->getModuleId(), ['name' => $className]);
188 Option::delete('main.stepper.' . $updater->getModuleId(), ['name' => '\\' . $className]);
189
190 return '';
191 }
192
196 public function __destruct()
197 {
198 }
199
205 abstract function execute(array &$option);
206
207 public function setOuterParams(array $outerParams): void
208 {
209 $this->outerParams = $outerParams;
210 }
211
212 public function getOuterParams(): array
213 {
214 return $this->outerParams;
215 }
216
222 public static function makeArguments($arguments = []): string
223 {
224 if (is_array($arguments))
225 {
226 foreach ($arguments as $key => $val)
227 {
228 if (is_string($val))
229 {
230 $arguments[$key] = "'" . EscapePHPString($val, "'") . "'";
231 }
232 else
233 {
234 $arguments[$key] = intval($val);
235 }
236 }
237 return implode(", ", $arguments);
238 }
239 return "";
240 }
241
246 public static function createInstance()
247 {
248 return new static;
249 }
250
255 public static function getModuleId()
256 {
257 return static::$moduleId;
258 }
259
266 public static function bind($delay = 300, $withArguments = [])
267 {
269 $c = get_called_class();
270 self::bindClass($c, $c::getModuleId(), $delay, $withArguments);
271 }
272
281 public static function bindClass($className, $moduleId, $delay = 300, $withArguments = [])
282 {
283 if (class_exists("\CAgent"))
284 {
285 $addAgent = true;
286 $withArguments = is_array($withArguments) ? $withArguments : [];
287
288 $delay = (int)$delay;
289 if ($delay <= 0)
290 {
292 $addAgent = ('' !== call_user_func_array([$className, "execAgent"], $withArguments));
293 }
294
295 if ($addAgent)
296 {
297 if (Option::get("main.stepper." . $moduleId, $className) === "")
298 {
299 Option::set("main.stepper." . $moduleId, $className, serialize([]));
300 }
301 \CTimeZone::Disable();
302 \CAgent::AddAgent(
303 $className . '::execAgent(' . (empty($withArguments) ? '' : call_user_func_array([$className, "makeArguments"], [$withArguments])) . ');',
304 $moduleId,
305 "Y",
306 1,
307 "",
308 "Y",
309 date(Main\Type\Date::convertFormatToPhp(\CSite::GetDateFormat()), time() + $delay),
310 100,
311 false,
312 false
313 );
314 \CTimeZone::Enable();
315 }
316 }
317 else
318 {
319 $connection = \Bitrix\Main\Application::getConnection();
320 $helper = $connection->getSqlHelper();
321
322 $arguments = '';
323 if (!empty($withArguments))
324 {
325 $arguments = class_exists($className)
326 ? call_user_func_array([$className, "makeArguments"], [$withArguments])
327 : self::makeArguments($withArguments);
328 }
329 $name = $helper->forSql($className . '::execAgent(' . $arguments . ');', 2000);
330 $className = $helper->forSql($className);
331 $moduleId = $helper->forSql($moduleId);
332 $agent = $connection->query("SELECT ID FROM b_agent WHERE MODULE_ID='" . $moduleId . "' AND NAME = '" . $name . "' AND USER_ID IS NULL")->fetch();
333 if (!$agent)
334 {
335 $connection->query(
336 "INSERT INTO b_agent (MODULE_ID, SORT, NAME, ACTIVE, AGENT_INTERVAL, IS_PERIOD, NEXT_EXEC)
337 VALUES ('" . $moduleId . "', 100, '" . $name . "', 'Y', 1, 'Y', " . ($delay > 0 ? $helper->addSecondsToDateTime($delay) : $helper->getCurrentDateTimeFunction()) . ")"
338 );
339 $merge = $helper->prepareMerge(
340 'b_option',
341 ['MODULE_ID', 'NAME'],
342 [
343 'MODULE_ID' => 'main.stepper.' . $moduleId,
344 'NAME' => $className,
345 'VALUE' => 'a:0:{}',
346 ],
347 [
348 'VALUE' => 'a:0:{}',
349 ]
350 );
351 if ($merge)
352 {
353 $connection->Query($merge[0]);
354 }
355 }
356 }
357 }
358
363 public static function checkRequest()
364 {
365 $result = [];
366 $data = Context::getCurrent()->getRequest()->getPost("stepper");
367 if (is_array($data))
368 {
369 foreach ($data as $stepper)
370 {
371 if (($option = Option::get("main.stepper." . $stepper["moduleId"], $stepper["class"])) !== "" &&
372 ($res = unserialize($option, ['allowed_classes' => false])) && is_array($res))
373 {
374 $r = [
375 "moduleId" => $stepper["moduleId"],
376 "class" => $stepper["class"],
377 "steps" => $res["steps"],
378 "count" => $res["count"],
379 ];
380 $result[] = $r;
381 }
382 }
383 }
384 self::sendJson($result);
385 }
386
392 private static function sendJson($result)
393 {
394 global $APPLICATION;
395 $APPLICATION->RestartBuffer();
396
397 header('Content-Type:application/json; charset=UTF-8');
398
399 echo Json::encode($result);
400 \CMain::finalActions();
401 die;
402 }
403
404 protected function writeToLog(\Exception $exception)
405 {
407 $exceptionHandler = $application->getExceptionHandler();
408 $exceptionHandler->writeToLog($exception);
409 }
410}
$connection
Определения actionsdefinitions.php:38
$count
Определения admin_tab.php:4
global $APPLICATION
Определения include.php:80
static getInstance()
Определения application.php:98
writeToLog(\Exception $exception)
Определения stepper.php:404
getOuterParams()
Определения stepper.php:212
setOuterParams(array $outerParams)
Определения stepper.php:207
static makeArguments($arguments=[])
Определения stepper.php:222
const THRESHOLD_TIME
Определения stepper.php:32
static checkRequest()
Определения stepper.php:363
__destruct()
Определения stepper.php:196
const FINISH_EXECUTION
Определения stepper.php:31
const CONTINUE_EXECUTION
Определения stepper.php:30
const DELAY_COEFFICIENT
Определения stepper.php:33
static getHtml($ids=[], $title="")
Определения stepper.php:46
static execAgent()
Определения stepper.php:144
execute(array &$option)
static $moduleId
Определения stepper.php:35
static getModuleId()
Определения stepper.php:255
static createInstance()
Определения stepper.php:246
static getTitle()
Определения stepper.php:135
static Init($arExt=array(), $bReturn=false)
Определения jscore.php:66
$startTime
Определения sync.php:69
$options
Определения commerceml2.php:49
$data['IS_AVAILABLE']
Определения .description.php:13
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$moduleId
$application
Определения bitrix.php:23
EscapePHPString($str, $encloser='"')
Определения tools.php:4917
$name
Определения menu_edit.php:35
if( $daysToExpire >=0 &&$daysToExpire< 60 elseif)( $daysToExpire< 0)
Определения prolog_main_admin.php:393
if(empty($signedUserToken)) $key
Определения quickway.php:257
die
Определения quickway.php:367
font style
Определения invoice.php:442
</p ></td >< td valign=top style='border-top:none;border-left:none;border-bottom:solid windowtext 1.0pt;border-right:solid windowtext 1.0pt;padding:0cm 2.0pt 0cm 2.0pt;height:9.0pt'>< p class=Normal align=center style='margin:0cm;margin-bottom:.0001pt;text-align:center;line-height:normal'>< a name=ТекстовоеПоле54 ></a ><?=($taxRate > count( $arTaxList) > 0) ? $taxRate."%"
Определения waybill.php:936
$title
Определения pdf.php:123
$option
Определения options.php:1711
$val
Определения options.php:1793