1 | <?php |
||||
2 | |||||
3 | /* |
||||
4 | * @copyright 2014 Mautic Contributors. All rights reserved |
||||
5 | * @author Mautic |
||||
6 | * |
||||
7 | * @link http://mautic.org |
||||
8 | * |
||||
9 | * @license GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html |
||||
10 | */ |
||||
11 | |||||
12 | namespace Mautic\AssetBundle\Entity; |
||||
13 | |||||
14 | use Doctrine\ORM\Mapping as ORM; |
||||
15 | use Mautic\ApiBundle\Serializer\Driver\ApiMetadataDriver; |
||||
16 | use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder; |
||||
17 | use Mautic\CoreBundle\Entity\FormEntity; |
||||
18 | use Mautic\CoreBundle\Helper\FileHelper; |
||||
19 | use Symfony\Component\Filesystem\Filesystem; |
||||
20 | use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; |
||||
21 | use Symfony\Component\HttpFoundation\File\File; |
||||
22 | use Symfony\Component\HttpFoundation\File\UploadedFile; |
||||
23 | use Symfony\Component\Validator\Constraints as Assert; |
||||
24 | use Symfony\Component\Validator\Context\ExecutionContextInterface; |
||||
25 | use Symfony\Component\Validator\Mapping\ClassMetadata; |
||||
26 | |||||
27 | class Asset extends FormEntity |
||||
28 | { |
||||
29 | /** |
||||
30 | * @var int |
||||
31 | */ |
||||
32 | private $id; |
||||
33 | |||||
34 | /** |
||||
35 | * @var string |
||||
36 | */ |
||||
37 | private $title; |
||||
38 | |||||
39 | /** |
||||
40 | * @var string |
||||
41 | */ |
||||
42 | private $description; |
||||
43 | |||||
44 | /** |
||||
45 | * @var string |
||||
46 | */ |
||||
47 | private $storageLocation = 'local'; |
||||
48 | |||||
49 | /** |
||||
50 | * @var string |
||||
51 | */ |
||||
52 | private $path; |
||||
53 | |||||
54 | /** |
||||
55 | * @var string |
||||
56 | */ |
||||
57 | private $remotePath; |
||||
58 | |||||
59 | /** |
||||
60 | * @var string |
||||
61 | */ |
||||
62 | private $originalFileName; |
||||
63 | |||||
64 | /** |
||||
65 | * @var File |
||||
66 | */ |
||||
67 | private $file; |
||||
68 | |||||
69 | /** |
||||
70 | * Holds upload directory. |
||||
71 | */ |
||||
72 | private $uploadDir; |
||||
73 | |||||
74 | /** |
||||
75 | * Holds max size of uploaded file. |
||||
76 | */ |
||||
77 | private $maxSize; |
||||
78 | |||||
79 | /** |
||||
80 | * Temporary location when asset file is beeing updated. |
||||
81 | * We need to keep the old file till we are sure the new |
||||
82 | * one is stored correctly. |
||||
83 | */ |
||||
84 | private $temp; |
||||
85 | |||||
86 | /** |
||||
87 | * Temporary ID used for file upload and validations |
||||
88 | * before the actual ID is known. |
||||
89 | */ |
||||
90 | private $tempId; |
||||
91 | |||||
92 | /** |
||||
93 | * Temporary file name used for file upload and validations |
||||
94 | * before the actual ID is known. |
||||
95 | */ |
||||
96 | private $tempName; |
||||
97 | |||||
98 | /** |
||||
99 | * @var string |
||||
100 | */ |
||||
101 | private $alias; |
||||
102 | |||||
103 | /** |
||||
104 | * @var string |
||||
105 | */ |
||||
106 | private $language = 'en'; |
||||
107 | |||||
108 | /** |
||||
109 | * @var \DateTime|null |
||||
110 | */ |
||||
111 | private $publishUp; |
||||
112 | |||||
113 | /** |
||||
114 | * @var \DateTime|null |
||||
115 | */ |
||||
116 | private $publishDown; |
||||
117 | |||||
118 | /** |
||||
119 | * @var int |
||||
120 | */ |
||||
121 | private $downloadCount = 0; |
||||
122 | |||||
123 | /** |
||||
124 | * @var int |
||||
125 | */ |
||||
126 | private $uniqueDownloadCount = 0; |
||||
127 | |||||
128 | /** |
||||
129 | * @var int |
||||
130 | */ |
||||
131 | private $revision = 1; |
||||
132 | |||||
133 | /** |
||||
134 | * @var \Mautic\CategoryBundle\Entity\Category |
||||
135 | **/ |
||||
136 | private $category; |
||||
137 | |||||
138 | /** |
||||
139 | * @var string |
||||
140 | */ |
||||
141 | private $extension; |
||||
142 | |||||
143 | /** |
||||
144 | * @var string |
||||
145 | */ |
||||
146 | private $mime; |
||||
147 | |||||
148 | /** |
||||
149 | * @var int |
||||
150 | */ |
||||
151 | private $size; |
||||
152 | |||||
153 | /** |
||||
154 | * @var string|null |
||||
155 | */ |
||||
156 | private $downloadUrl; |
||||
157 | |||||
158 | /** |
||||
159 | * @var bool |
||||
160 | */ |
||||
161 | private $disallow = false; |
||||
162 | |||||
163 | public static function loadMetadata(ORM\ClassMetadata $metadata) |
||||
164 | { |
||||
165 | $builder = new ClassMetadataBuilder($metadata); |
||||
166 | |||||
167 | $builder->setTable('assets') |
||||
168 | ->setCustomRepositoryClass('Mautic\AssetBundle\Entity\AssetRepository') |
||||
169 | ->addIndex(['alias'], 'asset_alias_search'); |
||||
170 | |||||
171 | $builder->addIdColumns('title'); |
||||
172 | |||||
173 | $builder->addField('alias', 'string'); |
||||
174 | |||||
175 | $builder->createField('storageLocation', 'string') |
||||
176 | ->columnName('storage_location') |
||||
177 | ->nullable() |
||||
178 | ->build(); |
||||
179 | |||||
180 | $builder->createField('path', 'string') |
||||
181 | ->nullable() |
||||
182 | ->build(); |
||||
183 | |||||
184 | $builder->createField('remotePath', 'string') |
||||
185 | ->columnName('remote_path') |
||||
186 | ->nullable() |
||||
187 | ->build(); |
||||
188 | |||||
189 | $builder->createField('originalFileName', 'string') |
||||
190 | ->columnName('original_file_name') |
||||
191 | ->nullable() |
||||
192 | ->build(); |
||||
193 | |||||
194 | $builder->createField('language', 'string') |
||||
195 | ->columnName('lang') |
||||
196 | ->build(); |
||||
197 | |||||
198 | $builder->addPublishDates(); |
||||
199 | |||||
200 | $builder->createField('downloadCount', 'integer') |
||||
201 | ->columnName('download_count') |
||||
202 | ->build(); |
||||
203 | |||||
204 | $builder->createField('uniqueDownloadCount', 'integer') |
||||
205 | ->columnName('unique_download_count') |
||||
206 | ->build(); |
||||
207 | |||||
208 | $builder->addField('revision', 'integer'); |
||||
209 | |||||
210 | $builder->addCategory(); |
||||
211 | |||||
212 | $builder->createField('extension', 'string') |
||||
213 | ->nullable() |
||||
214 | ->build(); |
||||
215 | |||||
216 | $builder->createField('mime', 'string') |
||||
217 | ->nullable() |
||||
218 | ->build(); |
||||
219 | |||||
220 | $builder->createField('size', 'integer') |
||||
221 | ->nullable() |
||||
222 | ->build(); |
||||
223 | |||||
224 | $builder->createField('disallow', 'boolean') |
||||
225 | ->nullable() |
||||
226 | ->build(); |
||||
227 | } |
||||
228 | |||||
229 | /** |
||||
230 | * Prepares the metadata for API usage. |
||||
231 | * |
||||
232 | * @param $metadata |
||||
233 | */ |
||||
234 | public static function loadApiMetadata(ApiMetadataDriver $metadata) |
||||
235 | { |
||||
236 | $metadata->setGroupPrefix('asset') |
||||
237 | ->addListProperties( |
||||
238 | [ |
||||
239 | 'id', |
||||
240 | 'title', |
||||
241 | 'alias', |
||||
242 | 'category', |
||||
243 | 'description', |
||||
244 | ] |
||||
245 | ) |
||||
246 | ->addProperties( |
||||
247 | [ |
||||
248 | 'language', |
||||
249 | 'publishUp', |
||||
250 | 'publishDown', |
||||
251 | 'downloadCount', |
||||
252 | 'uniqueDownloadCount', |
||||
253 | 'revision', |
||||
254 | 'extension', |
||||
255 | 'mime', |
||||
256 | 'size', |
||||
257 | 'downloadUrl', |
||||
258 | 'storageLocation', |
||||
259 | 'disallow', |
||||
260 | ] |
||||
261 | ) |
||||
262 | ->build(); |
||||
263 | } |
||||
264 | |||||
265 | /** |
||||
266 | * Clone magic function. |
||||
267 | */ |
||||
268 | public function __clone() |
||||
269 | { |
||||
270 | $this->id = null; |
||||
271 | |||||
272 | parent::__clone(); |
||||
273 | } |
||||
274 | |||||
275 | /** |
||||
276 | * Get id. |
||||
277 | * |
||||
278 | * @return int |
||||
279 | */ |
||||
280 | public function getId() |
||||
281 | { |
||||
282 | return $this->id; |
||||
283 | } |
||||
284 | |||||
285 | /** |
||||
286 | * Sets file. |
||||
287 | * |
||||
288 | * @param File $file |
||||
289 | */ |
||||
290 | public function setFile(File $file = null) |
||||
291 | { |
||||
292 | $this->file = $file; |
||||
293 | |||||
294 | // check if we have an old asset path |
||||
295 | if (isset($this->path)) { |
||||
296 | // store the old name to delete after the update |
||||
297 | $this->temp = $this->path; |
||||
298 | $this->path = null; |
||||
299 | } |
||||
300 | } |
||||
301 | |||||
302 | /** |
||||
303 | * Get file. |
||||
304 | * |
||||
305 | * @return UploadedFile |
||||
306 | */ |
||||
307 | public function getFile() |
||||
308 | { |
||||
309 | // if file is not set, try to find it at temp folder |
||||
310 | if ($this->isLocal() && empty($this->file)) { |
||||
311 | $tempFile = $this->loadFile(true); |
||||
312 | |||||
313 | if ($tempFile) { |
||||
314 | $this->setFile($tempFile); |
||||
315 | } |
||||
316 | } |
||||
317 | |||||
318 | return $this->file; |
||||
319 | } |
||||
320 | |||||
321 | /** |
||||
322 | * Set title. |
||||
323 | * |
||||
324 | * @param string $title |
||||
325 | * |
||||
326 | * @return Asset |
||||
327 | */ |
||||
328 | public function setTitle($title) |
||||
329 | { |
||||
330 | $this->isChanged('title', $title); |
||||
331 | $this->title = $title; |
||||
332 | |||||
333 | return $this; |
||||
334 | } |
||||
335 | |||||
336 | /** |
||||
337 | * Get title. |
||||
338 | * |
||||
339 | * @return string |
||||
340 | */ |
||||
341 | public function getTitle() |
||||
342 | { |
||||
343 | return $this->title; |
||||
344 | } |
||||
345 | |||||
346 | /** |
||||
347 | * @return mixed |
||||
348 | */ |
||||
349 | public function getExtension() |
||||
350 | { |
||||
351 | return $this->extension; |
||||
352 | } |
||||
353 | |||||
354 | /** |
||||
355 | * @param mixed $extension |
||||
356 | */ |
||||
357 | public function setExtension($extension) |
||||
358 | { |
||||
359 | $this->extension = $extension; |
||||
360 | } |
||||
361 | |||||
362 | /** |
||||
363 | * @return mixed |
||||
364 | */ |
||||
365 | public function getMime() |
||||
366 | { |
||||
367 | return $this->mime; |
||||
368 | } |
||||
369 | |||||
370 | /** |
||||
371 | * @param mixed $mime |
||||
372 | */ |
||||
373 | public function setMime($mime) |
||||
374 | { |
||||
375 | $this->mime = $mime; |
||||
376 | } |
||||
377 | |||||
378 | /** |
||||
379 | * Set originalFileName. |
||||
380 | * |
||||
381 | * @param string $originalFileName |
||||
382 | * |
||||
383 | * @return Asset |
||||
384 | */ |
||||
385 | public function setOriginalFileName($originalFileName) |
||||
386 | { |
||||
387 | $this->isChanged('originalFileName', $originalFileName); |
||||
388 | $this->originalFileName = $originalFileName; |
||||
389 | |||||
390 | return $this; |
||||
391 | } |
||||
392 | |||||
393 | /** |
||||
394 | * Get originalFileName. |
||||
395 | * |
||||
396 | * @return string |
||||
397 | */ |
||||
398 | public function getOriginalFileName() |
||||
399 | { |
||||
400 | return $this->originalFileName; |
||||
401 | } |
||||
402 | |||||
403 | /** |
||||
404 | * Set storage location. |
||||
405 | * |
||||
406 | * @param string $storageLocation |
||||
407 | * |
||||
408 | * @return Asset |
||||
409 | */ |
||||
410 | public function setStorageLocation($storageLocation) |
||||
411 | { |
||||
412 | $this->isChanged('storageLocation', $storageLocation); |
||||
413 | $this->storageLocation = $storageLocation; |
||||
414 | |||||
415 | return $this; |
||||
416 | } |
||||
417 | |||||
418 | /** |
||||
419 | * Get storage location. |
||||
420 | * |
||||
421 | * @return string |
||||
422 | */ |
||||
423 | public function getStorageLocation() |
||||
424 | { |
||||
425 | if (null === $this->storageLocation) { |
||||
426 | $this->storageLocation = 'local'; |
||||
427 | } |
||||
428 | |||||
429 | return $this->storageLocation; |
||||
430 | } |
||||
431 | |||||
432 | /** |
||||
433 | * Set path. |
||||
434 | * |
||||
435 | * @param string $path |
||||
436 | * |
||||
437 | * @return Asset |
||||
438 | */ |
||||
439 | public function setPath($path) |
||||
440 | { |
||||
441 | $this->isChanged('path', $path); |
||||
442 | $this->path = $path; |
||||
443 | |||||
444 | return $this; |
||||
445 | } |
||||
446 | |||||
447 | /** |
||||
448 | * Get path. |
||||
449 | * |
||||
450 | * @return string |
||||
451 | */ |
||||
452 | public function getPath() |
||||
453 | { |
||||
454 | return $this->path; |
||||
455 | } |
||||
456 | |||||
457 | /** |
||||
458 | * Set remote path. |
||||
459 | * |
||||
460 | * @param string $remotePath |
||||
461 | * |
||||
462 | * @return Asset |
||||
463 | */ |
||||
464 | public function setRemotePath($remotePath) |
||||
465 | { |
||||
466 | $this->isChanged('remotePath', $remotePath); |
||||
467 | $this->remotePath = $remotePath; |
||||
468 | |||||
469 | return $this; |
||||
470 | } |
||||
471 | |||||
472 | /** |
||||
473 | * Get remote path. |
||||
474 | * |
||||
475 | * @return string |
||||
476 | */ |
||||
477 | public function getRemotePath() |
||||
478 | { |
||||
479 | return $this->remotePath; |
||||
480 | } |
||||
481 | |||||
482 | /** |
||||
483 | * Set alias. |
||||
484 | * |
||||
485 | * @param string $alias |
||||
486 | * |
||||
487 | * @return Asset |
||||
488 | */ |
||||
489 | public function setAlias($alias) |
||||
490 | { |
||||
491 | $this->isChanged('alias', $alias); |
||||
492 | $this->alias = $alias; |
||||
493 | |||||
494 | return $this; |
||||
495 | } |
||||
496 | |||||
497 | /** |
||||
498 | * Get alias. |
||||
499 | * |
||||
500 | * @return string |
||||
501 | */ |
||||
502 | public function getAlias() |
||||
503 | { |
||||
504 | return $this->alias; |
||||
505 | } |
||||
506 | |||||
507 | /** |
||||
508 | * Set publishUp. |
||||
509 | * |
||||
510 | * @param \DateTime $publishUp |
||||
511 | * |
||||
512 | * @return Asset |
||||
513 | */ |
||||
514 | public function setPublishUp($publishUp) |
||||
515 | { |
||||
516 | $this->isChanged('publishUp', $publishUp); |
||||
517 | $this->publishUp = $publishUp; |
||||
518 | |||||
519 | return $this; |
||||
520 | } |
||||
521 | |||||
522 | /** |
||||
523 | * Get publishUp. |
||||
524 | * |
||||
525 | * @return \DateTime |
||||
526 | */ |
||||
527 | public function getPublishUp() |
||||
528 | { |
||||
529 | return $this->publishUp; |
||||
530 | } |
||||
531 | |||||
532 | /** |
||||
533 | * Set publishDown. |
||||
534 | * |
||||
535 | * @param \DateTime $publishDown |
||||
536 | * |
||||
537 | * @return Asset |
||||
538 | */ |
||||
539 | public function setPublishDown($publishDown) |
||||
540 | { |
||||
541 | $this->isChanged('publishDown', $publishDown); |
||||
542 | $this->publishDown = $publishDown; |
||||
543 | |||||
544 | return $this; |
||||
545 | } |
||||
546 | |||||
547 | /** |
||||
548 | * Get publishDown. |
||||
549 | * |
||||
550 | * @return \DateTime |
||||
551 | */ |
||||
552 | public function getPublishDown() |
||||
553 | { |
||||
554 | return $this->publishDown; |
||||
555 | } |
||||
556 | |||||
557 | /** |
||||
558 | * Set downloadCount. |
||||
559 | * |
||||
560 | * @param int $downloadCount |
||||
561 | * |
||||
562 | * @return Asset |
||||
563 | */ |
||||
564 | public function setDownloadCount($downloadCount) |
||||
565 | { |
||||
566 | $this->downloadCount = $downloadCount; |
||||
567 | |||||
568 | return $this; |
||||
569 | } |
||||
570 | |||||
571 | /** |
||||
572 | * Get downloadCount. |
||||
573 | * |
||||
574 | * @return int |
||||
575 | */ |
||||
576 | public function getDownloadCount() |
||||
577 | { |
||||
578 | return $this->downloadCount; |
||||
579 | } |
||||
580 | |||||
581 | /** |
||||
582 | * Set revision. |
||||
583 | * |
||||
584 | * @param int $revision |
||||
585 | * |
||||
586 | * @return Asset |
||||
587 | */ |
||||
588 | public function setRevision($revision) |
||||
589 | { |
||||
590 | $this->revision = $revision; |
||||
591 | |||||
592 | return $this; |
||||
593 | } |
||||
594 | |||||
595 | /** |
||||
596 | * Get revision. |
||||
597 | * |
||||
598 | * @return int |
||||
599 | */ |
||||
600 | public function getRevision() |
||||
601 | { |
||||
602 | return $this->revision; |
||||
603 | } |
||||
604 | |||||
605 | /** |
||||
606 | * Set language. |
||||
607 | * |
||||
608 | * @param string $language |
||||
609 | * |
||||
610 | * @return Asset |
||||
611 | */ |
||||
612 | public function setLanguage($language) |
||||
613 | { |
||||
614 | $this->isChanged('language', $language); |
||||
615 | $this->language = $language; |
||||
616 | |||||
617 | return $this; |
||||
618 | } |
||||
619 | |||||
620 | /** |
||||
621 | * Get language. |
||||
622 | * |
||||
623 | * @return string |
||||
624 | */ |
||||
625 | public function getLanguage() |
||||
626 | { |
||||
627 | return $this->language; |
||||
628 | } |
||||
629 | |||||
630 | /** |
||||
631 | * Set category. |
||||
632 | * |
||||
633 | * @param \Mautic\CategoryBundle\Entity\Category $category |
||||
634 | * |
||||
635 | * @return Asset |
||||
636 | */ |
||||
637 | public function setCategory(\Mautic\CategoryBundle\Entity\Category $category = null) |
||||
638 | { |
||||
639 | $this->isChanged('category', $category); |
||||
640 | $this->category = $category; |
||||
641 | |||||
642 | return $this; |
||||
643 | } |
||||
644 | |||||
645 | /** |
||||
646 | * Get category. |
||||
647 | * |
||||
648 | * @return \Mautic\CategoryBundle\Entity\Category |
||||
649 | */ |
||||
650 | public function getCategory() |
||||
651 | { |
||||
652 | return $this->category; |
||||
653 | } |
||||
654 | |||||
655 | /** |
||||
656 | * Set uniqueDownloadCount. |
||||
657 | * |
||||
658 | * @param int $uniqueDownloadCount |
||||
659 | * |
||||
660 | * @return Asset |
||||
661 | */ |
||||
662 | public function setUniqueDownloadCount($uniqueDownloadCount) |
||||
663 | { |
||||
664 | $this->uniqueDownloadCount = $uniqueDownloadCount; |
||||
665 | |||||
666 | return $this; |
||||
667 | } |
||||
668 | |||||
669 | /** |
||||
670 | * Get uniqueDownloadCount. |
||||
671 | * |
||||
672 | * @return int |
||||
673 | */ |
||||
674 | public function getUniqueDownloadCount() |
||||
675 | { |
||||
676 | return $this->uniqueDownloadCount; |
||||
677 | } |
||||
678 | |||||
679 | public function setFileNameFromRemote() |
||||
680 | { |
||||
681 | $fileName = basename($this->getRemotePath()); |
||||
682 | |||||
683 | $this->setOriginalFileName($fileName); |
||||
684 | |||||
685 | // set the asset title as original file name if title is missing |
||||
686 | if (null === $this->getTitle()) { |
||||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||
687 | $this->setTitle($fileName); |
||||
688 | } |
||||
689 | } |
||||
690 | |||||
691 | public function preUpload() |
||||
692 | { |
||||
693 | if (null !== $this->getFile()) { |
||||
694 | // set the asset title as original file name if title is missing |
||||
695 | if (null === $this->getTitle()) { |
||||
696 | $this->setTitle($this->file->getClientOriginalName()); |
||||
697 | } |
||||
698 | |||||
699 | $filename = sha1(uniqid(mt_rand(), true)); |
||||
700 | $extension = $this->getFile()->guessExtension(); |
||||
701 | |||||
702 | if (empty($extension)) { |
||||
703 | //get it from the original name |
||||
704 | $extension = pathinfo($this->originalFileName, PATHINFO_EXTENSION); |
||||
705 | } |
||||
706 | $this->path = $filename.'.'.$extension; |
||||
0 ignored issues
–
show
Are you sure
$extension of type array|string can be used in concatenation ?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
707 | } elseif ($this->isRemote() && null !== $this->getRemotePath()) { |
||||
708 | $this->setFileNameFromRemote(); |
||||
709 | } |
||||
710 | } |
||||
711 | |||||
712 | public function upload() |
||||
713 | { |
||||
714 | // the file property can be empty if the field is not required |
||||
715 | if (null === $this->getFile()) { |
||||
716 | // check for the remote and set type data |
||||
717 | if ($this->isRemote()) { |
||||
718 | $this->setFileInfoFromFile(); |
||||
719 | } |
||||
720 | |||||
721 | return; |
||||
722 | } |
||||
723 | |||||
724 | // move takes the target directory and then the |
||||
725 | // target filename to move to |
||||
726 | $this->getFile()->move($this->getUploadDir(), $this->path); |
||||
727 | $filePath = $this->getUploadDir().'/'.$this->temp; |
||||
728 | |||||
729 | $this->setFileInfoFromFile(); |
||||
730 | |||||
731 | // check if we have an old asset |
||||
732 | if (isset($this->temp) && file_exists($filePath)) { |
||||
733 | // delete the old asset |
||||
734 | unlink($filePath); |
||||
735 | // clear the temp asset path |
||||
736 | $this->temp = null; |
||||
737 | } |
||||
738 | |||||
739 | // Remove temporary folder and files |
||||
740 | $fs = new Filesystem(); |
||||
741 | $fs->remove($this->getAbsoluteTempDir()); |
||||
742 | |||||
743 | // clean up the file property as you won't need it anymore |
||||
744 | $this->file = null; |
||||
745 | } |
||||
746 | |||||
747 | /** |
||||
748 | * Remove a file. |
||||
749 | */ |
||||
750 | public function setFileInfoFromFile() |
||||
751 | { |
||||
752 | // get some basic information about the file type |
||||
753 | $fileInfo = $this->getFileInfo(); |
||||
754 | |||||
755 | if (!is_array($fileInfo)) { |
||||
0 ignored issues
–
show
|
|||||
756 | return; |
||||
757 | } |
||||
758 | |||||
759 | // set the mime and extension column values |
||||
760 | $this->setExtension($fileInfo['extension']); |
||||
761 | $this->setMime($fileInfo['mime']); |
||||
762 | $this->setSize($fileInfo['size']); |
||||
763 | } |
||||
764 | |||||
765 | /** |
||||
766 | * Remove a file. |
||||
767 | * |
||||
768 | * @param bool $temp >> regular uploaded file or temporary |
||||
769 | */ |
||||
770 | public function removeUpload($temp = false) |
||||
771 | { |
||||
772 | if ($temp) { |
||||
773 | $file = $this->getAbsoluteTempPath(); |
||||
774 | } else { |
||||
775 | $file = $this->getAbsolutePath(); |
||||
776 | } |
||||
777 | |||||
778 | if ($file && file_exists($file)) { |
||||
779 | unlink($file); |
||||
780 | } |
||||
781 | } |
||||
782 | |||||
783 | /** |
||||
784 | * Returns absolute path to the file. |
||||
785 | * |
||||
786 | * @return string |
||||
787 | */ |
||||
788 | public function getAbsolutePath() |
||||
789 | { |
||||
790 | return null === $this->path |
||||
791 | ? null |
||||
792 | : $this->getUploadDir().'/'.$this->path; |
||||
793 | } |
||||
794 | |||||
795 | /** |
||||
796 | * Returns absolute path to temporary file. |
||||
797 | * |
||||
798 | * @return string |
||||
799 | */ |
||||
800 | public function getAbsoluteTempPath() |
||||
801 | { |
||||
802 | return null === $this->tempId || null === $this->tempName |
||||
803 | ? null |
||||
804 | : $this->getAbsoluteTempDir().'/'.$this->tempName; |
||||
805 | } |
||||
806 | |||||
807 | /** |
||||
808 | * Returns absolute path to temporary file. |
||||
809 | * |
||||
810 | * @return string |
||||
811 | */ |
||||
812 | public function getAbsoluteTempDir() |
||||
813 | { |
||||
814 | return null === $this->tempId |
||||
815 | ? null |
||||
816 | : $this->getUploadDir().'/tmp/'.$this->tempId; |
||||
817 | } |
||||
818 | |||||
819 | /** |
||||
820 | * Returns absolute path to upload dir. |
||||
821 | * |
||||
822 | * @return string |
||||
823 | */ |
||||
824 | protected function getUploadDir() |
||||
825 | { |
||||
826 | if ($this->uploadDir) { |
||||
827 | return $this->uploadDir; |
||||
828 | } |
||||
829 | |||||
830 | return 'media/files'; |
||||
831 | } |
||||
832 | |||||
833 | /** |
||||
834 | * Set uploadDir. |
||||
835 | * |
||||
836 | * @param string $uploadDir |
||||
837 | * |
||||
838 | * @return Asset |
||||
839 | */ |
||||
840 | public function setUploadDir($uploadDir) |
||||
841 | { |
||||
842 | $this->uploadDir = $uploadDir; |
||||
843 | |||||
844 | return $this; |
||||
845 | } |
||||
846 | |||||
847 | /** |
||||
848 | * Returns maximal uploadable size in bytes. |
||||
849 | * If not set, 6000000 is default. |
||||
850 | * |
||||
851 | * @return string |
||||
852 | */ |
||||
853 | protected function getMaxSize() |
||||
854 | { |
||||
855 | if ($this->maxSize) { |
||||
856 | return $this->maxSize; |
||||
857 | } |
||||
858 | |||||
859 | return 6000000; |
||||
860 | } |
||||
861 | |||||
862 | /** |
||||
863 | * Set max size. |
||||
864 | * |
||||
865 | * @param string $maxSize |
||||
866 | * |
||||
867 | * @return Asset |
||||
868 | */ |
||||
869 | public function setMaxSize($maxSize) |
||||
870 | { |
||||
871 | $this->maxSize = $maxSize; |
||||
872 | |||||
873 | return $this; |
||||
874 | } |
||||
875 | |||||
876 | /** |
||||
877 | * Returns file extension. |
||||
878 | * |
||||
879 | * @return string |
||||
880 | */ |
||||
881 | public function getFileType() |
||||
882 | { |
||||
883 | if (!empty($this->extension) && empty($this->changes['originalFileName'])) { |
||||
884 | return $this->extension; |
||||
885 | } |
||||
886 | |||||
887 | if ($this->isRemote()) { |
||||
888 | return pathinfo(parse_url($this->getRemotePath(), PHP_URL_PATH), PATHINFO_EXTENSION); |
||||
889 | } |
||||
890 | |||||
891 | if (null === $this->loadFile()) { |
||||
892 | return ''; |
||||
893 | } |
||||
894 | |||||
895 | return $this->loadFile()->guessExtension(); |
||||
896 | } |
||||
897 | |||||
898 | /** |
||||
899 | * Returns some file info. |
||||
900 | * |
||||
901 | * @return array |
||||
902 | */ |
||||
903 | public function getFileInfo() |
||||
904 | { |
||||
905 | $fileInfo = []; |
||||
906 | |||||
907 | if ($this->isRemote()) { |
||||
908 | $ch = curl_init($this->getRemotePath()); |
||||
909 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
910 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
||||
911 | curl_setopt($ch, CURLOPT_HEADER, 1); |
||||
912 | curl_setopt($ch, CURLOPT_NOBODY, 1); |
||||
913 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); |
||||
914 | curl_exec($ch); |
||||
915 | |||||
916 | // build an array of handy info |
||||
917 | $fileInfo['mime'] = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); |
||||
918 | $fileInfo['extension'] = $this->getFileType(); |
||||
919 | $fileInfo['size'] = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD); |
||||
920 | |||||
921 | return $fileInfo; |
||||
922 | } |
||||
923 | |||||
924 | if (null === $this->loadFile()) { |
||||
925 | return ''; |
||||
926 | } |
||||
927 | |||||
928 | // return an array of file type info |
||||
929 | $fileInfo['mime'] = $this->loadFile()->getMimeType(); |
||||
930 | $fileInfo['extension'] = $this->getFileType(); |
||||
931 | $fileInfo['size'] = $this->getSize(false, true); |
||||
932 | |||||
933 | return $fileInfo; |
||||
934 | } |
||||
935 | |||||
936 | /** |
||||
937 | * Returns file mime type. |
||||
938 | * |
||||
939 | * @return string |
||||
940 | */ |
||||
941 | public function getFileMimeType() |
||||
942 | { |
||||
943 | if ($this->isRemote()) { |
||||
944 | $ch = curl_init($this->getRemotePath()); |
||||
945 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
946 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
||||
947 | curl_setopt($ch, CURLOPT_HEADER, 1); |
||||
948 | curl_setopt($ch, CURLOPT_NOBODY, 1); |
||||
949 | curl_exec($ch); |
||||
950 | |||||
951 | return curl_getinfo($ch, CURLINFO_CONTENT_TYPE); |
||||
952 | } |
||||
953 | |||||
954 | if (null === $this->loadFile()) { |
||||
955 | return ''; |
||||
956 | } |
||||
957 | |||||
958 | return $this->loadFile()->getMimeType(); |
||||
959 | } |
||||
960 | |||||
961 | /** |
||||
962 | * Returns Font Awesome icon class based on file type. |
||||
963 | * |
||||
964 | * @return string |
||||
965 | */ |
||||
966 | public function getIconClass() |
||||
967 | { |
||||
968 | $fileType = $this->getFileType(); |
||||
969 | |||||
970 | // return missing file icon if file type is empty |
||||
971 | if (!$fileType) { |
||||
972 | return 'fa fa-ban'; |
||||
973 | } |
||||
974 | |||||
975 | $fileTypes = $this->getFileExtensions(); |
||||
976 | |||||
977 | // Search for icon name by file extension. |
||||
978 | foreach ($fileTypes as $icon => $extensions) { |
||||
979 | if (in_array($fileType, $extensions)) { |
||||
980 | return 'fa fa-file-'.$icon.'-o'; |
||||
981 | } |
||||
982 | } |
||||
983 | |||||
984 | // File extension is unknown, display general file icon. |
||||
985 | return 'fa fa-file-o'; |
||||
986 | } |
||||
987 | |||||
988 | /** |
||||
989 | * Decides if an asset is image displayable by browser. |
||||
990 | * |
||||
991 | * @return bool |
||||
992 | */ |
||||
993 | public function isImage() |
||||
994 | { |
||||
995 | $fileType = strtolower($this->getFileType()); |
||||
996 | |||||
997 | if (!$fileType) { |
||||
998 | return false; |
||||
999 | } |
||||
1000 | |||||
1001 | $imageTypes = ['jpg', 'jpeg', 'png', 'gif']; |
||||
1002 | |||||
1003 | if (in_array($fileType, $imageTypes)) { |
||||
1004 | return true; |
||||
1005 | } |
||||
1006 | |||||
1007 | return false; |
||||
1008 | } |
||||
1009 | |||||
1010 | /** |
||||
1011 | * Returns array of common extensions. |
||||
1012 | * |
||||
1013 | * @return string |
||||
1014 | */ |
||||
1015 | public function getFileExtensions() |
||||
1016 | { |
||||
1017 | return [ |
||||
0 ignored issues
–
show
|
|||||
1018 | 'excel' => [ |
||||
1019 | 'xlsx', |
||||
1020 | 'xlsm', |
||||
1021 | 'xlsb', |
||||
1022 | 'xltx', |
||||
1023 | 'xltm', |
||||
1024 | 'xls', |
||||
1025 | 'xlt', |
||||
1026 | ], |
||||
1027 | 'word' => [ |
||||
1028 | 'doc', |
||||
1029 | 'docx', |
||||
1030 | 'docm', |
||||
1031 | 'dotx', |
||||
1032 | ], |
||||
1033 | 'pdf' => [ |
||||
1034 | 'pdf', |
||||
1035 | ], |
||||
1036 | 'audio' => [ |
||||
1037 | 'mp3', |
||||
1038 | ], |
||||
1039 | 'archive' => [ |
||||
1040 | 'zip', |
||||
1041 | 'rar', |
||||
1042 | 'iso', |
||||
1043 | 'tar', |
||||
1044 | 'gz', |
||||
1045 | '7z', |
||||
1046 | ], |
||||
1047 | 'image' => [ |
||||
1048 | 'jpg', |
||||
1049 | 'jpeg', |
||||
1050 | 'png', |
||||
1051 | 'gif', |
||||
1052 | 'ico', |
||||
1053 | 'bmp', |
||||
1054 | 'psd', |
||||
1055 | ], |
||||
1056 | 'text' => [ |
||||
1057 | 'txt', |
||||
1058 | 'pub', |
||||
1059 | ], |
||||
1060 | 'code' => [ |
||||
1061 | 'php', |
||||
1062 | 'js', |
||||
1063 | 'json', |
||||
1064 | 'yaml', |
||||
1065 | 'xml', |
||||
1066 | 'html', |
||||
1067 | 'htm', |
||||
1068 | 'sql', |
||||
1069 | ], |
||||
1070 | 'powerpoint' => [ |
||||
1071 | 'ppt', |
||||
1072 | 'pptx', |
||||
1073 | 'pptm', |
||||
1074 | 'xps', |
||||
1075 | 'potm', |
||||
1076 | 'potx', |
||||
1077 | 'pot', |
||||
1078 | 'pps', |
||||
1079 | 'odp', |
||||
1080 | ], |
||||
1081 | 'video' => [ |
||||
1082 | 'wmv', |
||||
1083 | 'avi', |
||||
1084 | 'mp4', |
||||
1085 | 'mkv', |
||||
1086 | 'mpeg', |
||||
1087 | ], |
||||
1088 | ]; |
||||
1089 | } |
||||
1090 | |||||
1091 | /** |
||||
1092 | * Load the file object from it's path. |
||||
1093 | * |
||||
1094 | * @return \Symfony\Component\HttpFoundation\File\File|null |
||||
1095 | */ |
||||
1096 | public function loadFile($temp = false) |
||||
1097 | { |
||||
1098 | if ($temp) { |
||||
1099 | $path = $this->getAbsoluteTempPath(); |
||||
1100 | } else { |
||||
1101 | $path = $this->getAbsolutePath(); |
||||
1102 | } |
||||
1103 | |||||
1104 | if (!$path || !file_exists($path)) { |
||||
1105 | return null; |
||||
1106 | } |
||||
1107 | |||||
1108 | try { |
||||
1109 | $file = new File($path); |
||||
1110 | } catch (FileNotFoundException $e) { |
||||
1111 | $file = null; |
||||
1112 | } |
||||
1113 | |||||
1114 | return $file; |
||||
1115 | } |
||||
1116 | |||||
1117 | /** |
||||
1118 | * Load content of the file from it's path. |
||||
1119 | * |
||||
1120 | * @return string |
||||
1121 | */ |
||||
1122 | public function getFileContents() |
||||
1123 | { |
||||
1124 | $path = $this->getFilePath(); |
||||
1125 | |||||
1126 | return file_get_contents($path); |
||||
1127 | } |
||||
1128 | |||||
1129 | /** |
||||
1130 | * Get the path to the file; a URL if remote or full file path if local. |
||||
1131 | * |
||||
1132 | * @return string |
||||
1133 | */ |
||||
1134 | public function getFilePath() |
||||
1135 | { |
||||
1136 | return $this->isRemote() ? $this->getRemotePath() : $this->getAbsolutePath(); |
||||
1137 | } |
||||
1138 | |||||
1139 | /** |
||||
1140 | * @return mixed |
||||
1141 | */ |
||||
1142 | public function getDescription() |
||||
1143 | { |
||||
1144 | return $this->description; |
||||
1145 | } |
||||
1146 | |||||
1147 | /** |
||||
1148 | * @param mixed $description |
||||
1149 | */ |
||||
1150 | public function setDescription($description) |
||||
1151 | { |
||||
1152 | $this->description = $description; |
||||
1153 | } |
||||
1154 | |||||
1155 | public static function loadValidatorMetadata(ClassMetadata $metadata) |
||||
1156 | { |
||||
1157 | // Add a constraint to manage the file upload data |
||||
1158 | $metadata->addConstraint(new Assert\Callback([__CLASS__, 'validateFile'])); |
||||
1159 | } |
||||
1160 | |||||
1161 | /** |
||||
1162 | * Validator to ensure proper data for the file fields. |
||||
1163 | * |
||||
1164 | * @param Asset $object Entity object to validate |
||||
1165 | * @param ExecutionContextInterface $context Context object |
||||
1166 | */ |
||||
1167 | public static function validateFile($object, ExecutionContextInterface $context) |
||||
1168 | { |
||||
1169 | if ($object->isLocal()) { |
||||
1170 | $tempName = $object->getTempName(); |
||||
1171 | $path = $object->getPath(); |
||||
1172 | |||||
1173 | // If the object is stored locally, we should have file data |
||||
1174 | if ($object->isNew() && null === $tempName && null === $path) { |
||||
1175 | $context->buildViolation('mautic.asset.asset.error.missing.file') |
||||
1176 | ->atPath('tempName') |
||||
1177 | ->setTranslationDomain('validators') |
||||
1178 | ->addViolation(); |
||||
1179 | } |
||||
1180 | |||||
1181 | if (null === $object->getTitle()) { |
||||
1182 | $context->buildViolation('mautic.asset.asset.error.missing.title') |
||||
1183 | ->atPath('title') |
||||
1184 | ->setTranslationDomain('validators') |
||||
1185 | ->addViolation(); |
||||
1186 | } |
||||
1187 | |||||
1188 | // Unset any remote file data |
||||
1189 | $object->setRemotePath(null); |
||||
1190 | } elseif ($object->isRemote()) { |
||||
1191 | // If the object is stored remotely, we should have a remote path |
||||
1192 | if (null === $object->getRemotePath()) { |
||||
1193 | $context->buildViolation('mautic.asset.asset.error.missing.remote.path') |
||||
1194 | ->atPath('remotePath') |
||||
1195 | ->setTranslationDomain('validators') |
||||
1196 | ->addViolation(); |
||||
1197 | } |
||||
1198 | |||||
1199 | // Unset any local file data |
||||
1200 | $object->setPath(null); |
||||
1201 | } |
||||
1202 | } |
||||
1203 | |||||
1204 | /** |
||||
1205 | * Set temporary ID. |
||||
1206 | * |
||||
1207 | * @param string $tempId |
||||
1208 | * |
||||
1209 | * @return Asset |
||||
1210 | */ |
||||
1211 | public function setTempId($tempId) |
||||
1212 | { |
||||
1213 | $this->tempId = $tempId; |
||||
1214 | |||||
1215 | return $this; |
||||
1216 | } |
||||
1217 | |||||
1218 | /** |
||||
1219 | * Get temporary ID. |
||||
1220 | * |
||||
1221 | * @return string |
||||
1222 | */ |
||||
1223 | public function getTempId() |
||||
1224 | { |
||||
1225 | return $this->tempId; |
||||
1226 | } |
||||
1227 | |||||
1228 | /** |
||||
1229 | * Set temporary file name. |
||||
1230 | * |
||||
1231 | * @param string $tempName |
||||
1232 | * |
||||
1233 | * @return Asset |
||||
1234 | */ |
||||
1235 | public function setTempName($tempName) |
||||
1236 | { |
||||
1237 | $this->tempName = $tempName; |
||||
1238 | |||||
1239 | return $this; |
||||
1240 | } |
||||
1241 | |||||
1242 | /** |
||||
1243 | * Get temporary file name. |
||||
1244 | * |
||||
1245 | * @return string |
||||
1246 | */ |
||||
1247 | public function getTempName() |
||||
1248 | { |
||||
1249 | return $this->tempName; |
||||
1250 | } |
||||
1251 | |||||
1252 | /** |
||||
1253 | * @param bool $humanReadable |
||||
1254 | * @param bool $forceUpdate |
||||
1255 | * @param string $inUnit |
||||
1256 | * |
||||
1257 | * @return float|string |
||||
1258 | */ |
||||
1259 | public function getSize($humanReadable = true, $forceUpdate = false, $inUnit = '') |
||||
1260 | { |
||||
1261 | if (empty($this->size) || $forceUpdate) { |
||||
1262 | // Try to fetch it |
||||
1263 | if ($this->isRemote()) { |
||||
1264 | $ch = curl_init($this->getRemotePath()); |
||||
1265 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||
1266 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); |
||||
1267 | curl_setopt($ch, CURLOPT_HEADER, 1); |
||||
1268 | curl_setopt($ch, CURLOPT_NOBODY, 1); |
||||
1269 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); |
||||
1270 | |||||
1271 | curl_exec($ch); |
||||
1272 | |||||
1273 | $this->setSize(round(curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD))); |
||||
1274 | } |
||||
1275 | |||||
1276 | if (null === $this->loadFile()) { |
||||
1277 | return 0; |
||||
1278 | } |
||||
1279 | |||||
1280 | $this->setSize(round($this->loadFile()->getSize())); |
||||
1281 | } |
||||
1282 | |||||
1283 | return ($humanReadable) ? static::convertBytesToHumanReadable($this->size, $inUnit) : $this->size; |
||||
1284 | } |
||||
1285 | |||||
1286 | /** |
||||
1287 | * @param mixed $size |
||||
1288 | * |
||||
1289 | * @return Asset |
||||
1290 | */ |
||||
1291 | public function setSize($size) |
||||
1292 | { |
||||
1293 | $this->size = $size; |
||||
1294 | |||||
1295 | return $this; |
||||
1296 | } |
||||
1297 | |||||
1298 | /** |
||||
1299 | * Get value from PHP configuration with special handling of -1. |
||||
1300 | * |
||||
1301 | * @param string $setting |
||||
1302 | * @param bool|true $convertToBytes |
||||
1303 | * |
||||
1304 | * @return int |
||||
1305 | */ |
||||
1306 | public static function getIniValue($setting, $convertToBytes = true) |
||||
1307 | { |
||||
1308 | $value = ini_get($setting); |
||||
1309 | |||||
1310 | if (-1 == $value || 0 === $value) { |
||||
1311 | return PHP_INT_MAX; |
||||
1312 | } |
||||
1313 | |||||
1314 | if ($convertToBytes) { |
||||
1315 | $value = FileHelper::convertPHPSizeToBytes($value); |
||||
1316 | } |
||||
1317 | |||||
1318 | return (int) $value; |
||||
1319 | } |
||||
1320 | |||||
1321 | /** |
||||
1322 | * @param $size |
||||
1323 | * @param string $unit |
||||
1324 | * |
||||
1325 | * @return string |
||||
1326 | */ |
||||
1327 | public static function convertBytesToHumanReadable($size, $unit = '') |
||||
1328 | { |
||||
1329 | list($number, $unit) = self::convertBytesToUnit($size, $unit); |
||||
1330 | |||||
1331 | // Format number |
||||
1332 | $number = number_format($number, 2); |
||||
1333 | |||||
1334 | // Remove trailing .00 |
||||
1335 | $number = false !== strpos($number, '.') ? rtrim(rtrim($number, '0'), '.') : $number; |
||||
1336 | |||||
1337 | return $number.' '.$unit; |
||||
1338 | } |
||||
1339 | |||||
1340 | /** |
||||
1341 | * @param $size |
||||
1342 | * @param string $unit |
||||
1343 | * |
||||
1344 | * @return array |
||||
1345 | */ |
||||
1346 | public static function convertBytesToUnit($size, $unit = '') |
||||
1347 | { |
||||
1348 | $unit = strtoupper($unit); |
||||
1349 | |||||
1350 | if ((!$unit && $size >= 1 << 30) || 'GB' == $unit || 'G' == $unit) { |
||||
1351 | return [$size / (1 << 30), 'GB']; |
||||
1352 | } |
||||
1353 | if ((!$unit && $size >= 1 << 20) || 'MB' == $unit || 'M' == $unit) { |
||||
1354 | return [$size / (1 << 20), 'MB']; |
||||
1355 | } |
||||
1356 | if ((!$unit && $size >= 1 << 10) || 'KB' == $unit || 'K' == $unit) { |
||||
1357 | return [$size / (1 << 10), 'KB']; |
||||
1358 | } |
||||
1359 | |||||
1360 | // Add zero to remove useless .00 |
||||
1361 | return [$size, 'bytes']; |
||||
1362 | } |
||||
1363 | |||||
1364 | /** |
||||
1365 | * @return string|null |
||||
1366 | */ |
||||
1367 | public function getDownloadUrl() |
||||
1368 | { |
||||
1369 | return $this->downloadUrl; |
||||
1370 | } |
||||
1371 | |||||
1372 | /** |
||||
1373 | * @param string|null $downloadUrl |
||||
1374 | * |
||||
1375 | * @return Asset |
||||
1376 | */ |
||||
1377 | public function setDownloadUrl($downloadUrl) |
||||
1378 | { |
||||
1379 | $this->downloadUrl = $downloadUrl; |
||||
1380 | |||||
1381 | return $this; |
||||
1382 | } |
||||
1383 | |||||
1384 | /** |
||||
1385 | * @return bool |
||||
1386 | */ |
||||
1387 | public function isLocal() |
||||
1388 | { |
||||
1389 | return 'local' === $this->storageLocation; |
||||
1390 | } |
||||
1391 | |||||
1392 | /** |
||||
1393 | * @return bool |
||||
1394 | */ |
||||
1395 | public function isRemote() |
||||
1396 | { |
||||
1397 | return 'remote' === $this->storageLocation; |
||||
1398 | } |
||||
1399 | |||||
1400 | /** |
||||
1401 | * @return bool |
||||
1402 | */ |
||||
1403 | public function getDisallow() |
||||
1404 | { |
||||
1405 | return $this->disallow; |
||||
1406 | } |
||||
1407 | |||||
1408 | /** |
||||
1409 | * @param mixed $disallow |
||||
1410 | */ |
||||
1411 | public function setDisallow($disallow) |
||||
1412 | { |
||||
1413 | $this->disallow = $disallow; |
||||
1414 | } |
||||
1415 | } |
||||
1416 |