parent
4e7d2f31e0
commit
f57641bb27
@ -0,0 +1,78 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Component\Utils; |
||||
|
||||
use Symfony\Component\PropertyAccess\PropertyAccess; |
||||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; |
||||
use Vich\UploaderBundle\Mapping\PropertyMapping; |
||||
use Vich\UploaderBundle\Naming\ConfigurableInterface; |
||||
use Vich\UploaderBundle\Naming\DirectoryNamerInterface; |
||||
use Vich\UploaderBundle\Util\Transliterator; |
||||
|
||||
class AssetDirectoryNamer implements DirectoryNamerInterface, ConfigurableInterface |
||||
{ |
||||
/** |
||||
* @var string |
||||
*/ |
||||
private $propertyPath; |
||||
private $charsPerDir = 2; |
||||
private $dirs = 1; |
||||
|
||||
/** |
||||
* @var bool |
||||
*/ |
||||
private $transliterate = false; |
||||
|
||||
/** |
||||
* @var PropertyAccessorInterface |
||||
*/ |
||||
protected $propertyAccessor; |
||||
|
||||
/** |
||||
* @var Transliterator |
||||
*/ |
||||
private $transliterator; |
||||
|
||||
public function __construct(?PropertyAccessorInterface $propertyAccessor, Transliterator $transliterator) |
||||
{ |
||||
$this->propertyAccessor = $propertyAccessor ?: PropertyAccess::createPropertyAccessor(); |
||||
$this->transliterator = $transliterator; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* @param array $options Options for this namer. The following options are accepted: |
||||
* - chars_per_dir: how many chars use for each dir. |
||||
* - dirs: how many dirs create |
||||
*/ |
||||
public function configure(array $options): void |
||||
{ |
||||
if (empty($options['property'])) { |
||||
throw new \InvalidArgumentException('Option "property" is missing or empty.'); |
||||
} |
||||
|
||||
$this->propertyPath = $options['property']; |
||||
|
||||
$options = \array_merge(['chars_per_dir' => $this->charsPerDir, 'dirs' => $this->dirs], $options); |
||||
|
||||
$this->charsPerDir = $options['chars_per_dir']; |
||||
$this->dirs = $options['dirs']; |
||||
} |
||||
|
||||
public function directoryName($object, PropertyMapping $mapping): string |
||||
{ |
||||
$fileName = $mapping->getFileName($object); |
||||
|
||||
$category = $this->propertyAccessor->getValue($object, $this->propertyPath); |
||||
|
||||
$parts[] = $category; |
||||
/*for ($i = 0, $start = 0; $i < $this->dirs; $i++, $start += $this->charsPerDir) { |
||||
$parts[] = \substr($fileName, $start, $this->charsPerDir); |
||||
}*/ |
||||
$parts[] = $fileName; |
||||
|
||||
return \implode('/', $parts); |
||||
} |
||||
} |
@ -0,0 +1,383 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Entity; |
||||
|
||||
use Doctrine\ORM\Mapping as ORM; |
||||
use Gedmo\Timestampable\Traits\TimestampableEntity; |
||||
use Symfony\Component\HttpFoundation\File\File; |
||||
use Symfony\Component\HttpFoundation\File\UploadedFile; |
||||
use Symfony\Component\Serializer\Annotation\Groups; |
||||
use Symfony\Component\Validator\Constraints as Assert; |
||||
use Vich\UploaderBundle\Mapping\Annotation as Vich; |
||||
|
||||
/** |
||||
* @ORM\Entity |
||||
* @Vich\Uploadable |
||||
* |
||||
* @ORM\Table(name="asset") |
||||
*/ |
||||
class Asset |
||||
{ |
||||
use TimestampableEntity; |
||||
|
||||
public const SCORM = 'scorm'; |
||||
public const WATERMARK = 'watermark'; |
||||
public const CSS = 'css'; |
||||
|
||||
/** |
||||
* @ORM\Id |
||||
* @ORM\Column(type="integer") |
||||
* @ORM\GeneratedValue |
||||
*/ |
||||
protected $id; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @Assert\NotBlank() |
||||
* |
||||
* @ORM\Column(type="string", length=255) |
||||
*/ |
||||
protected $title; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @Assert\Choice({Asset::SCORM, Asset::WATERMARK, Asset::CSS}, message="Choose a valid category.") |
||||
* |
||||
* @ORM\Column(type="string", length=255) |
||||
*/ |
||||
protected $category; |
||||
|
||||
/** |
||||
* @var File |
||||
* |
||||
* @Assert\NotNull() |
||||
* @Vich\UploadableField( |
||||
* mapping="assets", |
||||
* fileNameProperty="title", |
||||
* size="size", |
||||
* mimeType="mimeType", |
||||
* originalName="originalName", |
||||
* dimensions="dimensions" |
||||
* ) |
||||
*/ |
||||
protected $file; |
||||
|
||||
/** |
||||
* @ORM\Column(type="boolean") |
||||
*/ |
||||
protected bool $compressed; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @Groups({"resource_file:read", "resource_node:read", "document:read"}) |
||||
* @ORM\Column(type="text", nullable=true) |
||||
*/ |
||||
protected $mimeType; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(type="text", nullable=true) |
||||
*/ |
||||
protected $originalName; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @Groups({"resource_file:read", "resource_node:read", "document:read"}) |
||||
* @ORM\Column(type="simple_array", nullable=true) |
||||
*/ |
||||
protected $dimensions; |
||||
|
||||
/** |
||||
* @var int |
||||
* |
||||
* @ORM\Column(type="integer") |
||||
*/ |
||||
protected $size; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(name="crop", type="string", length=255, nullable=true) |
||||
*/ |
||||
protected $crop; |
||||
|
||||
/** |
||||
* @var array |
||||
* |
||||
* @ORM\Column(type="array", nullable=true) |
||||
*/ |
||||
protected $metadata; |
||||
|
||||
/** |
||||
* @var string |
||||
* |
||||
* @ORM\Column(name="description", type="text", nullable=true) |
||||
*/ |
||||
protected $description; |
||||
|
||||
public function __construct() |
||||
{ |
||||
$this->metadata = []; |
||||
$this->size = 0; |
||||
$this->compressed = false; |
||||
} |
||||
|
||||
/** |
||||
* @return int |
||||
*/ |
||||
public function getId() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
public function __toString(): string |
||||
{ |
||||
return $this->getOriginalName(); |
||||
} |
||||
|
||||
public function isImage(): bool |
||||
{ |
||||
$mimeType = $this->getMimeType(); |
||||
if (false !== strpos($mimeType, 'image')) { |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public function isVideo(): bool |
||||
{ |
||||
$mimeType = $this->getMimeType(); |
||||
if (false !== strpos($mimeType, 'video')) { |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getCrop() |
||||
{ |
||||
return $this->crop; |
||||
} |
||||
|
||||
/** |
||||
* @param string $crop |
||||
* |
||||
* @return $this |
||||
*/ |
||||
public function setCrop($crop): self |
||||
{ |
||||
$this->crop = $crop; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getSize(): int |
||||
{ |
||||
return (int) $this->size; |
||||
} |
||||
|
||||
/** |
||||
* @param int $size |
||||
*/ |
||||
public function setSize($size): self |
||||
{ |
||||
$this->size = $size; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/*public function getDescription(): string |
||||
{ |
||||
return $this->description; |
||||
} |
||||
|
||||
public function setDescription(string $description): self |
||||
{ |
||||
$this->description = $description; |
||||
|
||||
return $this; |
||||
}*/ |
||||
|
||||
public function getMimeType(): string |
||||
{ |
||||
return $this->mimeType; |
||||
} |
||||
|
||||
/** |
||||
* @param string $mimeType |
||||
*/ |
||||
public function setMimeType($mimeType): self |
||||
{ |
||||
$this->mimeType = $mimeType; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getOriginalName(): string |
||||
{ |
||||
return (string) $this->originalName; |
||||
} |
||||
|
||||
/** |
||||
* @param string $originalName |
||||
*/ |
||||
public function setOriginalName($originalName): self |
||||
{ |
||||
$this->originalName = $originalName; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getDimensions(): array |
||||
{ |
||||
return $this->dimensions; |
||||
} |
||||
|
||||
/** |
||||
* @param $dimensions |
||||
*/ |
||||
public function setDimensions($dimensions): self |
||||
{ |
||||
$this->dimensions = $dimensions; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getWidth(): int |
||||
{ |
||||
$data = $this->getDimensions(); |
||||
if ($data) { |
||||
//$data = explode(',', $data); |
||||
|
||||
return (int) $data[0]; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
public function getHeight(): int |
||||
{ |
||||
$data = $this->getDimensions(); |
||||
|
||||
if ($data) { |
||||
//$data = explode(',', $data); |
||||
|
||||
return (int) $data[1]; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
public function getMetadata(): array |
||||
{ |
||||
return $this->metadata; |
||||
} |
||||
|
||||
public function setMetadata(array $metadata): self |
||||
{ |
||||
$this->metadata = $metadata; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getDescription(): string |
||||
{ |
||||
return $this->description; |
||||
} |
||||
|
||||
public function setDescription(string $description): self |
||||
{ |
||||
$this->description = $description; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getFile(): ?File |
||||
{ |
||||
return $this->file; |
||||
} |
||||
|
||||
public function hasFile() |
||||
{ |
||||
return null !== $this->file; |
||||
} |
||||
|
||||
/** |
||||
* @param File|UploadedFile $file |
||||
*/ |
||||
public function setFile(File $file = null): self |
||||
{ |
||||
$this->file = $file; |
||||
|
||||
if (null !== $file) { |
||||
// It is required that at least one field changes if you are using doctrine |
||||
// otherwise the event listeners won't be called and the file is lost |
||||
$this->updatedAt = new \DateTimeImmutable(); |
||||
} |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getTitle(): string |
||||
{ |
||||
return $this->title; |
||||
} |
||||
|
||||
/** |
||||
* @param string $title |
||||
* |
||||
* @return Asset |
||||
*/ |
||||
public function setTitle(string $title): Asset |
||||
{ |
||||
$this->title = $title; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
/** |
||||
* @return string |
||||
*/ |
||||
public function getCategory(): string |
||||
{ |
||||
return $this->category; |
||||
} |
||||
|
||||
/** |
||||
* @param string $category |
||||
* |
||||
* @return Asset |
||||
*/ |
||||
public function setCategory(string $category): Asset |
||||
{ |
||||
$this->category = $category; |
||||
|
||||
return $this; |
||||
} |
||||
|
||||
public function getCompressed(): bool |
||||
{ |
||||
return $this->compressed; |
||||
} |
||||
|
||||
public function setCompressed(bool $compressed) |
||||
{ |
||||
$this->compressed = $compressed; |
||||
|
||||
return $this; |
||||
} |
||||
} |
@ -0,0 +1,103 @@ |
||||
<?php |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Repository; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Asset; |
||||
use Chamilo\CoreBundle\Entity\Course; |
||||
use Chamilo\CoreBundle\Entity\CourseCategory; |
||||
use Chamilo\CoreBundle\Entity\ResourceFile; |
||||
use Chamilo\CoreBundle\Entity\ResourceLink; |
||||
use Chamilo\CoreBundle\Entity\ResourceNode; |
||||
use Chamilo\CoreBundle\Entity\ResourceType; |
||||
use Chamilo\CoreBundle\Entity\Session; |
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository; |
||||
use Doctrine\ORM\EntityManagerInterface; |
||||
use Doctrine\Persistence\ManagerRegistry; |
||||
use League\Flysystem\FilesystemInterface; |
||||
use League\Flysystem\MountManager; |
||||
use League\Flysystem\ZipArchive\ZipArchiveAdapter; |
||||
use Symfony\Component\Filesystem\Exception\FileNotFoundException; |
||||
use Vich\UploaderBundle\Storage\FlysystemStorage; |
||||
|
||||
class AssetRepository extends ServiceEntityRepository |
||||
{ |
||||
protected $mountManager; |
||||
protected $storage; |
||||
|
||||
public function __construct(ManagerRegistry $registry, FlysystemStorage $storage, MountManager $mountManager) |
||||
{ |
||||
parent::__construct($registry, Asset::class); |
||||
$this->storage = $storage; |
||||
$this->mountManager = $mountManager; |
||||
} |
||||
|
||||
public function getFilename(ResourceFile $resourceFile) |
||||
{ |
||||
return $this->storage->resolveUri($resourceFile); |
||||
} |
||||
|
||||
/** |
||||
* @return FilesystemInterface |
||||
*/ |
||||
public function getFileSystem() |
||||
{ |
||||
// Flysystem mount name is saved in config/packages/oneup_flysystem.yaml |
||||
return $this->mountManager->getFilesystem('assets_fs'); |
||||
} |
||||
|
||||
public function unZipFile(Asset $asset, ZipArchiveAdapter $zipArchiveAdapter) |
||||
{ |
||||
$folder = '/'.$asset->getCategory().'/'.$asset->getTitle(); |
||||
|
||||
$fs = $this->getFileSystem(); |
||||
if ($fs->has($folder)) { |
||||
$contents = $zipArchiveAdapter->listContents(); |
||||
foreach ($contents as $data) { |
||||
if ($fs->has($folder.'/'.$data['path'])) { |
||||
continue; |
||||
} |
||||
|
||||
if ('dir' === $data['type']) { |
||||
$fs->createDir($folder.'/'.$data['path']); |
||||
continue; |
||||
} |
||||
|
||||
$fs->write($folder.'/'.$data['path'], $zipArchiveAdapter->read($data['path'])); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public function getFileContent(Asset $asset): string |
||||
{ |
||||
try { |
||||
if ($asset->hasFile()) { |
||||
$file = $asset->getFile(); |
||||
$fileName = $this->getFilename($file); |
||||
|
||||
return $this->getFileSystem()->read($fileName); |
||||
} |
||||
|
||||
return ''; |
||||
} catch (\Throwable $exception) { |
||||
throw new FileNotFoundException($asset); |
||||
} |
||||
} |
||||
|
||||
public function getFileStream(Asset $asset) |
||||
{ |
||||
try { |
||||
if ($asset->hasFile()) { |
||||
$file = $asset->getFile(); |
||||
$fileName = $this->getFilename($file); |
||||
|
||||
return $this->getFileSystem()->readStream($fileName); |
||||
} |
||||
|
||||
return ''; |
||||
} catch (\Throwable $exception) { |
||||
throw new FileNotFoundException($asset); |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue