Fix folder/file/html file document creation.

pull/3346/head
Julio Montoya 6 years ago
parent 182fa29275
commit 1a8c2310fa
  1. 21
      assets/vue/mixins/UpdateMixin.js
  2. 9
      assets/vue/router/documents.js
  3. 4
      assets/vue/services/api.js
  4. 3
      assets/vue/store/modules/crud.js
  5. 1
      assets/vue/utils/fetch.js
  6. 2
      assets/vue/views/documents/CreateFile.vue
  7. 9
      assets/vue/views/documents/List.vue
  8. 1
      assets/vue/views/documents/Update.vue
  9. 88
      src/CoreBundle/Controller/CreateResourceNodeFileAction.php
  10. 3
      src/CoreBundle/Controller/ResourceController.php
  11. 9
      src/CoreBundle/Entity/AbstractResource.php
  12. 38
      src/CoreBundle/Entity/ResourceFile.php
  13. 14
      src/CoreBundle/EventSubscriber/ResolveResourceFileContentUrlSubscriber.php
  14. 57
      src/CoreBundle/Repository/ResourceRepository.php
  15. 40
      src/CourseBundle/Entity/CDocument.php

@ -1,5 +1,6 @@
import NotificationMixin from './NotificationMixin';
import { formatDateTime } from '../utils/dates';
import isEmpty from "lodash/isEmpty";
export default {
mixins: [NotificationMixin],
@ -9,14 +10,30 @@ export default {
};
},
created() {
this.retrieve(decodeURIComponent(this.$route.params.id));
// Changed
let id = this.$route.params.id;
if (isEmpty(id)) {
id = this.$route.query.id;
}
this.retrieve(decodeURIComponent(id));
// default
//this.retrieve(decodeURIComponent(this.$route.params.id));
},
beforeDestroy() {
this.reset();
},
computed: {
retrieved() {
return this.find(decodeURIComponent(this.$route.params.id));
let id = this.$route.params.id;
if (isEmpty(id)) {
id = this.$route.query.id;
}
let item = this.find(decodeURIComponent(id));
return item;
//return this.find(decodeURIComponent(this.$route.params.id));
}
},
methods: {

@ -27,9 +27,16 @@ export default {
},
{
name: 'DocumentsUpdate',
path: ':id/edit',
//path: ':id/edit',
path: 'edit',
component: () => import('../views/documents/Update')
},
{
name: 'DocumentsUpdateFile',
//path: ':id/edit',
path: 'edit_file',
component: () => import('../views/documents/UpdateFile')
},
{
name: 'DocumentsShow',
//path: ':id',

@ -16,9 +16,11 @@ export default function makeService(endpoint) {
return fetch(item['@id'], { method: 'DELETE' });
},
update(payload) {
console.log(payload);
return fetch(payload['@id'], {
method: 'PUT',
body: JSON.stringify(payload)
body: payload
//body: JSON.stringify(payload)
});
}
};

@ -155,7 +155,6 @@ export default function makeCrudModule({
commit(ACTIONS.TOGGLE_LOADING);
commit(ACTIONS.ADD_RESOURCE_NODE, normalizeRelations(item));
return item;
})
.catch(e => handleError(commit, e));
@ -195,7 +194,7 @@ export default function makeCrudModule({
list: (state, getters) => {
return state.allIds.map(id => getters.find(id));
},
getResourceNode: (state, getters) => {
getResourceNode: (state) => {
return state.resourceNode;
},
},

@ -38,7 +38,6 @@ export default function(id, options = {}) {
const entryPoint = ENTRYPOINT + (ENTRYPOINT.endsWith('/') ? '' : '/');
let formData = new FormData();
//console.log(options.body);
if (options.body) {
Object.keys(options.body).forEach(function (key) {
// key: the name of the object key

@ -36,7 +36,7 @@ export default {
filetype: 'file',
parentResourceNodeId: null,
resourceLinkList: null,
content: null
contentFile: null
},
};
},

@ -33,9 +33,6 @@
>
<template slot="item.resourceNode.title" slot-scope="{ item }">
<div v-if="item['resourceNode']['resourceFile']">
<!-- <a @click="showHandler(item)" >-->
<!-- {{ item['contentUrl'] }}-->
<!-- </a>-->
<a data-fancybox="gallery"
:href=" item['contentUrl'] ">
<v-icon left color="primary">mdi-file</v-icon> {{ item['resourceNode']['title'] }}
@ -47,9 +44,7 @@
</a>
</div>
</template>
<!-- <template slot="item.resourceNode" slot-scope="{ item }">-->
<!-- {{ item['@id'] }}-->
<!-- </template>-->
<template slot="item.resourceNode.updatedAt" slot-scope="{ item }">
{{ item.resourceNode.updatedAt | moment("from", "now") }}
</template>
@ -76,8 +71,6 @@ import ActionCell from '../../components/ActionCell';
import DocumentsFilterForm from '../../components/documents/Filter';
import DataFilter from '../../components/DataFilter';
import Toolbar from '../../components/Toolbar';
import {ACTIONS} from "../../store/modules/crud";
import Vue from "vue";
export default {
name: 'DocumentsList',

@ -44,7 +44,6 @@ export default {
violations: 'violations'
}),
...mapGetters('documents', ['find'])
},
methods: {

@ -5,48 +5,72 @@
namespace Chamilo\CoreBundle\Controller;
use Chamilo\CourseBundle\Entity\CDocument;
use Chamilo\CourseBundle\Repository\CDocumentRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
class CreateResourceNodeFileAction
{
public function __invoke(Request $request): CDocument
public function __invoke(Request $request, CDocumentRepository $repo): CDocument
{
$document = new CDocument();
$title = $request->get('title');
$comment = $request->get('comment');
if ('file' === $request->get('filetype')) {
$fileParsed = false;
// File upload
if ($request->files->count() > 0) {
/** @var UploadedFile $uploadedFile */
$uploadedFile = $request->files->get('uploadFile');
if (!$uploadedFile) {
throw new BadRequestHttpException('"uploadFile" is required');
if ($request->request->has('filetype')) {
$document->setFiletype($request->get('filetype'));
}
$content = '';
if ($request->request->has('contentFile')) {
$document->setFiletype('file');
$content = $request->request->get('contentFile');
}
$nodeId = (int) $request->get('parentResourceNodeId');
$document->setParentResourceNode($nodeId);
switch ($document->getFiletype()) {
case 'file':
$fileParsed = false;
// File upload
if ($request->files->count() > 0) {
/** @var UploadedFile $uploadedFile */
$uploadedFile = $request->files->get('uploadFile');
if (!$uploadedFile) {
throw new BadRequestHttpException('"uploadFile" is required');
}
$title = $uploadedFile->getClientOriginalName();
$document->setTitle($title);
$document->setUploadFile($uploadedFile);
$fileParsed = true;
}
$title = $uploadedFile->getClientOriginalName();
$document->setUploadFile($uploadedFile);
$fileParsed = true;
}
// Get data in content and create a HTML file
if (false === $fileParsed && $request->request->has('content')) {
$content = $request->request->get('content');
$title .= '.html';
$handle = tmpfile();
fwrite($handle, $content);
$meta = stream_get_meta_data($handle);
$file = new UploadedFile($meta['uri'], $title, 'text/html', null, true);
$document->setUploadFile($file);
$fileParsed = true;
}
// Get data in content and create a HTML file
if (false === $fileParsed && $content) {
$document->setTitle($title);
if (false === $fileParsed) {
throw new \InvalidArgumentException(
'filetype was set to "file" but not upload found'
);
}
$title .= '.html';
$handle = tmpfile();
fwrite($handle, $content);
$meta = stream_get_meta_data($handle);
$file = new UploadedFile($meta['uri'], $title, 'text/html', null, true);
$document->setUploadFile($file);
$fileParsed = true;
}
if (false === $fileParsed) {
throw new \InvalidArgumentException(
'filetype was set to "file" but not upload found'
);
}
break;
case 'folder':
$document->setTitle($title);
break;
}
if ($request->request->has('resourceLinkList')) {
@ -64,11 +88,7 @@ class CreateResourceNodeFileAction
$document->setResourceLinkList($links);
}
$document->setTitle($title);
$document->setComment($request->get('comment'));
$nodeId = (int) $request->get('parentResourceNodeId');
$document->setParentResourceNode($nodeId);
$document->setComment($comment);
return $document;
}

@ -942,10 +942,7 @@ class ResourceController extends AbstractResourceController implements CourseCon
/** @var ResourceNode $node */
foreach ($children as $node) {
//$resourceFile = $node->getResourceFile();
//$systemName = $resourceFile->getFile()->getPathname();
$stream = $repo->getResourceNodeFileStream($node);
//error_log($node->getPathForDisplay());
$fileToDisplay = str_replace($rootNodePath, '', $node->getPathForDisplay());
$zip->addFileFromStream($fileToDisplay, $stream);
}

@ -26,10 +26,17 @@ abstract class AbstractResource
*/
public $contentUrl;
/**
* @var string|null
*
* @Groups({"resource_file:read", "resource_node:read", "document:read", "document:write", "media_object_read"})
*/
public $contentFile;
/**
* @Assert\Valid()
* @ApiSubresource()
* @Groups({"resource_node:read", "resource_node:write"})
* @Groups({"resource_node:read", "resource_node:write", "document:write" })
* @ORM\OneToOne(
* targetEntity="Chamilo\CoreBundle\Entity\ResourceNode",
* cascade={"persist", "remove"},

@ -78,6 +78,7 @@ class ResourceFile
public $contentUrl;
/**
* @Groups({"resource_file:read", "resource_node:read", "document:read"})
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue
@ -104,7 +105,7 @@ class ResourceFile
/**
* @var string
*
* @Groups({"resource_file:read", "resource_node:read", "document:read"})
* @ORM\Column(type="text", nullable=true)
*/
protected $originalName;
@ -128,7 +129,7 @@ class ResourceFile
/**
* @var File
*
* @Assert\NotNull(groups={"media_object_create", "document:write"})
* @Assert\NotNull()
* @Vich\UploadableField(
* mapping="resources",
* fileNameProperty="name",
@ -172,7 +173,7 @@ class ResourceFile
public function __toString(): string
{
return (string) $this->getOriginalName();
return $this->getOriginalName();
}
/**
@ -228,35 +229,6 @@ class ResourceFile
return $this;
}
/*public function getCopyright(): string
{
return (string) $this->copyright;
}*/
/*public function getContentType(): string
{
return (string) $this->contentType;
}
public function setContentType(string $contentType): self
{
$this->contentType = $contentType;
return $this;
}*/
/*public function getExtension(): string
{
return $this->extension;
}
public function setExtension(string $extension): self
{
$this->extension = $extension;
return $this;
}*/
public function getResourceNode(): ResourceNode
{
return $this->resourceNode;
@ -328,7 +300,7 @@ class ResourceFile
public function getOriginalName(): string
{
return $this->originalName;
return (string) $this->originalName;
}
/**

@ -7,7 +7,7 @@ namespace Chamilo\CoreBundle\EventSubscriber;
use ApiPlatform\Core\EventListener\EventPriorities;
use ApiPlatform\Core\Util\RequestAttributesExtractor;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\ResourceFile;
use Chamilo\CoreBundle\Repository\ResourceNodeRepository;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Event\ViewEvent;
@ -17,10 +17,12 @@ use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
class ResolveResourceFileContentUrlSubscriber implements EventSubscriberInterface
{
private $generator;
private $nodeRepository;
public function __construct(UrlGeneratorInterface $generator)
public function __construct(UrlGeneratorInterface $generator, ResourceNodeRepository $nodeRepository)
{
$this->generator = $generator;
$this->nodeRepository = $nodeRepository;
}
public static function getSubscribedEvents(): array
@ -51,7 +53,9 @@ class ResolveResourceFileContentUrlSubscriber implements EventSubscriberInterfac
if (!is_iterable($mediaObjects)) {
$mediaObjects = [$mediaObjects];
}
//error_log($request->get('getFile'));
//$getFile = $request->get('getFile');
$getFile = true;
foreach ($mediaObjects as $mediaObject) {
if (!$mediaObject instanceof AbstractResource) {
continue;
@ -64,6 +68,10 @@ class ResolveResourceFileContentUrlSubscriber implements EventSubscriberInterfac
];
$mediaObject->contentUrl = $this->generator->generate('chamilo_core_resource_view_file', $params);
if ($getFile && $mediaObject->getResourceNode()->hasResourceFile()) {
//$mediaObject->contentFile = $this->nodeRepository->getResourceNodeFileContent($mediaObject->getResourceNode());
}
}
}
}

@ -810,27 +810,27 @@ class ResourceRepository extends EntityRepository
*/
public function updateResourceFileContent(AbstractResource $resource, $content)
{
try {
$resourceNode = $resource->getResourceNode();
if ($resourceNode->hasResourceFile()) {
$resourceFile = $resourceNode->getResourceFile();
if ($resourceFile) {
$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
$this->getResourceNodeRepository()->getFileSystem()->update($fileName, $content);
//$size = $this->getResourceNodeRepository()->getSize($resourceNode);
if ($resource instanceof CDocument) {
//$resource->setSize($size);
}
$this->entityManager->persist($resource);
return true;
}
$resourceNode = $resource->getResourceNode();
if ($resourceNode->hasResourceFile()) {
$resourceFile = $resourceNode->getResourceFile();
if ($resourceFile) {
$title = $resource->getTitle();
$handle = tmpfile();
fwrite($handle, $content);
$meta = stream_get_meta_data($handle);
$file = new UploadedFile($meta['uri'], $title, 'text/html', null, true);
$resource->setUploadFile($file);
/*$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
$this->getResourceNodeRepository()->getFileSystem()->update($fileName, $content);
$resourceFile->setSize(strlen($content));*/
//$this->entityManager->persist($resource);
return true;
}
return false;
} catch (\Throwable $exception) {
}
return false;
}
/**
@ -856,6 +856,25 @@ class ResourceRepository extends EntityRepository
$this->setLinkVisibility($resource, ResourceLink::VISIBILITY_PENDING);
}
public function setResourceTitle(AbstractResource $resource, $title)
{
$resource->setTitle($title);
$resourceNode = $resource->getResourceNode();
$resourceNode->setTitle($title);
if ($resourceNode->hasResourceFile()) {
//$resourceFile = $resourceNode->getResourceFile();
//$resourceFile->setName($title);
/*$fileName = $this->getResourceNodeRepository()->getFilename($resourceFile);
error_log('$fileName');
error_log($fileName);
error_log($title);
$this->getResourceNodeRepository()->getFileSystem()->rename($fileName, $title);
$resourceFile->setName($title);
$resourceFile->setOriginalName($title);*/
}
}
public function createNodeForResource(ResourceInterface $resource, User $creator, ResourceNode $parentNode = null, UploadedFile $file = null): ResourceNode
{
$em = $this->getEntityManager();

@ -5,10 +5,12 @@
namespace Chamilo\CourseBundle\Entity;
use ApiPlatform\Core\Annotation\ApiFilter;
use ApiPlatform\Core\Serializer\Filter\PropertyFilter;
use ApiPlatform\Core\Annotation\ApiResource;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\OrderFilter;
use ApiPlatform\Core\Bridge\Doctrine\Orm\Filter\SearchFilter;
use Chamilo\CoreBundle\Controller\CreateResourceNodeFileAction;
use Chamilo\CoreBundle\Controller\UpdateResourceNodeFileAction;
use Chamilo\CoreBundle\Entity\AbstractResource;
use Chamilo\CoreBundle\Entity\Course;
use Chamilo\CoreBundle\Entity\ResourceInterface;
@ -17,6 +19,7 @@ use Chamilo\CoreBundle\Entity\Session;
use Chamilo\CourseBundle\Traits\ShowCourseResourcesInSessionTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
//* attributes={"security"="is_granted('ROLE_ADMIN')"},
/**
@ -24,6 +27,17 @@ use Symfony\Component\Serializer\Annotation\Groups;
* shortName="Documents",
* normalizationContext={"groups"={"document:read", "resource_node:read"}},
* denormalizationContext={"groups"={"document:write"}},
* itemOperations={
* "put" ={
* "controller"=UpdateResourceNodeFileAction::class,
* "deserialize"=false,
* "security"="is_granted('ROLE_USER')",
* "validation_groups"={"Default", "media_object_create", "document:write"},
* },
* "get",
* "delete"
* },
* collectionOperations={
* "post"={
* "controller"=CreateResourceNodeFileAction::class,
@ -47,7 +61,7 @@ use Symfony\Component\Serializer\Annotation\Groups;
* "comment"={
* "type"="string",
* },
* "content"={
* "contentFile"={
* "type"="string",
* },
* "uploadFile"={
@ -81,10 +95,11 @@ use Symfony\Component\Serializer\Annotation\Groups;
* }
* }
* },
* "get"
* "get",
* },
* )
* @ApiFilter(SearchFilter::class, properties={"title": "partial", "resourceNode.parent": "exact"})
* @ApiFilter(PropertyFilter::class)
* @ApiFilter(
* OrderFilter::class,
* properties={
@ -156,6 +171,7 @@ class CDocument extends AbstractResource implements ResourceInterface, ResourceT
/**
* @var string File type, it can be 'folder' or 'file'
* @Groups({"document:read", "document:write"})
* @Assert\Choice({"folder", "file"}, message="Choose a valid filetype.")
* @ORM\Column(name="filetype", type="string", length=10, nullable=false)
*/
protected $filetype;
@ -169,14 +185,12 @@ class CDocument extends AbstractResource implements ResourceInterface, ResourceT
/**
* @var bool
*
* @ORM\Column(name="readonly", type="boolean", nullable=false)
*/
protected $readonly;
/**
* @var bool
*
* @ORM\Column(name="template", type="boolean", nullable=false)
*/
protected $template;
@ -275,11 +289,9 @@ class CDocument extends AbstractResource implements ResourceInterface, ResourceT
/**
* Set title.
*
* @param string $title
*
* @return CDocument
*/
public function setTitle($title)
public function setTitle(string $title)
{
$this->title = $title;
@ -298,12 +310,8 @@ class CDocument extends AbstractResource implements ResourceInterface, ResourceT
/**
* Set filetype.
*
* @param string $filetype
*
* @return CDocument
*/
public function setFiletype($filetype)
public function setFiletype(string $filetype): self
{
$this->filetype = $filetype;
@ -425,14 +433,6 @@ class CDocument extends AbstractResource implements ResourceInterface, ResourceT
return $this;
}
/*public function postPersist(LifecycleEventArgs $args)
{
// Update id with iid value
$em = $args->getEntityManager();
$em->persist($this);
$em->flush();
}*/
/**
* Resource identifier.
*/

Loading…
Cancel
Save