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