Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
package.php
1<?php
2
4
11
13{
14 /* @var string $index Package ID. */
15 protected $index;
16 /* @var Log $cidLog */
17 protected $cidLog = null;
18 /* @var Log $log */
19 protected $log = null;
21 protected $path;
23 protected $CID;
24 /* @var array */
25 protected $copies = array(
26 "default" => array(
27 "width" => null,
28 "height" => null
29 )
30 );
31 /* @var Storable */
32 protected $storage;
34 public $files = array();
36 public $controlId = "fileUploader";
37 /*
38 * @var string $script Url to uploading page for forming url to view
39 * @var array $processTime Time limits
40 */
41 protected $processTime = array( // Time limits
42 "max" => 30,
43 "start" => 0,
44 "current" => 0);
45
54 public function __construct($path, $CID, $index)
55 {
56 if (!is_string($path))
57 throw new ArgumentNullException("path");
58 $this->path = $path;
59 $this->setCid($CID);
60 $this->cidLog = new Log($this->path.$this->getCid().".log");
61 $this->setIndex($index);
62
63 $this->request = Context::getCurrent()->getRequest();
64 if (!$this->request->isPost())
65 throw new NotImplementedException("File uploader support only POST method.");
66
67 $post = Context::getCurrent()->getRequest()->getPostList()->toArray();
68 $post = $post[Uploader::INFO_NAME];
69 if (!preg_match("/^([0-9]+)$/", $post["filesCount"]))
70 {
71 throw new ArgumentException("The value filesCount must be an integer", "packageIndex");
72 }
73 $this->log = new Log($this->path.$this->getIndex().".package");
74 if (!isset($this->log["CID"]))
75 {
76 $this->log["CID"] = $this->getCid();
77 $this->log["pIndex"] = $this->getIndex();
78 $this->log["filesCount"] = intval($post["filesCount"]);
79 $this->log["files"] = array();
80 }
81
82 $this->processTime["max"] = intval(ini_get("max_execution_time")) * 0.75;
83 $this->processTime["start"] = time();
84
85 set_time_limit(0);
86
87 return $this;
88 }
89
90 protected function setIndex($index)
91 {
92 if (!is_string($index))
93 throw new ArgumentNullException("packageIndex");
94 if (!preg_match("/^pIndex([0-9]+)$/", $index))
95 throw new ArgumentException("Index must be a string like '^pIndex([0-9]+)$'", "packageIndex");
96
97 $this->index = $index;
98 }
103 public function getIndex()
104 {
105 return $this->index;
106 }
111 public function getCidLog($key = null)
112 {
113 if (is_null($key))
114 return $this->cidLog->getLog();
115 $log = $this->cidLog->getLog();
116 return $log[$key];
117 }
122 public function getLog($key = null)
123 {
124 if (is_null($key))
125 return $this->log->getLog();
126 $log = $this->log->getLog();
127 return $log[$key];
128 }
129
134 public function getFile($id)
135 {
136 return $this->files[$id];
137 }
138
139 protected function setCid($CID)
140 {
141 if (!is_string($CID))
142 throw new ArgumentNullException("CID");
143 else if (strpos($CID, "/") !== false)
144 throw new ArgumentException("CID contains a forbidden symbol /");
145 $this->CID = preg_replace("/[^a-z0-9_\\-.]/i", "_", $CID);
146 }
150 public function getCid()
151 {
152 return $this->CID;
153 }
154
158 public function getPath()
159 {
160 return $this->path;
161 }
162
168 public function setStorage(array $params)
169 {
170 $params = array_change_key_case($params, CASE_LOWER);
171 try
172 {
173 if (array_key_exists("cloud", $params) && $params["cloud"] === true &&
174 (\CUtil::Unformat(ini_get("upload_max_filesize")) / 1024 / 1024) >= 5)
175 $this->storage = new CloudStorage($params);
176 }
177 catch(\Exception $e)
178 {
179 }
180 if (!($this->storage instanceof Storable))
181 {
182 $this->storage = new Storage($params);
183 }
184 return $this;
185 }
189 public function getStorage()
190 {
191 return $this->storage;
192 }
193
198 public function setCopies(array $params)
199 {
200 foreach ($params as $code => $p)
201 {
202 $this->copies[$code] = $p;
203 }
204 return $this;
205 }
209 public function getCopies()
210 {
211 return $this->copies;
212 }
218 protected static function unescape($data)
219 {
220 if(is_array($data))
221 {
222 $res = array();
223 foreach($data as $k => $v)
224 {
225 $k = Uri::urnDecode($k, "UTF-8");
226 $res[$k] = self::unescape($v);
227 }
228 }
229 else
230 {
231 $res = Uri::urnDecode($data, "UTF-8");
232 }
233
234 return $res;
235 }
242 public function checkPost($fileLimits)
243 {
244 $unescapedPost = self::unescape(
245 Context::getCurrent()->getRequest()->getPostList()->toArrayRaw()
246 ?? Context::getCurrent()->getRequest()->getPostList()->toArray()
247 );
248 $postFiles = $unescapedPost[Uploader::FILE_NAME];
249 $post = $unescapedPost[Uploader::INFO_NAME];
250 if (!(is_array($post) &&
251 $this->log["filesCount"] > 0 &&
252 $post["filesCount"] == $this->log["filesCount"] &&
253 is_array($postFiles) &&
254 !empty($postFiles))
255 )
256 return array();
257
259 Context::getCurrent()->getRequest()->getFileList()->toArrayRaw()
260 ?? Context::getCurrent()->getRequest()->getFileList()->toArray()
261 );
263
264 $type = $post["type"] ?? null;
265 if ($type !== "brief") // If it is IE8
266 {
267 $error = "";
268 if ($this->log["executeStatus"] != "executed")
269 {
270 $eventName = ($this->cidLog["executeStatus"] === "executed" ? "onUploadIsContinued" : "onUploadIsStarted");
271 $this->cidLog["executeStatus"] = "executed";
272
273 foreach(GetModuleEvents(Uploader::EVENT_NAME, $eventName, true) as $event)
274 {
275 if (ExecuteModuleEventEx($event, array(&$this->log, &$this->cidLog, &$unescapedPost, &$files, &$error)) === false)
276 throw new NotImplementedException($error);
277 }
278 $eventName = "onPackageIsStarted";
279 }
280 else
281 {
282 $eventName = "onPackageIsContinued";
283 }
284
285 $this->log["executeStatus"] = "executed";
286 foreach(GetModuleEvents(Uploader::EVENT_NAME, $eventName, true) as $event)
287 {
288 if (ExecuteModuleEventEx($event, array(&$this->log, &$this->cidLog, &$unescapedPost, &$files, &$error)) === false)
289 throw new NotImplementedException($error);
290 }
291 }
292
293 $filesRaw = array();
294 // $_POST
295 foreach($postFiles as $fileID => $file)
296 {
297 if (is_array($file))
298 {
299 if (isset($file["removed"]))
300 {
301 $f = array_merge($file, array("id" => $fileID));
302 File::deleteCache($this, $f);
303 $filesRaw[] = [
304 'id' => $fileID,
305 'removed' => 'Y'
306 ];
307 }
308 else if (isset($file["restored"]))
309 {
310 $f = array_merge($file, array("id" => $fileID));
311 if ($f["restored"] === "Y")
312 {
313 File::deleteCache($this, $f);
314 }
315 else
316 {
317 $filesRaw[] = $f;
318 }
319 }
320 if (array_key_exists("files", $file) && is_array($file["files"]))
321 {
322 foreach ($file["files"] as $serviceName => $f)
323 {
324 if (is_array($f) && array_key_exists("tmp_url", $f))
325 {
334 $filesRaw[] = array_merge($f, array(
335 "id" => $fileID,
336 "code" => $serviceName
337 ));
338 }
339 }
340 }
341 }
342 }
343 // $_FILES
344 if (is_array($files))
345 {
346 foreach($files["name"] as $fileID => $fileNames)
347 {
348 if (is_array($fileNames))
349 {
350 foreach ($fileNames as $fileName => $val)
351 {
352 $filesRaw[] = array(
353 "id" => $fileID,
354 "code" => $fileName,
355 "tmp_name" => $files["tmp_name"][$fileID][$fileName],
356 "type" => $files["type"][$fileID][$fileName],
357 "size" => $files["size"][$fileID][$fileName],
358 "error" => $files["error"][$fileID][$fileName]
359 );
360 }
361 }
362 else
363 {
364 $filesRaw[] = array(
365 "id" => $fileID,
366 "code" => $fileNames,
367 "tmp_name" => $files["tmp_name"][$fileID],
368 "type" => $files["type"][$fileID],
369 "size" => $files["size"][$fileID],
370 "error" => $files["error"][$fileID]
371 );
372 }
373 }
374 }
375
376 $file = null;
377 $filesFromLog = is_array($this->log["files"]) ? $this->log["files"] : array();
378 $filesOnThisPack = array();
379 if ($fileRaw = reset($filesRaw))
380 {
381 $this->log["uploadStatus"] = "inprogress";
382 do
383 {
384 if (!array_key_exists($fileRaw["id"], $postFiles))
385 continue;
386 if (!$this->checkTime())
387 break;
388 if (!array_key_exists($fileRaw["id"], $filesOnThisPack))
389 {
390 if (!empty($fileRaw["removed"]))
391 {
392 $file = new FileRemoved($this, [
393 'id' => $fileRaw['id'],
394 'name' => $postFiles[$fileRaw["id"]]["name"]
395 ]);
396 }
397 else
398 {
399 $file = new File($this, array(
400 "id" => $fileRaw["id"],
401 "name" => $postFiles[$fileRaw["id"]]["name"],
402 "type" => $postFiles[$fileRaw["id"]]["type"],
403 "size" => $postFiles[$fileRaw["id"]]["size"]
404 ) + (is_array($postFiles[$fileRaw["id"]]) ? $postFiles[$fileRaw["id"]] : []));
405 if (isset($fileRaw["restored"]))
406 {
407 if ($file->isExecuted())
408 $file->setExecuteStatus("none");
409 $fileRaw = $file->getFile("default");
410 if (empty($fileRaw) || !is_array($fileRaw))
411 $file->addError(new Error(\Bitrix\Main\Localization\Loc::getMessage("BXU_FileIsNotRestored"), "BXU350.0"));
412 }
413 }
414 $filesOnThisPack[$fileRaw["id"]] = $file;
415 }
416 /* @var File $file */
417 $file = $filesOnThisPack[$fileRaw["id"]];
418 if ($file->hasError() || $file instanceof FileRemoved)
419 {
420 continue;
421 }
422 $result = File::checkFile($fileRaw, $file, $fileLimits + array("path" => $this->getPath()));
423 if ($result->isSuccess() && ($result = $file->saveFile($fileRaw, $this->getStorage(), $this->getCopies())) && $result->isSuccess() &&
424 $type !== "brief" &&
425 $file->isUploaded() &&
426 !$file->isExecuted()
427 )
428 {
429 $file->setExecuteStatus("executed");
430 $fileArray = $file->toArray();
431 foreach(GetModuleEvents(Uploader::EVENT_NAME, "onFileIsUploaded", true) as $event)
432 {
433 $error = "";
434 if (!ExecuteModuleEventEx($event, array($file->getHash(), &$fileArray,
435 &$this->log,
436 &$this->cidLog,
437 &$error)))
438 {
439 $result->addError(new Error($error, "BXU350.1"));
440 break;
441 }
442 }
443 $file->fromArray($fileArray);
444 }
445 if (!$result->isSuccess())
446 $file->addError($result->getErrorCollection()->current());
447 } while ($fileRaw = next($filesRaw));
448 }
449
450 $response = array();
451 /* @var File $file */
452 foreach ($filesOnThisPack as $file)
453 {
454 $response[$file->getId()] = $file->toArray();
455 $filesFromLog[$file->getId()] = $response[$file->getId()]["status"] = $file->isUploaded() ? "uploaded" : "inprogress";
456 if ($file->hasError())
457 {
458 $response[$file->getId()]["status"] = "error";
459 $response[$file->getId()]["error"] = $file->getErrorMessage();
460 $filesFromLog[$file->getId()] = "error";
461 }
462 }
463 $this->files = $filesOnThisPack;
464 $this->log["files"] = $filesFromLog;
465 $declaredFiles = (int) $this->log["filesCount"];
466
467 $cnt = 0;
468 foreach ($filesFromLog as $status)
469 $cnt += ($status == "uploaded" || $status == "error" ? 1 : 0);
470
471 if ($declaredFiles > 0 && $declaredFiles <= $cnt)
472 {
473 if ($type !== "brief") // If it is IE8
474 {
475 $this->log["uploadStatus"] = "uploaded";
476 $error = "";
477 foreach(GetModuleEvents(Uploader::EVENT_NAME, "onPackageIsFinished", true) as $event)
478 {
479 if (ExecuteModuleEventEx($event, array(&$this->log, &$this->cidLog, &$unescapedPost, &$response, &$error)) === false)
480 throw new NotImplementedException($error);
481 }
482 }
483 }
484 return $response;
485 }
486
490 public function checkTime()
491 {
492 if ($this->processTime["max"] > 0)
493 {
494 $res = (microtime(true) - START_EXEC_TIME);
495 return $res < $this->processTime["max"];
496 }
497 return true;
498 }
499
508 public static function merge($res, $res2)
509 {
510 $res = is_array($res) ? $res : array();
511 $res2 = is_array($res2) ? $res2 : array();
512 foreach ($res2 as $key => $val)
513 {
514 if (array_key_exists($key, $res) && is_array($val))
515 $res[$key] = self::merge($res[$key], $val);
516 else
517 $res[$key] = $val;
518 }
519 return $res;
520 }
521}
522
523?>
static getCurrent()
Definition context.php:241
static getMessage($code, $replace=null, $language=null)
Definition loc.php:29
static deleteCache(Package $package, array $file)
Definition file.php:334
static checkFile(&$file, File $f, $params)
Definition file.php:592
static merge($res, $res2)
Definition package.php:508
__construct($path, $CID, $index)
Definition package.php:54