From 9f183abd0ec90e05007b16220e3022286407eb8e Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Wed, 30 Oct 2019 15:04:42 +0100 Subject: [PATCH] Add "Illustration" entity to set the image of a resource. --- config/services.yaml | 16 +-- main/auth/courses_categories.php | 37 +++--- main/create_course/add_course.php | 27 +++- main/inc/lib/course.lib.php | 2 +- .../Controller/ResourceController.php | 117 ++++++++++-------- .../Controller/ResourceDownloadController.php | 2 - .../Entity/CourseRelUserCatalogue.php | 4 +- src/CoreBundle/Entity/Illustration.php | 102 +++++++++++++++ .../Entity/Resource/AbstractResource.php | 9 -- src/CoreBundle/Framework/Container.php | 10 -- .../Repository/ResourceRepository.php | 57 ++++++++- src/CoreBundle/Resources/config/tools.yml | 2 +- .../Controller/Home/HomeController.php | 54 +------- src/CourseBundle/Resources/config/routing.yml | 7 ++ 14 files changed, 286 insertions(+), 160 deletions(-) create mode 100644 src/CoreBundle/Entity/Illustration.php diff --git a/config/services.yaml b/config/services.yaml index 2f045b57a0..7c72a36af6 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -24,11 +24,11 @@ parameters: glide_config: source: 'oneup_flysystem.resources_filesystem' cache: 'oneup_flysystem.cache_resources_filesystem' + #cache: 'var/cache/resource/' glide_media_filters: document_thumbnail_small: - w: 100 - h: 100 + w: 500 services: # default configuration for services in *this* file @@ -128,12 +128,12 @@ chamilo_course: # model: Chamilo\CourseBundle\Entity\CCourseSetting # repository: Chamilo\CourseBundle\Repository\CCourseSettingRepository -doctrine_cache: - providers: - sylius_settings: - type: file_system - chamilo_settings: - type: file_system +#doctrine_cache: +# providers: +# sylius_settings: +# type: file_system +# chamilo_settings: +# type: file_system gregwar_captcha: width: 200 diff --git a/main/auth/courses_categories.php b/main/auth/courses_categories.php index f8da2d7284..f0c9ca8a81 100755 --- a/main/auth/courses_categories.php +++ b/main/auth/courses_categories.php @@ -1,6 +1,8 @@ getIllustration($courseEntity); + if ($illustration) { + $courseMediumImage = Container::getRouter()->generate( + 'core_tool_resource', + ['id' => $illustration->getId()] ); } diff --git a/main/create_course/add_course.php b/main/create_course/add_course.php index 10ed06916a..c39b8e2cb7 100755 --- a/main/create_course/add_course.php +++ b/main/create_course/add_course.php @@ -341,16 +341,35 @@ if ($form->validate()) { $params['gradebook_model_id'] = isset($course_values['gradebook_model_id']) ? $course_values['gradebook_model_id'] : null; $params['course_template'] = isset($course_values['course_template']) ? $course_values['course_template'] : ''; - include_once api_get_path(SYS_CODE_PATH).'lang/english/trad4all.inc.php'; + /*include_once api_get_path(SYS_CODE_PATH).'lang/english/trad4all.inc.php'; $file_to_include = api_get_path(SYS_CODE_PATH).'lang/'.$course_language.'/trad4all.inc.php'; if (file_exists($file_to_include)) { include $file_to_include; - } + }*/ $course_info = CourseManager::create_course($params); if (!empty($course_info)) { + $request = Container::getRequest(); + + if ($request->files->has('picture')) { + $uploadFile = $request->files->get('picture'); + $repo = Container::getCourseRepository(); + $em = $repo->getEntityManager(); + + // @todo add in repository + $course = $repo->find($course_info['real_id']); + $illustration = new \Chamilo\CoreBundle\Entity\Illustration(); + $illustration->setName('course_picture'); + + $repo->addResourceNode($illustration, api_get_user_entity(api_get_user_id()), $course); + $repo->addFileToResource($illustration, $uploadFile); + + $em->persist($illustration); + $em->flush(); + } + // update course picture /*$picture = $_FILES['picture']; if (!empty($picture['name'])) { @@ -364,12 +383,10 @@ if ($form->validate()) { /*$resourceFile = new \Chamilo\CoreBundle\Entity\Resource\ResourceFile(); $resourceFile->setName('course_image') $picture['tmp_name']*/ + $splash = api_get_setting('course_creation_splash_screen'); if ($splash === 'true') { $url = Container::getRouter()->generate('chamilo_core_course_welcome', ['course' =>$course_info['code']]); - /* - $url .= 'course_info/start.php?'.api_get_cidreq_params($course_info['code']); - $url .= '&first=1';*/ header('Location: '.$url); exit; } else { diff --git a/main/inc/lib/course.lib.php b/main/inc/lib/course.lib.php index 6bc34a2e40..6890ecc663 100755 --- a/main/inc/lib/course.lib.php +++ b/main/inc/lib/course.lib.php @@ -92,7 +92,7 @@ class CourseManager $hook = Container::instantiateHook(HookCreateCourse::class); // Check portal limits - $accessUrlId = api_get_current_access_url_id(); + $accessUrlId = !empty($accessUrlId) ? (int) $accessUrlId : api_get_current_access_url_id(); $authorId = empty($authorId) ? api_get_user_id() : (int) $authorId; if (isset($_configuration[$accessUrlId]) && is_array($_configuration[$accessUrlId])) { diff --git a/src/CoreBundle/Controller/ResourceController.php b/src/CoreBundle/Controller/ResourceController.php index 3f53d7b994..579cb0d133 100644 --- a/src/CoreBundle/Controller/ResourceController.php +++ b/src/CoreBundle/Controller/ResourceController.php @@ -12,11 +12,13 @@ use APY\DataGridBundle\Grid\Source\Entity; use Chamilo\CoreBundle\Component\Utils\Glide; use Chamilo\CoreBundle\Entity\Resource\ResourceNode; use Chamilo\CoreBundle\Entity\Resource\ResourceRight; +use Chamilo\CoreBundle\Repository\ResourceRepository; use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter; use Chamilo\CourseBundle\Controller\CourseControllerInterface; use Chamilo\CourseBundle\Controller\CourseControllerTrait; use Chamilo\CourseBundle\Entity\CDocument; use Chamilo\CourseBundle\Repository\CDocumentRepository; +use Doctrine\ORM\EntityManager; use FOS\RestBundle\View\View; use Sylius\Bundle\ResourceBundle\Event\ResourceControllerEvent; use Sylius\Component\Resource\Exception\UpdateHandlingException; @@ -400,40 +402,53 @@ class ResourceController extends BaseController implements CourseControllerInter * * @param Request $request * @param CDocumentRepository $documentRepo + * @param Glide $glide * * @return Response */ - public function showAction( - Request $request, - CDocumentRepository $documentRepo, - Glide $glide - ): Response { - $file = $request->get('file'); - $type = $request->get('type'); - // see list of filters in config/packages/liip_imagine.yaml - $filter = $request->get('filter'); - $type = !empty($type) ? $type : 'show'; + public function getResourceFileAction(Request $request, Glide $glide): Response + { + $id = $request->get('id'); + $em = $this->getDoctrine(); + $resourceNode = $em->getRepository('ChamiloCoreBundle:Resource\ResourceNode')->find($id); - $criteria = [ - 'path' => "/$file", - 'course' => $this->getCourse(), - ]; + return $this->showFile($resourceNode, $glide, 'show', ''); - $document = $documentRepo->findOneBy($criteria); - if (null === $document) { - throw new NotFoundHttpException(); - } + /* + $fs = $documentRepo->getFileSystem(); + $stream = $fs->readStream($filePath); + $response = new StreamedResponse(function () use ($stream): void { + stream_copy_to_stream($stream, fopen('php://output', 'wb')); + }); + $disposition = $response->headers->makeDisposition( + $forceDownload ? ResponseHeaderBag::DISPOSITION_ATTACHMENT : ResponseHeaderBag::DISPOSITION_INLINE, + Transliterator::transliterate($fileName) + ); + $response->headers->set('Content-Disposition', $disposition); + $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream'); - /** @var ResourceNode $resourceNode */ - $resourceNode = $document->getResourceNode(); + return $response;*/ + } + + /** + * @param ResourceNode $resourceNode + * @param $glide + * @param $type + * @param $filter + * + * @return StreamedResponse + * @throws \League\Flysystem\FileNotFoundException + */ + private function showFile(ResourceNode $resourceNode, $glide, $type, $filter) + { + $fs = $this-> container->get('oneup_flysystem.resources_filesystem'); $this->denyAccessUnlessGranted( ResourceNodeVoter::VIEW, $resourceNode, 'Unauthorised access to resource' ); - $resourceFile = $resourceNode->getResourceFile(); if (!$resourceFile) { @@ -444,13 +459,9 @@ class ResourceController extends BaseController implements CourseControllerInter $filePath = $resourceFile->getFile()->getPathname(); $mimeType = $resourceFile->getMimeType(); - //ServerFactory - switch ($type) { case 'download': $forceDownload = true; - //$provider = $this->get('sonata.media.pool')->getProvider($media->getProviderName()); - //$response = $provider->getDownloadResponse($media, $format, $this->get('sonata.media.pool')->getDownloadMode($media)); break; case 'show': default: @@ -465,7 +476,6 @@ class ResourceController extends BaseController implements CourseControllerInter break; } - $fs = $documentRepo->getFileSystem(); $stream = $fs->readStream($filePath); $response = new StreamedResponse(function () use ($stream): void { stream_copy_to_stream($stream, fopen('php://output', 'wb')); @@ -478,39 +488,40 @@ class ResourceController extends BaseController implements CourseControllerInter $response->headers->set('Content-Type', $mimeType ?: 'application/octet-stream'); return $response; + } - /* - - $configuration = $this->requestConfigurationFactory->create($this->metadata, $request); - $this->isGrantedOr403($configuration, ResourceActions::SHOW); - - $resource = $this->findOr404($configuration); - $resourceNode = $resource->getResourceNode(); + /** + * Shows a resource. + * + * @param Request $request + * @param CDocumentRepository $documentRepo + * @param Glide $glide + * + * @return Response + */ + public function showAction(Request $request, CDocumentRepository $documentRepo, Glide $glide): Response + { + $file = $request->get('file'); + $type = $request->get('type'); + // see list of filters in config/services.yaml + $filter = $request->get('filter'); + $type = !empty($type) ? $type : 'show'; - $this->eventDispatcher->dispatch(ResourceActions::SHOW, $configuration, $resource); + $criteria = [ + 'path' => "/$file", + 'course' => $this->getCourse(), + ]; - $this->denyAccessUnlessGranted( - ResourceNodeVoter::VIEW, - $resourceNode, - 'Unauthorised access to resource' - ); + $document = $documentRepo->findOneBy($criteria); - $view = View::create($resource); - - if ($configuration->isHtmlRequest()) { - $view - ->setTemplate($configuration->getTemplate(ResourceActions::SHOW.'.html')) - ->setTemplateVar($this->metadata->getName()) - ->setData([ - 'configuration' => $configuration, - 'metadata' => $this->metadata, - 'resource' => $resource, - $this->metadata->getName() => $resource, - ]) - ; + if (null === $document) { + throw new NotFoundHttpException(); } - return $this->viewHandler->handle($configuration, $view);*/ + /** @var ResourceNode $resourceNode */ + $resourceNode = $document->getResourceNode(); + + return $this->showFile($resourceNode, $glide, $type, $filter); } /** diff --git a/src/CoreBundle/Controller/ResourceDownloadController.php b/src/CoreBundle/Controller/ResourceDownloadController.php index deba9e01ea..e40d3e53c4 100644 --- a/src/CoreBundle/Controller/ResourceDownloadController.php +++ b/src/CoreBundle/Controller/ResourceDownloadController.php @@ -18,8 +18,6 @@ use Symfony\Component\Routing\Annotation\Route; * @author Julio Montoya . * * @Route("/resource") - * - * @package Chamilo\CoreBundle\Controller */ class ResourceDownloadController extends BaseController { diff --git a/src/CoreBundle/Entity/CourseRelUserCatalogue.php b/src/CoreBundle/Entity/CourseRelUserCatalogue.php index 8464eb9dbb..e61ff7d01b 100644 --- a/src/CoreBundle/Entity/CourseRelUserCatalogue.php +++ b/src/CoreBundle/Entity/CourseRelUserCatalogue.php @@ -43,9 +43,9 @@ class CourseRelUserCatalogue protected $course; /** - * @var bool + * @var int * - * @ORM\Column(name="visible", type="integer", precision=0, scale=0, nullable=false, unique=false) + * @ORM\Column(name="visible", type="integer", nullable=false, unique=false) */ protected $visible; diff --git a/src/CoreBundle/Entity/Illustration.php b/src/CoreBundle/Entity/Illustration.php new file mode 100644 index 0000000000..67d1c13943 --- /dev/null +++ b/src/CoreBundle/Entity/Illustration.php @@ -0,0 +1,102 @@ +id; + } + + /** + * @param int $id + * + * @return Illustration + */ + public function setId(int $id): Illustration + { + $this->id = $id; + + return $this; + } + + /** + * @return string + */ + public function getName(): string + { + return $this->name; + } + + /** + * @param string $name + * + * @return Illustration + */ + public function setName(string $name): Illustration + { + $this->name = $name; + + return $this; + } + + /** + * Resource identifier. + * + * @return int + */ + public function getResourceIdentifier(): int + { + return $this->getId(); + } + + /** + * @return string + */ + public function getResourceName(): string + { + return $this->getName(); + } + + /** + * @return string + */ + public function getToolName(): string + { + return 'Illustration'; + } +} diff --git a/src/CoreBundle/Entity/Resource/AbstractResource.php b/src/CoreBundle/Entity/Resource/AbstractResource.php index f14d4d4dd3..55502bb1ca 100644 --- a/src/CoreBundle/Entity/Resource/AbstractResource.php +++ b/src/CoreBundle/Entity/Resource/AbstractResource.php @@ -24,15 +24,6 @@ abstract class AbstractResource implements ResourceInterface */ abstract public function getResourceName(): string; - /** - * ORM\PreUpdate() - * - * @param LifecycleEventArgs $args - */ - /*public function preUpdate(LifecycleEventArgs $args): void - { - }*/ - /** * @ORM\PostUpdate() * diff --git a/src/CoreBundle/Framework/Container.php b/src/CoreBundle/Framework/Container.php index 07a4863baa..ec899f78c1 100644 --- a/src/CoreBundle/Framework/Container.php +++ b/src/CoreBundle/Framework/Container.php @@ -191,16 +191,6 @@ class Container return self::$container->get('chamilo_core.html_editor'); } - /** - * @deprecated - * - * @return \Symfony\Bundle\FrameworkBundle\Routing\Router - */ - public static function getUrlGenerator() - { - return self::$container->get('router.default'); - } - /** * @return object|Request */ diff --git a/src/CoreBundle/Repository/ResourceRepository.php b/src/CoreBundle/Repository/ResourceRepository.php index 44674caea9..ad458b6ec5 100644 --- a/src/CoreBundle/Repository/ResourceRepository.php +++ b/src/CoreBundle/Repository/ResourceRepository.php @@ -5,6 +5,7 @@ namespace Chamilo\CoreBundle\Repository; use Chamilo\CoreBundle\Entity\Course; use Chamilo\CoreBundle\Entity\Resource\AbstractResource; +use Chamilo\CoreBundle\Entity\Resource\ResourceFile; use Chamilo\CoreBundle\Entity\Resource\ResourceLink; use Chamilo\CoreBundle\Entity\Resource\ResourceNode; use Chamilo\CoreBundle\Entity\Resource\ResourceRight; @@ -14,11 +15,13 @@ use Chamilo\CoreBundle\Entity\Usergroup; use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter; use Chamilo\CourseBundle\Entity\CGroupInfo; use Chamilo\UserBundle\Entity\User; +use Doctrine\Common\Collections\Criteria; use Doctrine\ORM\EntityManager; use Doctrine\ORM\Query\Expr\Join; use League\Flysystem\FilesystemInterface; use League\Flysystem\MountManager; use Sylius\Bundle\ResourceBundle\Doctrine\ORM\EntityRepository; +use Symfony\Component\HttpFoundation\File\UploadedFile; /** * Class ResourceRepository. @@ -57,8 +60,8 @@ class ResourceRepository extends EntityRepository public function __construct(EntityManager $entityManager, MountManager $mountManager, string $className) { $this->repository = $entityManager->getRepository($className); + // Flysystem mount name is saved in config/packages/oneup_flysystem.yaml $this->fs = $mountManager->getFilesystem('resources_fs'); - $this->entityManager = $entityManager; } /** @@ -108,6 +111,58 @@ class ResourceRepository extends EntityRepository return $this->getRepository()->findOneBy($criteria, $orderBy); } + /** + * @param AbstractResource $resource + * + * @return ResourceNode|mixed + */ + public function getIllustration(AbstractResource $resource) + { + $node = $resource->getResourceNode(); + // @todo also filter by the resource type = Illustration + $criteria = Criteria::create()->where( + Criteria::expr()->eq('name', 'course_picture') + ); + + $illustration = $node->getChildren()->matching($criteria)->first(); + + return $illustration; + + /** @var ResourceNode $illustration */ + //$illustration = $this->getRepository()->findOneBy(['parent' => $node, 'name' => 'course_picture']); + var_dump($illustration); + } + + /** + * @param AbstractResource $resource + * @param UploadedFile $file + * + * @return ResourceFile + */ + public function addFileToResource(AbstractResource $resource, UploadedFile $file) + { + $resourceNode = $resource->getResourceNode(); + + if (!$resourceNode) { + return false; + } + + $resourceFile = $resourceNode->getResourceFile(); + if ($resourceFile === null) { + $resourceFile = new ResourceFile(); + } + + $em = $this->getEntityManager(); + + $resourceFile->setFile($file); + $resourceFile->setName($resource->getResourceName()); + $em->persist($resourceFile); + $resourceNode->setResourceFile($resourceFile); + $em->persist($resourceNode); + $em->flush(); + + return $resourceFile; + } /** diff --git a/src/CoreBundle/Resources/config/tools.yml b/src/CoreBundle/Resources/config/tools.yml index 7ef98a04cc..b319bf4de9 100644 --- a/src/CoreBundle/Resources/config/tools.yml +++ b/src/CoreBundle/Resources/config/tools.yml @@ -18,7 +18,7 @@ services: - 'admin' - 'admin.png' - '' - - [AccessUrl, Course] + - [AccessUrl, Course, Illustration] - 1 tags: - {name: chamilo_core.tool} diff --git a/src/CourseBundle/Controller/Home/HomeController.php b/src/CourseBundle/Controller/Home/HomeController.php index 80138b4847..2ebc760a37 100644 --- a/src/CourseBundle/Controller/Home/HomeController.php +++ b/src/CourseBundle/Controller/Home/HomeController.php @@ -81,17 +81,8 @@ class HomeController extends ToolBaseController } } - $homeView = api_get_setting('course.homepage_view'); - - if ($homeView == 'activity' || $homeView == 'activity_big') { - $blocks = $this->renderActivityView(); - } elseif ($homeView == '2column') { - $result = $this->render2ColumnView(); - } elseif ($homeView == '3column') { - $result = $this->render3ColumnView(); - } elseif ($homeView == 'vertical_activity') { - $result = $this->renderVerticalActivityView(); - } + //$homeView = api_get_setting('course.homepage_view'); + $blocks = $this->renderActivityView(); $toolList = $result['tool_list']; @@ -120,35 +111,6 @@ class HomeController extends ToolBaseController ); } - /** - * @param string $courseCode - * @param string $fileName - * - * @return \Symfony\Component\HttpFoundation\BinaryFileResponse - */ - public function getFileAction($courseCode, $fileName) - { - $courseInfo = api_get_course_info($courseCode); - $sessionId = $this->getRequest()->get('id_session'); - - $docId = \DocumentManager::get_document_id($courseInfo, "/".$fileName); - - $filePath = null; - - if ($docId) { - $isVisible = \DocumentManager::is_visible_by_id($docId, $courseInfo, $sessionId, api_get_user_id()); - $documentData = \DocumentManager::get_document_data_by_id($docId, $courseCode); - $filePath = $documentData['absolute_path']; - \Event::event_download($filePath); - } - - if (!api_is_allowed_to_edit() && !$isVisible) { - $this->abort(500); - } - - return $this->sendFile($filePath); - } - /** * @Route("/show/{iconId}", methods={"GET"}) * @@ -585,18 +547,6 @@ class HomeController extends ToolBaseController return $blocks; } - private function render2ColumnView() - { - } - - private function render3ColumnView() - { - } - - private function renderVerticalActivityView() - { - } - /** * @return array */ diff --git a/src/CourseBundle/Resources/config/routing.yml b/src/CourseBundle/Resources/config/routing.yml index cafba432a1..267fa3d545 100644 --- a/src/CourseBundle/Resources/config/routing.yml +++ b/src/CourseBundle/Resources/config/routing.yml @@ -14,6 +14,13 @@ core_tool_document: requirements: file: .+ # allow "/" in {file} +core_tool_resource: + path: /resources/{id} + defaults: + _controller: Chamilo\CoreBundle\Controller\ResourceController::getResourceFileAction + requirements: + file: .+ # allow "/" in {file} + chamilo_course_tool_intro_create: path: /courses/{course}/introduction/{tool}/create/ methods: [GET, POST]