|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
/* For licensing terms, see /license.txt */
|
|
|
|
|
|
|
|
|
|
namespace Chamilo\CoreBundle\Controller\Api;
|
|
|
|
|
|
|
|
|
|
use Chamilo\CoreBundle\Component\Utils\CreateUploadedFile;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\AbstractResource;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\Course;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\ResourceLink;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\ResourceRight;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\Session;
|
|
|
|
|
use Chamilo\CoreBundle\Entity\User;
|
|
|
|
|
use Chamilo\CoreBundle\Repository\ResourceRepository;
|
|
|
|
|
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
|
|
|
|
|
use Chamilo\CourseBundle\Entity\CDocument;
|
|
|
|
|
use Chamilo\CourseBundle\Entity\CGroup;
|
|
|
|
|
use DateTime;
|
|
|
|
|
use Doctrine\ORM\EntityManager;
|
|
|
|
|
use Doctrine\ORM\EntityManagerInterface;
|
|
|
|
|
use Exception;
|
|
|
|
|
use InvalidArgumentException;
|
|
|
|
|
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
|
|
|
|
use Symfony\Component\HttpKernel\KernelInterface;
|
|
|
|
|
use ZipArchive;
|
|
|
|
|
|
|
|
|
|
class BaseResourceFileAction
|
|
|
|
|
{
|
|
|
|
|
public static function setLinks(AbstractResource $resource, EntityManagerInterface $em): void
|
|
|
|
|
{
|
|
|
|
|
$resourceNode = $resource->getResourceNode();
|
|
|
|
|
$links = $resource->getResourceLinkArray();
|
|
|
|
|
if ($links) {
|
|
|
|
|
$groupRepo = $em->getRepository(CGroup::class);
|
|
|
|
|
$courseRepo = $em->getRepository(Course::class);
|
|
|
|
|
$sessionRepo = $em->getRepository(Session::class);
|
|
|
|
|
$userRepo = $em->getRepository(User::class);
|
|
|
|
|
|
|
|
|
|
foreach ($links as $link) {
|
|
|
|
|
$resourceLink = new ResourceLink();
|
|
|
|
|
$linkSet = false;
|
|
|
|
|
if (isset($link['cid']) && !empty($link['cid'])) {
|
|
|
|
|
$course = $courseRepo->find($link['cid']);
|
|
|
|
|
if (null !== $course) {
|
|
|
|
|
$linkSet = true;
|
|
|
|
|
$resourceLink->setCourse($course);
|
|
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException(sprintf('Course #%s does not exists', $link['cid']));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($link['sid']) && !empty($link['sid'])) {
|
|
|
|
|
$session = $sessionRepo->find($link['sid']);
|
|
|
|
|
if (null !== $session) {
|
|
|
|
|
$linkSet = true;
|
|
|
|
|
$resourceLink->setSession($session);
|
|
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException(sprintf('Session #%s does not exists', $link['sid']));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($link['gid']) && !empty($link['gid'])) {
|
|
|
|
|
$group = $groupRepo->find($link['gid']);
|
|
|
|
|
if (null !== $group) {
|
|
|
|
|
$linkSet = true;
|
|
|
|
|
$resourceLink->setGroup($group);
|
|
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException(sprintf('Group #%s does not exists', $link['gid']));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($link['uid']) && !empty($link['uid'])) {
|
|
|
|
|
$user = $userRepo->find($link['uid']);
|
|
|
|
|
if (null !== $user) {
|
|
|
|
|
$linkSet = true;
|
|
|
|
|
$resourceLink->setUser($user);
|
|
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException(sprintf('User #%s does not exists', $link['uid']));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (isset($link['visibility'])) {
|
|
|
|
|
$resourceLink->setVisibility((int) $link['visibility']);
|
|
|
|
|
} else {
|
|
|
|
|
throw new InvalidArgumentException('Link needs a visibility key');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ($linkSet) {
|
|
|
|
|
$em->persist($resourceLink);
|
|
|
|
|
$resourceNode->addResourceLink($resourceLink);
|
|
|
|
|
// $em->persist($resourceNode);
|
|
|
|
|
// $em->persist($resource->getResourceNode());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Use by Chamilo not api platform.
|
|
|
|
|
$links = $resource->getResourceLinkEntityList();
|
|
|
|
|
if ($links) {
|
|
|
|
|
// error_log('$resource->getResourceLinkEntityList()');
|
|
|
|
|
foreach ($links as $link) {
|
|
|
|
|
/*$rights = [];
|
|
|
|
|
switch ($link->getVisibility()) {
|
|
|
|
|
case ResourceLink::VISIBILITY_PENDING:
|
|
|
|
|
case ResourceLink::VISIBILITY_DRAFT:
|
|
|
|
|
$editorMask = ResourceNodeVoter::getEditorMask();
|
|
|
|
|
$resourceRight = new ResourceRight();
|
|
|
|
|
$resourceRight
|
|
|
|
|
->setMask($editorMask)
|
|
|
|
|
->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
|
|
|
|
|
;
|
|
|
|
|
$rights[] = $resourceRight;
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!empty($rights)) {
|
|
|
|
|
foreach ($rights as $right) {
|
|
|
|
|
$link->addResourceRight($right);
|
|
|
|
|
}
|
|
|
|
|
}*/
|
|
|
|
|
// error_log('link adding to node: '.$resource->getResourceNode()->getId());
|
|
|
|
|
// error_log('link with user : '.$link->getUser()->getUsername());
|
|
|
|
|
$resource->getResourceNode()->addResourceLink($link);
|
|
|
|
|
|
|
|
|
|
$em->persist($link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @todo use this function inside handleCreateFileRequest
|
|
|
|
|
*/
|
|
|
|
|
protected function handleCreateRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array
|
|
|
|
|
{
|
|
|
|
|
$contentData = $request->getContent();
|
|
|
|
|
|
|
|
|
|
if (!empty($contentData)) {
|
|
|
|
|
$contentData = json_decode($contentData, true);
|
|
|
|
|
$title = $contentData['title'] ?? '';
|
|
|
|
|
$parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0);
|
|
|
|
|
$resourceLinkList = $contentData['resourceLinkList'] ?? [];
|
|
|
|
|
if (empty($resourceLinkList)) {
|
|
|
|
|
$resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? [];
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$contentData = $request->request->all();
|
|
|
|
|
$title = $request->get('title');
|
|
|
|
|
$parentResourceNodeId = (int) $request->get('parentResourceNodeId');
|
|
|
|
|
$resourceLinkList = $request->get('resourceLinkList', []);
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true);
|
|
|
|
|
if (empty($resourceLinkList)) {
|
|
|
|
|
$message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]';
|
|
|
|
|
|
|
|
|
|
throw new InvalidArgumentException($message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 === $parentResourceNodeId) {
|
|
|
|
|
throw new Exception('Parameter parentResourceNodeId int value is needed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resource->setParentResourceNode($parentResourceNodeId);
|
|
|
|
|
|
|
|
|
|
if (empty($title)) {
|
|
|
|
|
throw new InvalidArgumentException('title is required');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resource->setResourceName($title);
|
|
|
|
|
|
|
|
|
|
// Set resource link list if exists.
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resource->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $contentData;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Function loaded when creating a resource using the api, then the ResourceListener is executed.
|
|
|
|
|
*/
|
|
|
|
|
protected function handleCreateFileRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request, EntityManager $em, string $fileExistsOption = ''): array
|
|
|
|
|
{
|
|
|
|
|
$contentData = $request->getContent();
|
|
|
|
|
|
|
|
|
|
if (!empty($contentData)) {
|
|
|
|
|
$contentData = json_decode($contentData, true);
|
|
|
|
|
$title = $contentData['title'] ?? '';
|
|
|
|
|
$comment = $contentData['comment'] ?? '';
|
|
|
|
|
$parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0);
|
|
|
|
|
$fileType = $contentData['filetype'] ?? '';
|
|
|
|
|
$resourceLinkList = $contentData['resourceLinkList'] ?? [];
|
|
|
|
|
} else {
|
|
|
|
|
$title = $request->get('title');
|
|
|
|
|
$comment = $request->get('comment');
|
|
|
|
|
$parentResourceNodeId = (int) $request->get('parentResourceNodeId');
|
|
|
|
|
$fileType = $request->get('filetype');
|
|
|
|
|
$resourceLinkList = $request->get('resourceLinkList', []);
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true);
|
|
|
|
|
if (empty($resourceLinkList)) {
|
|
|
|
|
$message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]';
|
|
|
|
|
|
|
|
|
|
throw new InvalidArgumentException($message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (empty($fileType)) {
|
|
|
|
|
throw new Exception('filetype needed: folder or file');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 === $parentResourceNodeId) {
|
|
|
|
|
throw new Exception('parentResourceNodeId int value needed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resource->setParentResourceNode($parentResourceNodeId);
|
|
|
|
|
|
|
|
|
|
switch ($fileType) {
|
|
|
|
|
case 'certificate':
|
|
|
|
|
case 'file':
|
|
|
|
|
$content = '';
|
|
|
|
|
if ($request->request->has('contentFile')) {
|
|
|
|
|
$content = $request->request->get('contentFile');
|
|
|
|
|
}
|
|
|
|
|
$fileParsed = false;
|
|
|
|
|
// File upload.
|
|
|
|
|
if ($request->files->count() > 0) {
|
|
|
|
|
if (!$request->files->has('uploadFile')) {
|
|
|
|
|
throw new BadRequestHttpException('"uploadFile" is required');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @var UploadedFile $uploadedFile */
|
|
|
|
|
$uploadedFile = $request->files->get('uploadFile');
|
|
|
|
|
$title = $uploadedFile->getClientOriginalName();
|
|
|
|
|
|
|
|
|
|
if (empty($title)) {
|
|
|
|
|
throw new InvalidArgumentException('title is required');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle the appropriate action based on the fileExistsOption
|
|
|
|
|
if (!empty($fileExistsOption)) {
|
|
|
|
|
// Check if a document with the same title and parent resource node already exists
|
|
|
|
|
$existingDocument = $resourceRepository->findByTitleAndParentResourceNode($title, $parentResourceNodeId);
|
|
|
|
|
if ($existingDocument) {
|
|
|
|
|
if ('overwrite' == $fileExistsOption) {
|
|
|
|
|
// Perform actions when file exists and 'overwrite' option is selected
|
|
|
|
|
$resource->setResourceName($title);
|
|
|
|
|
$existingDocument->setTitle($title);
|
|
|
|
|
$existingDocument->setComment($comment);
|
|
|
|
|
$em->persist($existingDocument);
|
|
|
|
|
$em->flush();
|
|
|
|
|
|
|
|
|
|
// Return any data you need for further processing
|
|
|
|
|
return [
|
|
|
|
|
'title' => $title,
|
|
|
|
|
'filetype' => 'file',
|
|
|
|
|
'comment' => $comment,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('rename' == $fileExistsOption) {
|
|
|
|
|
// Perform actions when file exists and 'rename' option is selected
|
|
|
|
|
$newTitle = $this->generateUniqueTitle($title); // Generate a unique title
|
|
|
|
|
$resource->setResourceName($newTitle);
|
|
|
|
|
$resource->setUploadFile($uploadedFile);
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resource->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
}
|
|
|
|
|
$em->persist($resource);
|
|
|
|
|
$em->flush();
|
|
|
|
|
|
|
|
|
|
// Return any data you need for further processing
|
|
|
|
|
return [
|
|
|
|
|
'title' => $title,
|
|
|
|
|
'filetype' => 'file',
|
|
|
|
|
'comment' => $comment,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('nothing' == $fileExistsOption) {
|
|
|
|
|
// Perform actions when file exists and 'nothing' option is selected
|
|
|
|
|
// Display a message indicating that the file already exists
|
|
|
|
|
// or perform any other desired actions based on your application's requirements
|
|
|
|
|
$resource->setResourceName($title);
|
|
|
|
|
$flashBag = $request->getSession()->getFlashBag();
|
|
|
|
|
$flashBag->add('warning', 'Upload Already Exists');
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'title' => $title,
|
|
|
|
|
'filetype' => 'file',
|
|
|
|
|
'comment' => $comment,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
throw new InvalidArgumentException('Invalid fileExistsOption');
|
|
|
|
|
} else {
|
|
|
|
|
$resource->setResourceName($title);
|
|
|
|
|
$resource->setUploadFile($uploadedFile);
|
|
|
|
|
$fileParsed = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get data in content and create a HTML file.
|
|
|
|
|
if (!$fileParsed && $content) {
|
|
|
|
|
$uploadedFile = CreateUploadedFile::fromString($title.'.html', 'text/html', $content);
|
|
|
|
|
$resource->setUploadFile($uploadedFile);
|
|
|
|
|
$fileParsed = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!$fileParsed) {
|
|
|
|
|
throw new InvalidArgumentException('filetype was set to "file" but not upload file found');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'folder':
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Set resource link list if exists.
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resource->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'title' => $title,
|
|
|
|
|
'filetype' => $fileType,
|
|
|
|
|
'comment' => $comment,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function handleCreateFileRequestUncompress(AbstractResource $resource, Request $request, EntityManager $em, KernelInterface $kernel): array
|
|
|
|
|
{
|
|
|
|
|
// Get the parameters from the request
|
|
|
|
|
$parentResourceNodeId = (int) $request->get('parentResourceNodeId');
|
|
|
|
|
$fileType = $request->get('filetype');
|
|
|
|
|
$resourceLinkList = $request->get('resourceLinkList', []);
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true);
|
|
|
|
|
if (empty($resourceLinkList)) {
|
|
|
|
|
$message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]';
|
|
|
|
|
|
|
|
|
|
throw new InvalidArgumentException($message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (empty($fileType)) {
|
|
|
|
|
throw new Exception('filetype needed: folder or file');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (0 === $parentResourceNodeId) {
|
|
|
|
|
throw new Exception('parentResourceNodeId int value needed');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ('file' == $fileType && $request->files->count() > 0) {
|
|
|
|
|
if (!$request->files->has('uploadFile')) {
|
|
|
|
|
throw new BadRequestHttpException('"uploadFile" is required');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$uploadedFile = $request->files->get('uploadFile');
|
|
|
|
|
$resourceTitle = $uploadedFile->getClientOriginalName();
|
|
|
|
|
$resource->setResourceName($resourceTitle);
|
|
|
|
|
$resource->setUploadFile($uploadedFile);
|
|
|
|
|
|
|
|
|
|
if ('zip' === $uploadedFile->getClientOriginalExtension()) {
|
|
|
|
|
// Extract the files and subdirectories
|
|
|
|
|
$extractedData = $this->extractZipFile($uploadedFile, $kernel);
|
|
|
|
|
$folderStructure = $extractedData['folderStructure'];
|
|
|
|
|
$extractPath = $extractedData['extractPath'];
|
|
|
|
|
$documents = $this->saveZipContentsAsDocuments($folderStructure, $em, $resourceLinkList, $parentResourceNodeId, '', $extractPath, $processedItems);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resource->setParentResourceNode($parentResourceNodeId);
|
|
|
|
|
|
|
|
|
|
return [
|
|
|
|
|
'filetype' => $fileType,
|
|
|
|
|
'comment' => 'Uncompressed',
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function handleUpdateRequest(AbstractResource $resource, ResourceRepository $repo, Request $request, EntityManager $em): AbstractResource
|
|
|
|
|
{
|
|
|
|
|
$contentData = $request->getContent();
|
|
|
|
|
$resourceLinkList = [];
|
|
|
|
|
if (!empty($contentData)) {
|
|
|
|
|
$contentData = json_decode($contentData, true);
|
|
|
|
|
$title = $contentData['title'] ?? '';
|
|
|
|
|
$content = $contentData['contentFile'] ?? '';
|
|
|
|
|
$resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? [];
|
|
|
|
|
} else {
|
|
|
|
|
$title = $request->get('title');
|
|
|
|
|
$content = $request->request->get('contentFile');
|
|
|
|
|
// $comment = $request->request->get('comment');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$repo->setResourceName($resource, $title);
|
|
|
|
|
|
|
|
|
|
$hasFile = $resource->getResourceNode()->hasResourceFile();
|
|
|
|
|
|
|
|
|
|
$resourceNode = $resource->getResourceNode();
|
|
|
|
|
|
|
|
|
|
if ($hasFile && !empty($content)) {
|
|
|
|
|
if ($resourceNode->hasResourceFile()) {
|
|
|
|
|
// The content is updated by the ResourceNodeListener.php
|
|
|
|
|
$resourceNode->setContent($content);
|
|
|
|
|
$resourceNode->getResourceFile()->setSize(\strlen($content));
|
|
|
|
|
}
|
|
|
|
|
$resourceNode->getResourceFile()->setUpdatedAt(new DateTime());
|
|
|
|
|
$resource->setResourceNode($resourceNode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$link = null;
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
foreach ($resourceLinkList as $key => &$linkArray) {
|
|
|
|
|
// Find the exact link.
|
|
|
|
|
$linkId = $linkArray['id'] ?? 0;
|
|
|
|
|
if (!empty($linkId)) {
|
|
|
|
|
/** @var ResourceLink $link */
|
|
|
|
|
$link = $resourceNode->getResourceLinks()->filter(fn ($link) => $link->getId() === $linkId)->first();
|
|
|
|
|
|
|
|
|
|
if (null !== $link) {
|
|
|
|
|
$link->setVisibility((int) $linkArray['visibility']);
|
|
|
|
|
unset($resourceLinkList[$key]);
|
|
|
|
|
|
|
|
|
|
$em->persist($link);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resource->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
self::setLinks($resource, $em);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$isRecursive = !$hasFile;
|
|
|
|
|
// If it's a folder then change the visibility to the children (That have the same link).
|
|
|
|
|
if ($isRecursive && null !== $link) {
|
|
|
|
|
$repo->copyVisibilityToChildren($resource->getResourceNode(), $link);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$resourceNode->setUpdatedAt(new DateTime());
|
|
|
|
|
|
|
|
|
|
return $resource;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function saveZipContentsAsDocuments(array $folderStructure, EntityManager $em, $resourceLinkList = [], $parentResourceId = null, $currentPath = '', $extractPath = '', &$processedItems = []): array
|
|
|
|
|
{
|
|
|
|
|
$documents = [];
|
|
|
|
|
|
|
|
|
|
foreach ($folderStructure as $key => $item) {
|
|
|
|
|
if (\is_array($item)) {
|
|
|
|
|
$folderName = $key;
|
|
|
|
|
$subFolderStructure = $item;
|
|
|
|
|
|
|
|
|
|
$document = new CDocument();
|
|
|
|
|
$document->setTitle($folderName);
|
|
|
|
|
$document->setFiletype('folder');
|
|
|
|
|
|
|
|
|
|
if (null !== $parentResourceId) {
|
|
|
|
|
$document->setParentResourceNode($parentResourceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$document->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$em->persist($document);
|
|
|
|
|
$em->flush();
|
|
|
|
|
|
|
|
|
|
$documentId = $document->getResourceNode()->getId();
|
|
|
|
|
$documents[$documentId] = [
|
|
|
|
|
'name' => $document->getTitle(),
|
|
|
|
|
'files' => [],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
$subDocuments = $this->saveZipContentsAsDocuments($subFolderStructure, $em, $resourceLinkList, $documentId, $currentPath.$folderName.'/', $extractPath, $processedItems);
|
|
|
|
|
$documents[$documentId]['files'] = $subDocuments;
|
|
|
|
|
} else {
|
|
|
|
|
$fileName = $item;
|
|
|
|
|
|
|
|
|
|
$document = new CDocument();
|
|
|
|
|
$document->setTitle($fileName);
|
|
|
|
|
$document->setFiletype('file');
|
|
|
|
|
|
|
|
|
|
if (null !== $parentResourceId) {
|
|
|
|
|
$document->setParentResourceNode($parentResourceId);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!empty($resourceLinkList)) {
|
|
|
|
|
$document->setResourceLinkArray($resourceLinkList);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$filePath = $extractPath.'/'.$currentPath.$fileName;
|
|
|
|
|
|
|
|
|
|
if (file_exists($filePath)) {
|
|
|
|
|
$uploadedFile = new UploadedFile(
|
|
|
|
|
$filePath,
|
|
|
|
|
$fileName
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
$document->setUploadFile($uploadedFile);
|
|
|
|
|
$em->persist($document);
|
|
|
|
|
$em->flush();
|
|
|
|
|
|
|
|
|
|
$documentId = $document->getResourceNode()->getId();
|
|
|
|
|
$documents[$documentId] = [
|
|
|
|
|
'name' => $document->getTitle(),
|
|
|
|
|
'files' => [],
|
|
|
|
|
];
|
|
|
|
|
} else {
|
|
|
|
|
error_log('File does not exist: '.$filePath);
|
|
|
|
|
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $documents;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function extractZipFile(UploadedFile $file, KernelInterface $kernel): array
|
|
|
|
|
{
|
|
|
|
|
// Get the temporary path of the ZIP file
|
|
|
|
|
$zipFilePath = $file->getRealPath();
|
|
|
|
|
|
|
|
|
|
// Create an instance of the ZipArchive class
|
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
|
$zip->open($zipFilePath);
|
|
|
|
|
|
|
|
|
|
$cacheDirectory = $kernel->getCacheDir();
|
|
|
|
|
$extractPath = $cacheDirectory.'/'.uniqid('extracted_', true);
|
|
|
|
|
mkdir($extractPath);
|
|
|
|
|
|
|
|
|
|
// Extract the contents of the ZIP file
|
|
|
|
|
$zip->extractTo($extractPath);
|
|
|
|
|
|
|
|
|
|
// Array to store the sorted extracted paths
|
|
|
|
|
$extractedPaths = [];
|
|
|
|
|
|
|
|
|
|
// Iterate over each file or directory in the ZIP file
|
|
|
|
|
for ($i = 0; $i < $zip->numFiles; $i++) {
|
|
|
|
|
$filename = $zip->getNameIndex($i);
|
|
|
|
|
$extractedPaths[] = $extractPath.'/'.$filename;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Close the ZIP file
|
|
|
|
|
$zip->close();
|
|
|
|
|
|
|
|
|
|
// Build the folder structure and file associations
|
|
|
|
|
$folderStructure = $this->buildFolderStructure($extractedPaths, $extractPath);
|
|
|
|
|
|
|
|
|
|
// Return the array of folder structure and the extraction path
|
|
|
|
|
return [
|
|
|
|
|
'folderStructure' => $folderStructure,
|
|
|
|
|
'extractPath' => $extractPath,
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function buildFolderStructure(array $paths, string $extractPath): array
|
|
|
|
|
{
|
|
|
|
|
$folderStructure = [];
|
|
|
|
|
|
|
|
|
|
foreach ($paths as $path) {
|
|
|
|
|
$relativePath = str_replace($extractPath.'/', '', $path);
|
|
|
|
|
$parts = explode('/', $relativePath);
|
|
|
|
|
|
|
|
|
|
$currentLevel = &$folderStructure;
|
|
|
|
|
|
|
|
|
|
foreach ($parts as $part) {
|
|
|
|
|
if (!isset($currentLevel[$part])) {
|
|
|
|
|
$currentLevel[$part] = [];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$currentLevel = &$currentLevel[$part];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $this->formatFolderStructure($folderStructure);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function formatFolderStructure(array $folderStructure): array
|
|
|
|
|
{
|
|
|
|
|
$result = [];
|
|
|
|
|
|
|
|
|
|
foreach ($folderStructure as $folder => $contents) {
|
|
|
|
|
$formattedContents = $this->formatFolderStructure($contents);
|
|
|
|
|
|
|
|
|
|
if (!empty($formattedContents)) {
|
|
|
|
|
$result[$folder] = $formattedContents;
|
|
|
|
|
} elseif (!empty($folder)) {
|
|
|
|
|
$result[] = $folder;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private function generateUniqueTitle(string $title): string
|
|
|
|
|
{
|
|
|
|
|
return $title.'_'.uniqid();
|
|
|
|
|
}
|
|
|
|
|
}
|