ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilCollectFilesJob.php
Go to the documentation of this file.
1 <?php
2 
24 
32 {
34 
35  private ?ilLogger $logger;
41  private static array $targets = [];
42 
46  public function __construct()
47  {
48  global $DIC;
49  $this->logger = $DIC->logger()->cal();
50  }
51 
52 
56  public function getInputTypes(): array
57  {
58  return
59  [
60  new SingleType(ilCopyDefinition::class),
61  new SingleType(BooleanValue::class),
62  ];
63  }
64 
65 
69  public function getOutputType(): Type
70  {
71  return new SingleType(ilCopyDefinition::class);
72  }
73 
74 
78  public function isStateless(): bool
79  {
80  return true;
81  }
82 
83 
88  public function run(array $input, \ILIAS\BackgroundTasks\Observer $observer): Value
89  {
90  $this->logger->debug('Start collecting files!');
91  $this->logger->dump($input);
92  $definition = $input[0];
93  $initiated_by_folder_action = $input[1]->getValue();
94  $object_ref_ids = $definition->getObjectRefIds();
95  $files = array();
96 
97  foreach ($object_ref_ids as $object_ref_id) {
98  $object = ilObjectFactory::getInstanceByRefId($object_ref_id);
99  $object_type = $object->getType();
100  $object_name = $object->getTitle();
101  $object_temp_dir = ""; // empty as content will be added in recurseFolder and getFileDirs
102 
103  if ($object_type === "fold" || $object_type === "crs") {
104  $num_recursions = 0;
105  $files_from_folder = $this->recurseFolder($object_ref_id, $object_name, $object_temp_dir, $num_recursions, $initiated_by_folder_action);
106  $files = array_merge($files, $files_from_folder);
107  } elseif (($object_type === "file") && (($file_dirs = $this->getFileDirs(
108  $object_ref_id,
109  $object_name,
110  $object_temp_dir
111  )) !== false)) {
112  $files[] = $file_dirs;
113  }
114  }
115  $this->logger->debug('Collected files:');
116  $this->logger->dump($files);
117 
118  $num_files = 0;
119  foreach ($files as $file) {
120  $definition->addCopyDefinition($file['source_dir'], $file['target_dir']);
121  $this->logger->debug('Added new copy definition: ' . $file['source_dir'] . ' -> ' . $file['target_dir']);
122 
123  // count files only (without empty directories)
124  $is_empty_folder = preg_match_all("/\/$/", $file['target_dir']);
125  if (!$is_empty_folder) {
126  $num_files++;
127  }
128  }
129  $definition->setObjectRefIds($object_ref_ids);
130  $definition->setNumFiles($num_files);
131 
132  return $definition;
133  }
134 
135 
142  private function getFileDirs($a_ref_id, $a_file_name, $a_temp_dir)
143  {
144  global $DIC;
145 
146  $user = $DIC->user();
147  $ilAccess = $DIC->access();
148  if ($ilAccess->checkAccessOfUser($user->getId(), "read", "", $a_ref_id)) {
149  $file = new ilObjFile($a_ref_id);
150  $source_dir = $file->getFile();
151 
152  if (@!is_file($source_dir)) {
153  return false;
154  }
155 
156  $filname_with_suffix = $this->ensureSuffix($a_file_name, $file->getFileExtension());
157 
158  $target_dir = $a_temp_dir . '/' . $filname_with_suffix;
159 
160  // #25025: allow duplicate filenames by appending an incrementing
161  // number per duplicate in brackets to the name.
162  // Example: test.txt, test (1).txt, test (2).txt, ...
163  if (isset(self::$targets[$target_dir])) {
164  $target_info = pathinfo($target_dir);
165  $filename = $target_info["filename"];
166  $extension = isset($target_info["extension"]) ? "." . $target_info["extension"] : "";
167  $target_dir = $a_temp_dir . $filename . " (" . ++self::$targets[$target_dir] . ")" . $extension;
168  } else {
169  self::$targets[$target_dir] = 0;
170  }
171 
172  return [
173  "source_dir" => $source_dir,
174  "target_dir" => $target_dir,
175  ];
176  }
177 
178  return false;
179  }
180 
181 
189  private function recurseFolder($a_ref_id, $a_folder_name, $a_temp_dir, $a_num_recursions, $a_initiated_by_folder_action): array
190  {
191  global $DIC;
192 
193  $num_recursions = $a_num_recursions + 1;
194  $tree = $DIC->repositoryTree();
195  $ilAccess = $DIC->access();
196  $files = array();
197 
198  // Avoid the duplication of the uppermost folder when the download is initiated via a folder's action drop-down
199  // by not including said folders name in the temp_dir path.
200  if ($num_recursions <= 1 && $a_initiated_by_folder_action) {
201  $temp_dir = $a_temp_dir;
202  } else {
203  $temp_dir = $a_temp_dir . '/' . ilFileUtils::getASCIIFilename($a_folder_name);
204  }
205 
206  $subtree = $tree->getChildsByTypeFilter($a_ref_id, array("fold", "file"));
207 
208  foreach ($subtree as $child) {
209  if (!$ilAccess->checkAccess("read", "", $child["ref_id"])) {
210  continue;
211  }
212  if (ilObject::_isInTrash($child["ref_id"])) {
213  continue;
214  }
215  if ($child["type"] == "fold") {
216  $files_from_folder = $this->recurseFolder($child["ref_id"], $child['title'], $temp_dir, $num_recursions, $a_initiated_by_folder_action);
217  $files = array_merge($files, $files_from_folder);
218  } else {
219  if (($child["type"] === "file") && (($dirs = $this->getFileDirs($child["ref_id"], $child['title'], $temp_dir)) !== false)) {
220  $files[] = $dirs;
221  }
222  }
223  }
224  // ensure that empty folders are also contained in the downloaded zip
225  if (empty($subtree)) {
226  $files[] = [
227  "source_dir" => "",
228  "target_dir" => $temp_dir . '/',
229  ];
230  }
231 
232  return $files;
233  }
234 
235 
240  {
241  return 30;
242  }
243 }
Description of class class.
Interface Observer Contains several chained tasks and infos about them.
getFileDirs($a_ref_id, $a_file_name, $a_temp_dir)
run(array $input, \ILIAS\BackgroundTasks\Observer $observer)
static getASCIIFilename(string $a_filename)
recurseFolder($a_ref_id, $a_folder_name, $a_temp_dir, $a_num_recursions, $a_initiated_by_folder_action)
static _isInTrash(int $ref_id)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
Class ilObjFile.
global $DIC
Definition: shib_login.php:25
$filename
Definition: buildRTE.php:78
trait ilObjFileSecureString
Trait ilObjFileSecureString.
getExpectedTimeOfTaskInSeconds()
int the amount of seconds this task usually taskes. If your task-duration scales with the the amount ...
ensureSuffix(string $title, ?string $suffix=null)