ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
class.ilFolderDownloadBackgroundTaskHandler.php
Go to the documentation of this file.
1<?php
2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3
4include_once "Services/BackgroundTask/classes/class.ilZipBackgroundTaskHandler.php";
5
13{
14 protected $settings; // [ilSetting]
15 protected $ref_ids = array(); // [array]
16 // bugfix mantis 24309: array for systematically numbering copied files
17 private static $duplicate_files = array(); // [array]
18
19
20 protected static $initialized; // [bool]
21
22 //
23 // constructor
24 //
25
31 public function __construct()
32 {
33 parent::__construct();
34 $this->settings = new ilSetting("fold");
35 }
36
37 public static function getInstanceFromTask(ilBackgroundTask $a_task)
38 {
39 global $DIC;
40 $tree = $DIC['tree'];
41
42 $obj = new self();
43 $obj->setTask($a_task);
44
45 $params = $a_task->getParams();
46 $obj->setRefIds($params["ref_ids"]);
47
48 $ref_id = (sizeof($params["ref_ids"]) == 1)
49 ? $params["ref_ids"][0]
50 : $tree->getParentId($params["ref_ids"][0]);
51 $obj->setDeliveryFilename(ilObject::_lookupTitle(ilObject::_lookupObjId($ref_id)));
52
53 return $obj;
54 }
55
56
57 //
58 // setter/getter/status
59 //
60
66 public static function isActive()
67 {
68 $settings = new ilSetting("fold");
69 return (bool) $settings->get("bgtask_download", false);
70 }
71
77 public function getRefIds()
78 {
79 return $this->ref_ids;
80 }
81
87 public function setRefIds($a_val)
88 {
89 $this->ref_ids = $a_val;
90 }
91
92
93 //
94 // gui integration
95 //
96
104 public static function getObjectListAction($a_ref_id)
105 {
107
108 return "il.BgTask.init('" . static::class . "', " . $a_ref_id . ");";
109 }
110
111
115 public static function initObjectListAction()
116 {
117 // js init only needed once per request
118 if (!self::$initialized) {
119 global $DIC;
120 $tpl = $DIC['tpl'];
121 $ilCtrl = $DIC['ilCtrl'];
122
123 $url = $ilCtrl->getLinkTargetByClass(array("ilrepositorygui", "ilobjfoldergui", "ilbackgroundtaskhub"), "", "", true, false);
124
125 $tpl->addJavaScript("Services/BackgroundTask/js/BgTask.js");
126 $tpl->addOnLoadCode('il.BgTask.setAjax("' . $url . '");');
127
128 // enable modals from js
129 include_once "Services/UIComponent/Modal/classes/class.ilModalGUI.php";
131
132 self::$initialized = true;
133 }
134 }
135
136
137 //
138 // handler interface
139 //
140
141 public function init($a_params = null)
142 {
143 global $DIC;
144 $lng = $DIC['lng'];
145 $ilUser = $DIC['ilUser'];
146
147 if ($a_params) {
148 $this->setRefIds(explode(",", $a_params));
149 }
150
151 $file_count = $total_bytes = 0;
152 $this->calculateRecursive($this->getRefIds(), $file_count, $total_bytes);
153
154 include_once "Services/BackgroundTask/classes/class.ilBackgroundTaskJson.php";
155
156 // empty folder - nothing to do
157 if (!$file_count) {
158 $json = ilBackgroundTaskJson::getFailedJson($lng->txt("bgtask_empty_folder"));
159 } else {
160 // check if below download size limit
161 $size_limit_mb = $this->getDownloadSizeLimit() * 1024 * 1024;
162 if ($size_limit_mb > 0 && $total_bytes > $size_limit_mb) {
163 $json = ilBackgroundTaskJson::getFailedJson(sprintf($lng->txt("bgtask_download_too_large"), ilUtil::formatSize($size_limit_mb)));
164 } else {
165 // set up task instance
166 include_once "Services/BackgroundTask/classes/class.ilBackgroundTask.php";
167 $task = new ilBackgroundTask();
168 $task->setHandlerId(get_class($this));
169 $task->setUserId($ilUser->getId());
170 $task->setParams(array(
171 "ref_ids" => $this->getRefIds()
172 ));
173 $task->setSteps($file_count+1); // +1 = create zip
175 $task->save();
176
177 $this->setTask($task);
178
179 // above thresholds: do background task
180 if ($file_count >= $this->getFileCountThreshold()
181 || $total_bytes >= $this->getTotalSizeThreshold() * 1024 * 1024) {
182 // check for other tasks from same user
183 $existing = ilBackgroundTask::getActiveByUserId($ilUser->getId());
184 if (sizeof($existing)) {
186 } else {
188 $task->getId(),
189 sprintf($lng->txt("bgtask_download_long"), $file_count, ilUtil::formatSize($total_bytes)),
190 $file_count+1
191 );
192 }
193 }
194 // below thresholds: direct download
195 else {
196 $this->process();
197
199 $task->save();
200
201 $res = $this->finish();
202
203 // see ilBackgroundTaskHub::progress()
204 $json = ilBackgroundTaskJson::getFinishedJson($task->getId(), $res[0], $res[1]);
205 }
206 }
207 }
208
209 return $json;
210 }
211
212 protected function gatherFiles()
213 {
214 $tmpdir = $this->getTempFolderPath();
215
216 $current_step = 0;
217
218 // parse folders
219 foreach ($this->getRefIds() as $ref_id) {
220 // has been cancelled: hurry up
221 if ($this->task->isToBeCancelled()) {
222 return;
223 }
224
225 if (!$this->validateAccess($ref_id)) {
226 continue;
227 }
228
229 $object = ilObjectFactory::getInstanceByRefId($ref_id);
230 switch ($object->getType()) {
231 case "fold":
232 $this->recurseFolder($ref_id, $object->getTitle(), $tmpdir, $current_step);
233 break;
234
235 case "file":
236 $this->copyFile($object->getId(), $object->getTitle(), $tmpdir, $current_step);
237 break;
238 }
239 }
240
241 return $current_step;
242 }
243
244
245 //
246 // processing
247 //
248
256 protected function calculateRecursive($a_ref_ids, &$a_file_count, &$a_file_size)
257 {
258 global $DIC;
259 $tree = $DIC['tree'];
260
261 include_once("./Modules/File/classes/class.ilObjFileAccess.php");
262
263 // parse folders
264 foreach ($a_ref_ids as $ref_id) {
265 if (!$this->validateAccess($ref_id)) {
266 continue;
267 }
268
269 // we are only interested in folders and files
270 switch (ilObject::_lookupType($ref_id, true)) {
271 case "fold":
272 // get child objects
273 $subtree = $tree->getChildsByTypeFilter($ref_id, array("fold", "file"));
274 if (count($subtree) > 0) {
275 $child_ref_ids = array();
276 foreach ($subtree as $child) {
277 $child_ref_ids[] = $child["ref_id"];
278 }
279 $this->calculateRecursive($child_ref_ids, $a_file_count, $a_file_size);
280 }
281 break;
282
283 case "file":
285 $a_file_count += 1;
286 break;
287 }
288 }
289 }
290
299 protected function recurseFolder($a_ref_id, $a_title, $a_tmpdir, &$a_current_step)
300 {
301 global $DIC;
302 $tree = $DIC['tree'];
303
304 $tmpdir = $a_tmpdir . "/" . ilUtil::getASCIIFilename($a_title);
305 ilUtil::makeDir($tmpdir);
306
307 $subtree = $tree->getChildsByTypeFilter($a_ref_id, array("fold", "file"));
308 foreach ($subtree as $child) {
309 // has been cancelled: hurry up
310 if ($this->task->isToBeCancelled()) {
311 return;
312 }
313
314 if (!$this->validateAccess($child["ref_id"])) {
315 continue;
316 }
317
318 switch ($child["type"]) {
319 case "fold":
320 $this->recurseFolder($child["ref_id"], $child["title"], $tmpdir, $a_current_step);
321 break;
322
323 case "file":
324 $this->copyFile($child["obj_id"], $child["title"], $tmpdir, $a_current_step);
325 break;
326 }
327 }
328 }
329
338 protected function copyFile($a_obj_id, $a_title, $a_tmpdir, &$a_current_step)
339 {
340 // :TODO: every file?
341 $this->task->setCurrentStep(++$a_current_step);
342 $this->task->save();
343
344 $new_filename = $a_tmpdir . "/" . ilUtil::getASCIIFilename($a_title);
345
346 // bugfix mantis 24309:
347 // alter the filename if there are identically named files in the same folder to prevent overwriting
348 if (file_exists($new_filename)) {
349 $new_filename = $this->renameDuplicateFile($new_filename);
350 }
351
352 // copy to temporary directory
353 include_once "Modules/File/classes/class.ilObjFile.php";
354 $old_filename = ilObjFile::_lookupAbsolutePath($a_obj_id);
355 if (!copy($old_filename, $new_filename)) {
356 throw new ilFileException("Could not copy " . $old_filename . " to " . $new_filename);
357 }
358
359 touch($new_filename, filectime($old_filename));
360 }
361
362
372 private static function renameDuplicateFile($duplicate_filename)
373 {
374 // determine the copy_number that will be added to the filename either by obtaining it from
375 // the entry of the current file in the duplicate_files-array or use 1 if there is no entry yet
376 $copy_number = 1;
377 $duplicate_has_array_entry = false;
378 foreach (self::$duplicate_files as &$duplicate_file) {
379 if ($duplicate_file['file_name'] == $duplicate_filename) {
380 $duplicate_has_array_entry = true;
381 $copy_number = $duplicate_file['copy_number'];
382 // increment the copy_number for correctly renaming the next duplicate of this file
383 $duplicate_file['copy_number']++;
384 }
385 }
386
387 // create an array entry for the duplicate file if there isn't one to ensure that the
388 // copy_number can be determined correctly for other duplicates of this file
389 if (!$duplicate_has_array_entry) {
390 self::$duplicate_files[] = [
391 'file_name' => $duplicate_filename,
392 'copy_number' => 2 // set as 2 because 1 is already used for this duplicate
393 ];
394 }
395
396 // rename the file
397 $path = pathinfo($duplicate_filename, PATHINFO_DIRNAME);
398 $filename = pathinfo($duplicate_filename, PATHINFO_FILENAME);
399 $extension = pathinfo($duplicate_filename, PATHINFO_EXTENSION);
400 $new_filename = $path . "/" . $filename . " (" . $copy_number . ")." . $extension;
401
402 return $new_filename;
403 }
404
405
412 protected function validateAccess($ref_id)
413 {
414 global $DIC;
415 $ilAccess = $DIC['ilAccess'];
416
417 if (!$ilAccess->checkAccess("read", "", $ref_id)) {
418 return false;
419 }
420
421 if (ilObject::_isInTrash($ref_id)) {
422 return false;
423 }
424
425 return true;
426 }
427
428
429 //
430 // settings
431 //
432
438 protected function getDownloadSizeLimit()
439 {
440 return (int) $this->settings->get("bgtask_download_limit", 0);
441 }
442
448 protected function getFileCountThreshold()
449 {
450 return (int) $this->settings->get("bgtask_download_tcount", 0);
451 }
452
458 protected function getTotalSizeThreshold()
459 {
460 return (int) $this->settings->get("bgtask_download_tsize", 0);
461 }
462}
sprintf('%.4f', $callTime)
$tpl
Definition: ilias.php:10
An exception for terminatinating execution or to throw for unit testing.
static getFailedJson($a_message)
Get json for failed task.
static getProcessingJson($a_task_id, $a_message, $a_steps)
Get json for processing task.
static getFinishedJson($a_task_id, $a_cmd, $a_result)
Get json for finished task.
static getBlockedJson($a_task_id)
Get json for blocked task.
static getActiveByUserId($a_user_id)
getParams()
Gets the params.
Class to report exception.
calculateRecursive($a_ref_ids, &$a_file_count, &$a_file_size)
Calculates the number and size of the files being downloaded recursively.
static isActive()
Is folder background download active?
recurseFolder($a_ref_id, $a_title, $a_tmpdir, &$a_current_step)
Copies a folder and its files to the specified temporary directory.
copyFile($a_obj_id, $a_title, $a_tmpdir, &$a_current_step)
Copies a file to the specified temporary directory.
static renameDuplicateFile($duplicate_filename)
bugfix mantis 24309: add a number in round brackets to the filename (in front of the file-type-extens...
static getObjectListAction($a_ref_id)
Get object list action.
static getInstanceFromTask(ilBackgroundTask $a_task)
Constructor/Factory.
static initJS(ilTemplate $a_main_tpl=null)
Init javascript.
static _lookupFileSize($a_id)
Quickly looks up the file size from the database and returns the number of bytes.
static _lookupAbsolutePath($obj_id, $a_version=null)
static getInstanceByRefId($a_ref_id, $stop_on_error=true)
get an instance of an Ilias object by reference id
static _lookupObjId($a_id)
static _lookupTitle($a_id)
lookup object title
static _isInTrash($a_ref_id)
checks wether object is in trash
static _lookupType($a_id, $a_reference=false)
lookup object type
ILIAS Setting Class.
static formatSize($size, $a_mode='short', $a_lng=null)
Returns the specified file size value in a human friendly form.
static getASCIIFilename($a_filename)
convert utf8 to ascii filename
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
Background task handler for zip creation.
setTask(ilBackgroundTask $a_task)
Set current task instance.
getTempFolderPath()
Gets the temporary folder path to copy the files and folders to.
global $ilCtrl
Definition: ilias.php:18
global $lng
Definition: privfeed.php:17
$url
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
settings()
Definition: settings.php:2
$ilUser
Definition: imgupload.php:18
$params
Definition: disable.php:11