Chamilo is a learning management system focused on ease of use and accessibility
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chamilo-lms/src/CoreBundle/Controller/Api/BaseResourceFileAction.php

286 lines
11 KiB

<?php
declare(strict_types=1);
/* For licensing terms, see /license.txt */
namespace Chamilo\CoreBundle\Controller\Api;
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\CGroup;
use DateTime;
use Doctrine\ORM\EntityManager;
use Exception;
use InvalidArgumentException;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class BaseResourceFileAction
{
public static function setLinks(AbstractResource $resource, $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);
}
}
}
/**
* Function loaded when creating a resource using the api, then the ResourceListener is executed.
*/
protected function handleCreateRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array
{
//error_log('handleCreateRequest');
$contentData = $request->getContent();
if (!empty($contentData)) {
$contentData = json_decode($contentData, true);
$title = $contentData['title'] ?? '';
$comment = $contentData['comment'] ?? '';
$parentResourceNodeId = $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 = false === strpos($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 '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();
$resource->setUploadFile($uploadedFile);
$fileParsed = true;
}
// Get data in content and create a HTML file.
if (!$fileParsed && $content) {
$uploadedFile = $resourceRepository->createTempUploadedFile($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;
}
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 [
'filetype' => $fileType,
'comment' => $comment,
];
}
protected function handleUpdateRequest(AbstractResource $resource, ResourceRepository $repo, Request $request, EntityManager $em)
{
$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;
}
}