1<?php 2 3use ILIAS\BackgroundTasks\Bucket; 4use ILIAS\BackgroundTasks\Implementation\Bucket\State; 5use ILIAS\BackgroundTasks\Implementation\Tasks\AbstractTask; 6use ILIAS\BackgroundTasks\Implementation\UI\StateTranslator; 7use ILIAS\BackgroundTasks\Task\UserInteraction; 8use ILIAS\UI\Component\Button\Button; 9use ILIAS\UI\Component\Button\Shy; 10use ILIAS\UI\Component\Legacy\Legacy; 11 12/** 13 * Class ilBTPopOverGUI 14 * 15 * @author Oskar Truffer <ot@studer-raimann.ch> 16 * @author Fabian Schmid <fs@studer-raimann.ch> 17 */ 18class ilBTPopOverGUI 19{ 20 use StateTranslator; 21 /** 22 * @var \ILIAS\DI\Container 23 */ 24 protected $dic; 25 26 27 public function __construct(\ILIAS\DI\Container $dic) 28 { 29 $this->dic = $dic; 30 } 31 32 33 /** 34 * Get the Notification Items. DOES NOT DO ANY PERMISSION CHECKS. 35 */ 36 public function getNotificationItem(int $nr_buckets) : ILIAS\UI\Component\Item\Notification 37 { 38 $ui_factory = $this->dic->ui()->factory(); 39 40 $title = $ui_factory->link()->standard($this->txt('background_tasks'), '#'); 41 $icon = $ui_factory->symbol()->icon()->standard('bgtk', $this->txt('background_tasks')); 42 43 return $this->dic->ui()->factory() 44 ->item() 45 ->notification($title, $icon) 46 ->withDescription("$nr_buckets {$this->txt('background_tasks')}") 47 ->withAggregateNotifications($this->getAggregateItems()); 48 } 49 50 51 /** 52 * @return ILIAS\UI\Component\Item\Notification[] 53 */ 54 protected function getAggregateItems() : array 55 { 56 $persistence = $this->dic->backgroundTasks()->persistence(); 57 $items = []; 58 $observer_ids = $persistence->getBucketIdsOfUser($this->dic->user()->getId(), 'id', 'DESC'); 59 foreach ($persistence->loadBuckets($observer_ids) as $observer) { 60 $items[] = $this->getItemForObserver($observer); 61 } 62 63 return $items; 64 } 65 66 67 public function getItemForObserver(Bucket $observer) : ILIAS\UI\Component\Item\Notification 68 { 69 $redirect_uri = "//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}"; 70 71 $f = $this->dic->ui()->factory(); 72 73 $state = (int) $observer->getState(); 74 $current_task = $observer->getCurrentTask(); 75 76 $icon = $f->symbol()->icon()->standard("bgtk", $this->txt("bg_task")); 77 $title = $observer->getTitle() . ($state === State::SCHEDULED ? " ({$this->txt('scheduled')})" : ""); 78 79 if ($state === State::USER_INTERACTION) { 80 $actions = $this->getUserInteractionContent($observer, $redirect_uri); 81 $primary_action = array_pop($actions); 82 if ($primary_action instanceof Button) { 83 $title = $primary_action->withLabel($title); 84 } 85 $item = $f->item()->notification($title, $icon); 86 87// $item = $item->withProperties([ 88// $this->dic->language()->txt('nc_mail_prop_time') => \ilDatePresentation::formatDate( 89// new \ilDateTime(time(), IL_CAL_UNIX) 90// ) 91// ]); 92 93 $item = $item->withActions($f->dropdown()->standard($actions)); 94 $input = $current_task->getInput(); 95 $message = $current_task->getMessage($input); 96 97 if ((!empty($message)) and ($message != null)) { 98 $item = $item->withDescription($message); 99 } else { 100 $item = $item->withAdditionalContent($this->getProgressbar($observer)); 101 } 102 103 return $item->withCloseAction( 104 $this->getCloseButtonAction($current_task->getRemoveOption(), $redirect_uri, $observer) 105 ); 106 } 107 108 $item = $f->item()->notification($title, $icon); 109 110 if ($state === State::RUNNING) { 111 $url = $this->getRefreshUrl($observer); 112 //Running Items probably need to refresh themselves, right? 113 $item = $item->withAdditionalOnLoadCode(function ($id) use ($url) { 114 //Note this is only for demo purposes, adapt as needed. 115 return "var notification_item = il.UI.item.notification.getNotificationItemObject($('#$id')); 116 il.BGTask.refreshItem(notification_item,'$url');"; 117 }); 118 119 $expected = $current_task->getExpectedTimeOfTaskInSeconds(); 120 $possibly_failed = ($observer->getLastHeartbeat() < (time() - $expected)); 121 if ($possibly_failed === true) { 122 $item = $item->withDescription($this->txt('task_might_be_failed')); 123 $item = $item->withCloseAction( 124 $this->getCloseButtonAction($current_task->getAbortOption(), $redirect_uri, $observer) 125 ); 126 } 127 } 128 129 return $item->withAdditionalContent($this->getDefaultCardContent($observer)); 130 } 131 132 133 private function getDefaultCardContent(Bucket $observer) : Legacy 134 { 135 return $this->getProgressbar($observer); 136 } 137 138 139 /** 140 * @return Shy[] 141 */ 142 public function getUserInteractionContent(Bucket $observer, string $redirect_uri) : array 143 { 144 $factory = $this->dic->ui()->factory(); 145 $language = $this->dic->language(); 146 $persistence = $this->dic->backgroundTasks()->persistence(); 147 $ctrl = $this->dic->ctrl(); 148 149 if (!$observer->getCurrentTask() instanceof UserInteraction) { 150 return [$factory->legacy('')]; 151 } 152 /** @var UserInteraction $userInteraction */ 153 $userInteraction = $observer->getCurrentTask(); 154 $options = $userInteraction->getOptions($userInteraction->getInput()); 155 156 $shy_buttons = array_map( 157 function (UserInteraction\Option $option) use ($ctrl, $factory, $observer, $persistence, $redirect_uri, $language) { 158 $ctrl->setParameterByClass( 159 ilBTControllerGUI::class, 160 ilBTControllerGUI::FROM_URL, 161 ilBTControllerGUI::hash("//{$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}") 162 ); 163 $ctrl->setParameterByClass( 164 ilBTControllerGUI::class, 165 ilBTControllerGUI::SELECTED_OPTION, 166 $option->getValue() 167 ); 168 $ctrl->setParameterByClass( 169 ilBTControllerGUI::class, 170 ilBTControllerGUI::OBSERVER_ID, 171 $persistence->getBucketContainerId($observer) 172 ); 173 $this->addFromUrlToNextRequest($redirect_uri); 174 175 return $factory->button() 176 ->shy( 177 $language->txt($option->getLangVar()), 178 $ctrl->getLinkTargetByClass([ilBTControllerGUI::class], ilBTControllerGUI::CMD_USER_INTERACTION) 179 ); 180 }, 181 $options 182 ); 183 184 return $shy_buttons; 185 } 186 187 188 private function getProgressbar(Bucket $observer) : Legacy 189 { 190 $percentage = $observer->getOverallPercentage(); 191 192 switch (true) { 193 case ((int) $percentage === 100): 194 $running = ""; 195 $content = $this->dic->language()->txt("completed"); 196 break; 197 case ((int) $observer->getState() === State::USER_INTERACTION): 198 $running = ""; 199 $content = $this->dic->language()->txt("waiting"); 200 break; 201 default: 202 $running = "active"; 203 $content = "{$percentage}%"; 204 break; 205 } 206 207 return $this->dic->ui()->factory()->legacy(" <div class='progress'> 208 <div class='progress-bar progress-bar-striped {$running}' role='progressbar' aria-valuenow='{$percentage}' 209 aria-valuemin='0' aria-valuemax='100' style='width:{$percentage}%'> 210 {$content} 211 </div> 212 </div> "); 213 } 214 215 216 private function getCloseButtonAction(UserInteraction\Option $option, $redirect_uri, Bucket $observer) : string 217 { 218 $ctrl = $this->dic->ctrl(); 219 $persistence = $this->dic->backgroundTasks()->persistence(); 220 $ctrl->setParameterByClass(ilBTControllerGUI::class, ilBTControllerGUI::OBSERVER_ID, $persistence->getBucketContainerId($observer)); 221 $this->addFromUrlToNextRequest($redirect_uri); 222 $ctrl->setParameterByClass(ilBTControllerGUI::class, ilBTControllerGUI::IS_ASYNC, "true"); 223 224 switch ($option->getValue()) { 225 case AbstractTask::MAIN_ABORT: 226 $action = $ctrl->getLinkTargetByClass([ilBTControllerGUI::class], ilBTControllerGUI::CMD_ABORT); 227 break; 228 case AbstractTask::MAIN_REMOVE: 229 $action = $ctrl->getLinkTargetByClass([ilBTControllerGUI::class], ilBTControllerGUI::CMD_REMOVE); 230 break; 231 default: 232 $ctrl->setParameterByClass(ilBTControllerGUI::class, ilBTControllerGUI::SELECTED_OPTION, $option->getValue()); 233 $action = $ctrl->getLinkTargetByClass([ilBTControllerGUI::class], ilBTControllerGUI::CMD_USER_INTERACTION); 234 break; 235 } 236 237 return $action; 238 } 239 240 241 private function getRefreshUrl(Bucket $observer) : string 242 { 243 $ctrl = $this->dic->ctrl(); 244 $persistence = $this->dic->backgroundTasks()->persistence(); 245 $ctrl->setParameterByClass(ilBTControllerGUI::class, ilBTControllerGUI::OBSERVER_ID, $persistence->getBucketContainerId($observer)); 246 247 return $ctrl->getLinkTargetByClass([ilBTControllerGUI::class], ilBTControllerGUI::CMD_GET_REPLACEMENT_ITEM); 248 } 249 250 251 private function addFromUrlToNextRequest(string $redirect_uri) : void 252 { 253 $this->dic->ctrl()->setParameterByClass(ilBTControllerGUI::class, ilBTControllerGUI::FROM_URL, ilBTControllerGUI::hash($redirect_uri)); 254 } 255 256 257 private function txt(string $id) : string 258 { 259 return $this->dic->language()->txt($id); 260 } 261} 262