ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilLearningProgressBaseGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=0);
20 
26 
36 {
38  protected HttpServices $http;
40  protected ilHelpGUI $help;
42  protected ilLanguage $lng;
43  protected ilLogger $logger;
44  protected ilTabsGUI $tabs_gui;
47  protected ilObjUser $user;
51  protected ilTree $tree;
55 
56  protected bool $anonymized;
57  protected int $usr_id = 0;
58  protected int $ref_id = 0;
59  protected int $obj_id = 0;
60  protected string $obj_type = '';
61  protected int $mode = 0;
62 
63  public const LP_CONTEXT_PERSONAL_DESKTOP = 1;
64  public const LP_CONTEXT_ADMINISTRATION = 2;
65  public const LP_CONTEXT_REPOSITORY = 3;
66  public const LP_CONTEXT_USER_FOLDER = 4;
67  public const LP_CONTEXT_ORG_UNIT = 5;
68 
69  protected const LP_ACTIVE_SETTINGS = 1;
70  protected const LP_ACTIVE_OBJECTS = 2;
71  protected const LP_ACTIVE_PROGRESS = 3;
72 
73  protected const LP_ACTIVE_USERS = 5;
74  protected const LP_ACTIVE_SUMMARY = 6;
75  protected const LP_ACTIVE_OBJSTATACCESS = 7;
76  protected const LP_ACTIVE_OBJSTATTYPES = 8;
77  protected const LP_ACTIVE_OBJSTATDAILY = 9;
78  protected const LP_ACTIVE_OBJSTATADMIN = 10;
79  protected const LP_ACTIVE_MATRIX = 11;
80 
81  public function __construct(
82  int $a_mode,
83  int $a_ref_id = 0,
84  int $a_usr_id = 0
85  ) {
86  global $DIC;
87 
88  $this->tpl = $DIC->ui()->mainTemplate();
89  $this->help = $DIC->help();
90  $this->ctrl = $DIC->ctrl();
91  $this->lng = $DIC->language();
92  $this->lng->loadLanguageModule('trac');
93  $this->tabs_gui = $DIC->tabs();
94  $this->toolbar = $DIC->toolbar();
95  $this->ilObjectDataCache = $DIC['ilObjDataCache'];
96  $this->user = $DIC->user();
97  $this->access = $DIC->access();
98  $this->rbacsystem = $DIC->rbac()->system();
99  $this->rbacreview = $DIC->rbac()->review();
100  $this->tree = $DIC->repositoryTree();
101  $this->lom_services = $DIC->learningObjectMetadata();
102 
103  $this->http = $DIC->http();
104  $this->refinery = $DIC->refinery();
105  $this->ui_factory = $DIC->ui()->factory();
106  $this->ui_renderer = $DIC->ui()->renderer();
107 
108  $this->mode = $a_mode;
109  $this->ref_id = $a_ref_id;
110  $this->obj_id = $this->ilObjectDataCache->lookupObjId($this->ref_id);
111  $this->obj_type = $this->ilObjectDataCache->lookupType($this->obj_id);
112  $this->usr_id = $a_usr_id;
113 
114  $this->anonymized = !ilObjUserTracking::_enabledUserRelatedData();
115  if (!$this->anonymized && $this->obj_id) {
116  $olp = ilObjectLP::getInstance($this->obj_id);
117  $this->anonymized = $olp->isAnonymized();
118  }
119  $this->logger = $DIC->logger()->trac();
120  }
121 
122  public function isAnonymized(): bool
123  {
124  return $this->anonymized;
125  }
126 
127  public function getMode(): int
128  {
129  return $this->mode;
130  }
131 
132  public function getRefId(): int
133  {
134  return $this->ref_id;
135  }
136 
137  public function getObjId(): int
138  {
139  return $this->obj_id;
140  }
141 
142  protected function initUserIdFromQuery(): int
143  {
144  if ($this->http->wrapper()->query()->has('user_id')) {
145  return $this->http->wrapper()->query()->retrieve(
146  'user_id',
147  $this->refinery->kindlyTo()->int()
148  );
149  }
150  return 0;
151  }
152 
153  public function getUserId(): int
154  {
155  if ($this->usr_id) {
156  return $this->usr_id;
157  }
158  if ($this->initUserIdFromQuery()) {
159  return $this->initUserIdFromQuery();
160  }
161  return 0;
162  }
163 
164  public function __getDefaultCommand(): string
165  {
166  if (strlen($cmd = $this->ctrl->getCmd())) {
167  return $cmd;
168  }
169  return 'show';
170  }
171 
172  public function __setSubTabs(int $a_active): void
173  {
174  switch ($this->getMode()) {
175  case self::LP_CONTEXT_PERSONAL_DESKTOP:
176 
179  $this->tabs_gui->addTarget(
180  'trac_progress',
181  $this->ctrl->getLinkTargetByClass(
182  'illplistofprogressgui',
183  ''
184  ),
185  "",
186  "",
187  "",
188  $a_active == self::LP_ACTIVE_PROGRESS
189  );
190  }
191  break;
192 
193  case self::LP_CONTEXT_REPOSITORY:
194  // #12771 - do not show status if learning progress is deactivated
195  $olp = ilObjectLP::getInstance($this->obj_id);
196  if ($olp->isActive()) {
198  'read_learning_progress',
199  $this->getRefId()
200  );
201 
202  if ($this->isAnonymized() || !$has_read) {
203  $this->ctrl->setParameterByClass(
204  'illplistofprogressgui',
205  'user_id',
206  $this->getUserId()
207  );
208  $this->tabs_gui->addSubTabTarget(
209  'trac_progress',
210  $this->ctrl->getLinkTargetByClass(
211  'illplistofprogressgui',
212  ''
213  ),
214  "",
215  "",
216  "",
217  $a_active == self::LP_ACTIVE_PROGRESS
218  );
219  } else {
220  // Check if it is a course
221  $sub_tab = ($this->ilObjectDataCache->lookupType(
222  $this->ilObjectDataCache->lookupObjId(
223  $this->getRefId()
224  )
225  ) == 'crs') ?
226  'trac_crs_objects' :
227  'trac_objects';
228 
229  $this->tabs_gui->addSubTabTarget(
230  $sub_tab,
231  $this->ctrl->getLinkTargetByClass(
232  "illplistofobjectsgui",
233  ''
234  ),
235  "",
236  "",
237  "",
238  $a_active == self::LP_ACTIVE_OBJECTS
239  );
240  }
241 
242  if ($has_read) {
243  if (!$this->isAnonymized() &&
244  !($olp instanceof ilPluginLP) &&
245  ilObjectLP::supportsMatrixView($this->obj_type)) {
246  $this->tabs_gui->addSubTabTarget(
247  "trac_matrix",
248  $this->ctrl->getLinkTargetByClass(
249  "illplistofobjectsgui",
250  'showUserObjectMatrix'
251  ),
252  "",
253  "",
254  "",
255  $a_active == self::LP_ACTIVE_MATRIX
256  );
257  }
258 
259  $this->tabs_gui->addSubTabTarget(
260  "trac_summary",
261  $this->ctrl->getLinkTargetByClass(
262  "illplistofobjectsgui",
263  'showObjectSummary'
264  ),
265  "",
266  "",
267  "",
268  $a_active == self::LP_ACTIVE_SUMMARY
269  );
270  }
271  }
272  if (!($olp instanceof ilPluginLP) &&
274  'edit_learning_progress',
275  $this->getRefId()
276  )) {
277  $this->tabs_gui->addSubTabTarget(
278  'trac_settings',
279  $this->ctrl->getLinkTargetByClass(
280  'illplistofsettingsgui',
281  ''
282  ),
283  "",
284  "",
285  "",
286  $a_active == self::LP_ACTIVE_SETTINGS
287  );
288  }
289  break;
290 
291  case self::LP_CONTEXT_USER_FOLDER:
292  case self::LP_CONTEXT_ORG_UNIT:
293  // No tabs default class is lpprogressgui
294  break;
295 
296  default:
297  die('No valid mode given');
298  break;
299  }
300  }
301 
302  public function __buildFooter(): void
303  {
304  switch ($this->getMode()) {
305  case self::LP_CONTEXT_PERSONAL_DESKTOP:
306  $this->tpl->printToStdout();
307  }
308  }
309 
310  public function __buildHeader(): void
311  {
312  }
313 
318  public static function _getStatusText(
319  int $a_status,
320  ?ilLanguage $a_lng = null
321  ): string {
322  global $DIC;
323 
324  $lng = $DIC->language();
325  if (!$a_lng) {
326  $a_lng = $lng;
327  }
328  switch ($a_status) {
330  return $a_lng->txt(ilLPStatus::LP_STATUS_IN_PROGRESS);
331 
333  return $a_lng->txt(ilLPStatus::LP_STATUS_COMPLETED);
334 
336  return $a_lng->txt(ilLPStatus::LP_STATUS_FAILED);
337 
338  default:
339  if ($a_status === ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM) {
340  return $a_lng->txt(ilLPStatus::LP_STATUS_NOT_ATTEMPTED);
341  }
342  return $a_lng->txt((string) $a_status);
343  }
344  }
345 
349  public function __showObjectDetails(
351  int $item_id = 0,
352  string $item_type = '',
353  bool $add_section = true
354  ): bool {
355  $details_id = $item_id ?: $this->details_id;
356  $details_type = $item_type ?: $this->details_type;
357 
358  $olp = ilObjectLP::getInstance($details_id);
359  $mode = $olp->getCurrentMode();
360  if (
362  $this->readTypicalLearningTimeInSeconds($details_id, 0, $details_type)
363  ) {
364  // Section object details
365  if ($add_section) {
366  $info->addSection($this->lng->txt('details'));
367  }
368 
369  if ($mode == ilLPObjSettings::LP_MODE_VISITS) {
370  $info->addProperty(
371  $this->lng->txt('trac_required_visits'),
372  (string) ilLPObjSettings::_lookupVisits($details_id)
373  );
374  }
375 
376  if ($seconds = $this->readTypicalLearningTimeInSeconds($details_id, 0, $details_type)) {
377  $info->addProperty(
378  $this->lng->txt('meta_typical_learning_time'),
380  );
381  }
382  return true;
383  }
384  return false;
385  }
386 
387  protected function readTypicalLearningTimeInSeconds(int $obj_id, int $sub_id, string $type): int
388  {
389  $paths = $this->lom_services->paths();
390  $data_helper = $this->lom_services->dataHelper();
391 
392  $value = $this->lom_services->read($obj_id, $sub_id, $type, $paths->firstTypicalLearningTime())
393  ->firstData($paths->firstTypicalLearningTime())
394  ->value();
395 
396  return $data_helper->durationToSeconds($value);
397  }
398 
399  public function __appendLPDetails(
401  int $item_id,
402  int $user_id
403  ): void {
404  $type = $this->ilObjectDataCache->lookupType($item_id);
405  // Section learning_progress
406  // $info->addSection($this->lng->txt('trac_learning_progress'));
407  // see ilLPTableBaseGUI::parseTitle();
408  $info->addSection(
409  $this->lng->txt("trac_progress") . ": " . ilObject::_lookupTitle(
410  $item_id
411  )
412  );
413  $olp = ilObjectLP::getInstance($item_id);
414  $info->addProperty(
415  $this->lng->txt('trac_mode'),
416  $olp->getModeText($olp->getCurrentMode())
417  );
418 
421 
423  ilLPStatus::_lookupStatus($item_id, $user_id)
424  );
425  $info->addProperty(
426  $this->lng->txt('trac_status'),
427  $icons->renderIconForStatus(ilLPStatus::_lookupStatus($item_id, $user_id)) .
428  " " .
429  $status_text
430  );
431 
432  if ($olp->getCurrentMode() === ilLPObjSettings::LP_MODE_MANUAL) {
433  // status
434  $i_tpl = new ilTemplate(
435  "tpl.lp_edit_manual_info_page.html",
436  true,
437  true,
438  "components/ILIAS/Tracking"
439  );
440  $i_tpl->setVariable(
441  "INFO_EDITED",
442  $this->lng->txt("trac_info_edited")
443  );
444  $i_tpl->setVariable(
445  "SELECT_STATUS",
448  $user_id,
449  $item_id
450  ),
451  'lp_edit',
452  [0 => $this->lng->txt('trac_not_completed'),
453  1 => $this->lng->txt('trac_completed')
454  ],
455  false,
456  true
457  )
458  );
459  $i_tpl->setVariable("TXT_SAVE", $this->lng->txt("save"));
460  $info->addProperty($this->lng->txt('trac_status'), $i_tpl->get());
461  }
462 
463  // #15334 - see ilLPTableBaseGUI::isPercentageAvailable()
464  $mode = $olp->getCurrentMode();
465  if (in_array(
466  $mode,
469  // ilLPObjSettings::LP_MODE_OBJECTIVES,
479  )
480  )) {
481  $perc = ilLPStatus::_lookupPercentage($item_id, $user_id);
482  $info->addProperty(
483  $this->lng->txt('trac_percentage'),
484  (int) $perc . "%"
485  );
486  }
487  }
488 
489  if (ilObjectLP::supportsMark($type)) {
490  if (strlen($mark = ilLPMarks::_lookupMark($user_id, $item_id))) {
491  $info->addProperty($this->lng->txt('trac_mark'), $mark);
492  }
493  }
494 
495  if (strlen($comment = ilLPMarks::_lookupComment($user_id, $item_id))) {
496  $info->addProperty($this->lng->txt('trac_comment'), $comment);
497  }
498 
499  // More infos for lm's
500  if (in_array($type, ["lm", "htlm"])) {
501  $progress = ilLearningProgress::_getProgress($user_id, $item_id);
502  if ($progress['access_time'] ?? false) {
503  $info->addProperty(
504  $this->lng->txt('trac_last_access'),
506  new ilDateTime($progress['access_time'], IL_CAL_UNIX)
507  )
508  );
509  } else {
510  $info->addProperty(
511  $this->lng->txt('trac_last_access'),
512  $this->lng->txt('trac_not_accessed')
513  );
514  }
515 
516  $info->addProperty(
517  $this->lng->txt('trac_visits'),
518  (string) ($progress['visits'] ?? "")
519  );
520 
521  if ($type == 'lm') {
522  $info->addProperty(
523  $this->lng->txt('trac_spent_time'),
525  $progress['spent_seconds']
526  )
527  );
528  }
529  }
530  }
531 
533  public static function __readStatus(int $a_obj_id, int $user_id): string
534  {
535  $status = ilLPStatus::_lookupStatus($a_obj_id, $user_id);
536 
537  switch ($status) {
540 
543 
546 
547  default:
550  }
551  }
552 
553  public function __getLegendHTML(int $variant = ilLPStatusIcons::ICON_VARIANT_LONG): string
554  {
555  $icons = ilLPStatusIcons::getInstance($variant);
556 
557  $tpl = new ilTemplate(
558  "tpl.lp_legend.html",
559  true,
560  true,
561  "components/ILIAS/Tracking"
562  );
563  $tpl->setVariable(
564  "IMG_NOT_ATTEMPTED",
565  $icons->renderIconForStatus(ilLPStatus::LP_STATUS_NOT_ATTEMPTED_NUM)
566  );
567  $tpl->setVariable(
568  "IMG_IN_PROGRESS",
569  $icons->renderIconForStatus(ilLPStatus::LP_STATUS_IN_PROGRESS_NUM)
570  );
571  $tpl->setVariable(
572  "IMG_COMPLETED",
573  $icons->renderIconForStatus(ilLPStatus::LP_STATUS_COMPLETED_NUM)
574  );
575  $tpl->setVariable(
576  "IMG_FAILED",
577  $icons->renderIconForStatus(ilLPStatus::LP_STATUS_FAILED_NUM)
578  );
579  $tpl->setVariable(
580  "TXT_NOT_ATTEMPTED",
581  $this->lng->txt("trac_not_attempted")
582  );
583  $tpl->setVariable(
584  "TXT_IN_PROGRESS",
585  $this->lng->txt("trac_in_progress")
586  );
587  $tpl->setVariable(
588  "TXT_COMPLETED",
589  $this->lng->txt("trac_completed")
590  );
591  $tpl->setVariable(
592  "TXT_FAILED",
593  $this->lng->txt("trac_failed")
594  );
595 
596  $panel = $this->ui_factory->panel()->secondary()->legacy(
597  '',
598  $this->ui_factory->legacy()->content($tpl->get())
599  );
600 
601  return $this->ui_renderer->render($panel);
602  }
603 
604  protected function initEditUserForm(
605  int $a_user_id,
606  int $a_obj_id,
607  ?string $a_cancel = null
608  ): ilPropertyFormGUI {
609  $olp = ilObjectLP::getInstance($a_obj_id);
610  $lp_mode = $olp->getCurrentMode();
611 
612  $form = new ilPropertyFormGUI();
613 
614  $form->setFormAction($this->ctrl->getFormAction($this, "updateUser"));
615 
616  $form->setTitle(
617  $this->lng->txt("edit") . ": " . ilObject::_lookupTitle($a_obj_id)
618  );
619  $form->setDescription(
620  $this->lng->txt('trac_mode') . ": " . $olp->getModeText($lp_mode)
621  );
622 
623  $user = new ilNonEditableValueGUI($this->lng->txt("user"), '', true);
624  $user->setValue(ilUserUtil::getNamePresentation($a_user_id, true));
625  $form->addItem($user);
626 
627  $marks = new ilLPMarks($a_obj_id, $a_user_id);
628 
630  $mark = new ilTextInputGUI($this->lng->txt("trac_mark"), "mark");
631  $mark->setValue($marks->getMark());
632  $mark->setMaxLength(32);
633  $form->addItem($mark);
634  }
635 
636  $comm = new ilTextInputGUI($this->lng->txt("trac_comment"), "comment");
637  $comm->setValue($marks->getComment());
638  $form->addItem($comm);
639 
640  if ($lp_mode == ilLPObjSettings::LP_MODE_MANUAL ||
642  $completed = ilLPStatus::_lookupStatus($a_obj_id, $a_user_id);
643 
644  $status = new ilCheckboxInputGUI(
645  $this->lng->txt('trac_completed'),
646  "completed"
647  );
648  $status->setChecked(
650  );
651  $form->addItem($status);
652  }
653 
654  $form->addCommandButton("updateUser", $this->lng->txt('save'));
655 
656  if ($a_cancel) {
657  $form->addCommandButton($a_cancel, $this->lng->txt('cancel'));
658  }
659 
660  return $form;
661  }
662 
663  public function __showEditUser(
664  int $a_user_id,
665  int $a_ref_id,
666  ?string $a_cancel = null,
667  int $a_sub_id = 0
668  ): string {
669  if (!$a_sub_id) {
670  $obj_id = ilObject::_lookupObjId($a_ref_id);
671  } else {
672  $this->ctrl->setParameter($this, 'userdetails_id', $a_sub_id);
673  $obj_id = ilObject::_lookupObjId($a_sub_id);
674  }
675  $this->ctrl->setParameter($this, 'user_id', $a_user_id);
676  $this->ctrl->setParameter($this, 'details_id', $a_ref_id);
677  $form = $this->initEditUserForm($a_user_id, $obj_id, $a_cancel);
678  return $form->getHTML();
679  }
680 
681  public function __updateUser(int $user_id, int $obj_id): void
682  {
683  $form = $this->initEditUserForm($user_id, $obj_id);
684  if ($form->checkInput()) {
685  $marks = new ilLPMarks($obj_id, $user_id);
686  $marks->setMark($form->getInput("mark"));
687  $marks->setComment($form->getInput("comment"));
688 
689  $do_lp = false;
690 
691  // status/completed is optional
692  $status = $form->getItemByPostVar("completed");
693  if (is_object($status)) {
694  if ($marks->getCompleted() != $form->getInput("completed")) {
695  $marks->setCompleted($form->getInput("completed"));
696  $do_lp = true;
697  }
698  }
699 
700  $marks->update();
701 
702  // #11600
703  if ($do_lp) {
704  ilLPStatusWrapper::_updateStatus($obj_id, $user_id);
705  }
706  }
707  }
708 
715  public static function isObjectOffline(
716  int $a_obj_id,
717  string $a_type = ''
718  ): bool {
719  global $DIC;
720 
721  $objDefinition = $DIC['objDefinition'];
722  $ilObjDataCache = $DIC['ilObjDataCache'];
723 
724  if (!$a_type) {
725  $a_type = $ilObjDataCache->lookupType($a_obj_id);
726  }
727 
728  if ($objDefinition->isPluginTypeName($a_type)) {
729  return false;
730  }
731  $class = "ilObj" . $objDefinition->getClassName($a_type) . "Access";
732  return (bool) $class::_isOffline($a_obj_id);
733  }
734 }
const LP_STATUS_COMPLETED_NUM
static _lookupVisits(int $a_obj_id)
readTypicalLearningTimeInSeconds(int $obj_id, int $sub_id, string $type)
__showEditUser(int $a_user_id, int $a_ref_id, ?string $a_cancel=null, int $a_sub_id=0)
static _lookupComment(int $a_usr_id, int $a_obj_id)
__showObjectDetails(ilInfoScreenGUI $info, int $item_id=0, string $item_type='', bool $add_section=true)
show details about current object.
static _getProgress(int $a_user_id, int $a_obj_id)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static isSupportedObjectType(string $type)
static supportsMatrixView(string $obj_type)
const LP_STATUS_NOT_ATTEMPTED
Help GUI class.
static _lookupPercentage(int $a_obj_id, int $a_user_id)
Lookup percentage.
addProperty(string $a_name, string $a_value, string $a_link="")
add a property to current section
const LP_STATUS_IN_PROGRESS_NUM
static getInstance(int $variant=ilLPStatusIcons::ICON_VARIANT_DEFAULT, ?\ILIAS\UI\Renderer $renderer=null, ?\ILIAS\UI\Factory $factory=null)
static formSelect( $selected, string $varname, array $options, bool $multiple=false, bool $direct_text=false, int $size=0, string $style_class="", array $attribs=[], bool $disabled=false)
Builds a select form field with options and shows the selected option first.
const IL_CAL_UNIX
setVariable(string $variable, $value='')
Sets the given variable to the given value.
static secondsToString(int $seconds, bool $force_with_seconds=false, ?ilLanguage $a_lng=null)
converts seconds to string: Long: 7 days 4 hour(s) ...
initEditUserForm(int $a_user_id, int $a_obj_id, ?string $a_cancel=null)
const LP_STATUS_IN_PROGRESS
static _lookupObjId(int $ref_id)
static _hasCompleted(int $a_usr_id, int $a_obj_id)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static http()
Fetches the global http state from ILIAS.
const LP_STATUS_FAILED
static getNamePresentation( $a_user_id, bool $a_user_image=false, bool $a_profile_link=false, string $a_profile_back_link='', bool $a_force_first_lastname=false, bool $a_omit_login=false, bool $a_sortable=true, bool $a_return_data_array=false, $a_ctrl_path='ilpublicuserprofilegui')
Default behaviour is:
static _lookupTitle(int $obj_id)
global $DIC
Definition: shib_login.php:26
addSection(string $a_title)
static _getStatusText(int $a_status, ?ilLanguage $a_lng=null)
Get status alt text.
get(string $part=self::DEFAULT_BLOCK)
Renders the given block and returns the html string.
static _lookupStatus(int $a_obj_id, int $a_user_id, bool $a_create=true)
Lookup status.
$comment
Definition: buildRTE.php:72
const LP_STATUS_NOT_ATTEMPTED_NUM
static _lookupMark(int $a_usr_id, int $a_obj_id)
__construct(int $a_mode, int $a_ref_id=0, int $a_usr_id=0)
static __readStatus(int $a_obj_id, int $user_id)
PhpInconsistentReturnPointsInspection
__appendLPDetails(ilInfoScreenGUI $info, int $item_id, int $user_id)
const LP_MODE_CMIX_COMPL_OR_PASSED_WITH_FAILED
static checkPermission(string $a_permission, int $a_ref_id, ?int $a_user_id=null)
wrapper for rbac access checks
static formatDate(ilDateTime $date, bool $a_skip_day=false, bool $a_include_wd=false, bool $include_seconds=false, ?ilObjUser $user=null,)
$info
Definition: entry_point.php:21
__getLegendHTML(int $variant=ilLPStatusIcons::ICON_VARIANT_LONG)
static supportsMark(string $obj_type)
static _lookupType(int $id, bool $reference=false)
static isObjectOffline(int $a_obj_id, string $a_type='')
const LP_STATUS_COMPLETED
static getInstance(int $obj_id)
const LP_STATUS_FAILED_NUM
static _updateStatus(int $a_obj_id, int $a_usr_id, ?object $a_obj=null, bool $a_percentage=false, bool $a_force_raise=false)