Course category: Add tests, fix CRUD course category asset + add migration

pull/3965/head
Julio 4 years ago
parent b091efd370
commit 4cd9798949
  1. 8
      public/main/admin/course_category.php
  2. 51
      public/main/inc/lib/course_category.lib.php
  3. 30
      src/CoreBundle/Entity/CourseCategory.php
  4. 7
      src/CoreBundle/EventListener/AssetListener.php
  5. 61
      src/CoreBundle/Migrations/Schema/V200/Version20191101132000.php
  6. 11
      src/CoreBundle/Repository/CourseCategoryRepository.php
  7. 141
      tests/CoreBundle/Repository/CourseCategoryRepositoryTest.php

@ -92,11 +92,11 @@ switch ($action) {
// Delete Picture Category
$deletePicture = $_POST['delete_picture'] ?? '';
var_dump($deletePicture);
if ($deletePicture) {
CourseCategory::deleteImage($categoryEntity);
if ($deletePicture && $categoryEntity) {
$categoryRepo->deleteAsset($categoryEntity);
}
exit;
if (isset($_FILES['image']) && $categoryEntity) {
$crop = $_POST['picture_crop_result'] ?? '';
CourseCategory::saveImage($categoryEntity, $_FILES['image'], $crop);

@ -203,27 +203,15 @@ class CourseCategory
Database::query($sql);
}
public static function delete($categoryId): bool
public static function edit($categoryId, $name, $canHaveCourses, $code, $description): ?CourseCategoryEntity
{
$repo = Container::getCourseCategoryRepository();
$category = $repo->find($categoryId);
if (null === $category) {
return false;
return null;
}
$repo->delete($category);
return true;
}
public static function edit($categoryId, $name, $canHaveCourses, $code, $description): CourseCategoryEntity
{
$name = trim(Database::escape_string($name));
$canHaveCourses = Database::escape_string($canHaveCourses);
$repo = Container::getCourseCategoryRepository();
$category = $repo->find($categoryId);
$name = trim($name);
$category
->setCode($name)
->setName($name)
@ -837,26 +825,6 @@ class CourseCategory
return $nameTools;
}
public static function deleteImage(CourseCategoryEntity $category)
{
$assetId = $category->getImage();
if (empty($assetId)) {
return false;
}
$assetRepo = Container::getAssetRepository();
/** @var Asset $asset */
$asset = $assetRepo->find($assetId);
if (null !== $asset) {
$category->setImage('');
$assetRepo->delete($asset);
$repo = Container::getCourseCategoryRepository();
$repo->save($category);
}
return true;
}
/**
* Save image for a course category.
*
@ -865,19 +833,18 @@ class CourseCategory
public static function saveImage(CourseCategoryEntity $category, $fileData, $crop = '')
{
if (isset($fileData['tmp_name']) && !empty($fileData['tmp_name'])) {
self::deleteImage($category);
$repo = Container::getCourseCategoryRepository();
$repo->deleteAsset($category);
$repo = Container::getAssetRepository();
$asset = new Asset();
$asset
$assetRepo = Container::getAssetRepository();
$asset = (new Asset())
->setCategory(Asset::COURSE_CATEGORY)
->setTitle($fileData['name'])
->setCrop($crop)
;
$asset = $repo->createFromRequest($asset, $fileData);
$asset = $assetRepo->createFromRequest($asset, $fileData);
$category->setImage($asset->getId());
$repo = Container::getCourseCategoryRepository();
$category->setAsset($asset);
$repo->save($category);
}
}

@ -57,17 +57,17 @@ class CourseCategory
protected Collection $children;
/**
* @Assert\NotBlank()
* @Groups({"course_category:read", "course_category:write", "course:read"})
* @ORM\Column(name="name", type="text", nullable=false)
*/
#[Assert\NotBlank]
protected string $name;
/**
* @Assert\NotBlank()
* @Groups({"course_category:read", "course_category:write", "course:read"})
* @ORM\Column(name="code", type="string", length=40, nullable=false)
*/
#[Assert\NotBlank]
protected string $code;
/**
@ -97,9 +97,10 @@ class CourseCategory
protected ?string $authCatChild = null;
/**
* @ORM\Column(name="image", type="string", length=255, nullable=true)
* @ORM\ManyToOne(targetEntity="Chamilo\CoreBundle\Entity\Asset", inversedBy="courseCategories", cascade={"remove"} )
* @ORM\JoinColumn(name="asset_id", referencedColumnName="id", onDelete="SET NULL")
*/
protected ?string $image = null;
protected ?Asset $asset = null;
/**
* @Groups({"course_category:read", "course_category:write"})
@ -265,26 +266,31 @@ class CourseCategory
return $this->authCatChild;
}
public function getImage(): ?string
public function getDescription(): ?string
{
return $this->image;
return $this->description;
}
public function setImage(string $image): self
public function setDescription(string $description): self
{
$this->image = $image;
$this->description = $description;
return $this;
}
public function getDescription(): ?string
public function getAsset(): ?Asset
{
return $this->description;
return $this->asset;
}
public function setDescription(string $description): self
public function hasAsset(): bool
{
$this->description = $description;
return null !== $this->asset;
}
public function setAsset(?Asset $asset): self
{
$this->asset = $asset;
return $this;
}

@ -25,13 +25,14 @@ class AssetListener
$asset = $event->getObject();
if ($asset instanceof Asset) {
$mapping = $event->getMapping();
$folder = $mapping->getFile($asset)->getFilename();
$filePath = $asset->getCategory().'/'.$asset->getFile()->getFilename();
$this->assetRepository->getFileSystem()->deleteDirectory($filePath);
// Deletes scorm folder: example: assets/scorm/myABC .
if (!empty($folder) && Asset::SCORM === $asset->getCategory()) {
/*if (!empty($folder) && Asset::SCORM === $asset->getCategory()) {
$folder = Asset::SCORM.'/'.$folder;
$this->assetRepository->getFileSystem()->deleteDirectory($folder);
}
}*/
}
}
}

@ -6,8 +6,13 @@ declare(strict_types=1);
namespace Chamilo\CoreBundle\Migrations\Schema\V200;
use Chamilo\CoreBundle\Entity\Asset;
use Chamilo\CoreBundle\Entity\CourseCategory;
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo;
use Chamilo\CoreBundle\Repository\CourseCategoryRepository;
use Chamilo\Kernel;
use Doctrine\DBAL\Schema\Schema;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class Version20191101132000 extends AbstractMigrationChamilo
{
@ -81,8 +86,12 @@ class Version20191101132000 extends AbstractMigrationChamilo
if (!$table->hasIndex('course_rel_user_c_id_user_id')) {
$this->addSql('CREATE INDEX course_rel_user_c_id_user_id ON course_rel_user (id, c_id, user_id)');
}
$table = $schema->getTable('course_category');
//$this->addSql('ALTER TABLE course DROP category_code');
$connection = $this->getEntityManager()->getConnection();
$em = $this->getEntityManager();
$connection = $em->getConnection();
$sql = 'SELECT * FROM course_category';
$result = $connection->executeQuery($sql);
$all = $result->fetchAllAssociative();
@ -102,15 +111,57 @@ class Version20191101132000 extends AbstractMigrationChamilo
$this->addSql('ALTER TABLE course_category CHANGE parent_id parent_id INT DEFAULT NULL;');
$table = $schema->getTable('course_category');
if (false === $table->hasForeignKey('FK_AFF87497727ACA70')) {
$this->addSql(
'ALTER TABLE course_category ADD CONSTRAINT FK_AFF87497727ACA70 FOREIGN KEY (parent_id) REFERENCES course_category (id) ON DELETE CASCADE'
'ALTER TABLE course_category ADD CONSTRAINT FK_AFF87497727ACA70 FOREIGN KEY (parent_id) REFERENCES course_category (id) ON DELETE SET NULL '
);
}
if (!$table->hasColumn('image')) {
$this->addSql('ALTER TABLE course_category ADD image VARCHAR(255) DEFAULT NULL');
if (!$table->hasColumn('asset_id')) {
$this->addSql('ALTER TABLE course_category ADD asset_id INT DEFAULT NULL');
$this->addSql('ALTER TABLE course_category ADD CONSTRAINT FK_AFF874975DA1941 FOREIGN KEY (asset_id) REFERENCES asset (id)');
$this->addSql('CREATE INDEX IDX_AFF874975DA1941 ON course_category (asset_id);');
}
$container = $this->getContainer();
/** @var Kernel $kernel */
$kernel = $container->get('kernel');
$rootPath = $kernel->getProjectDir();
$repo = $container->get(CourseCategoryRepository::class);
if ($table->hasColumn('image')) {
foreach ($all as $category) {
if (!empty($category['image'])) {
/** @var CourseCategory $categoryEntity */
$categoryEntity = $repo->find($category['id']);
if ($categoryEntity->hasAsset()) {
continue;
}
$filePath = $rootPath.'/app/upload/course_category/'.$category['image'];
if ($this->fileExists($filePath)) {
$fileName = basename($filePath);
$mimeType = mime_content_type($filePath);
$file = new UploadedFile($filePath, $fileName, $mimeType, null, true);
$asset = (new Asset())
->setCategory(Asset::COURSE_CATEGORY)
->setTitle($fileName)
->setFile($file)
;
$em->persist($asset);
$em->flush();
$categoryEntity->setAsset($asset);
$em->persist($categoryEntity);
$em->flush();
}
}
}
}
if (!$table->hasColumn('description')) {
$this->addSql('ALTER TABLE course_category ADD description LONGTEXT DEFAULT NULL');
}

@ -135,10 +135,21 @@ class CourseCategoryRepository extends ServiceEntityRepository
$em->flush();
}
public function deleteAsset(CourseCategory $category): void
{
$em = $this->getEntityManager();
if ($category->hasAsset()) {
$asset = $category->getAsset();
$em->remove($asset);
$em->flush();
}
}
public function delete(CourseCategory $category): void
{
$em = $this->getEntityManager();
$em->remove($category);
$this->deleteAsset($category);
$em->flush();
}

@ -6,10 +6,13 @@ declare(strict_types=1);
namespace Chamilo\Tests\CoreBundle\Repository;
use Chamilo\CoreBundle\Entity\Asset;
use Chamilo\CoreBundle\Entity\CourseCategory;
use Chamilo\CoreBundle\Repository\AssetRepository;
use Chamilo\CoreBundle\Repository\CourseCategoryRepository;
use Chamilo\Tests\AbstractApiTest;
use Chamilo\Tests\ChamiloTestTrait;
use Symfony\Component\HttpFoundation\Response;
class CourseCategoryRepositoryTest extends AbstractApiTest
{
@ -21,6 +24,7 @@ class CourseCategoryRepositoryTest extends AbstractApiTest
$em = $this->getManager();
$repo = self::getContainer()->get(CourseCategoryRepository::class);
$defaultCount = $repo->count([]);
$item = (new CourseCategory())
->setCode('Course cat')
@ -32,6 +36,141 @@ class CourseCategoryRepositoryTest extends AbstractApiTest
// On a fresh installation there are already 3 categories.
// See the src/CoreBundle/DataFixtures/CourseCategoryFixtures.php
$this->assertSame(4, $repo->count([]));
$this->assertSame($defaultCount + 1, $repo->count([]));
}
public function testCreateWithAsset(): void
{
self::bootKernel();
$em = $this->getManager();
/** @var CourseCategoryRepository $repoCourseCategory */
$repoCourseCategory = self::getContainer()->get(CourseCategoryRepository::class);
$defaultCount = $repoCourseCategory->count([]);
/** @var AssetRepository $assetRepo */
$assetRepo = self::getContainer()->get(AssetRepository::class);
$file = $this->getUploadedFile();
// Create asset.
$asset = (new Asset())
->setTitle('file')
->setCategory(Asset::COURSE_CATEGORY)
->setFile($file)
;
$em->persist($asset);
$item = (new CourseCategory())
->setCode('cat')
->setName('cat')
->setAsset($asset)
;
$this->assertHasNoEntityViolations($item);
$repoCourseCategory->save($item);
$this->assertSame($defaultCount + 1, $repoCourseCategory->count([]));
$this->assertTrue($item->hasAsset());
$this->assertSame(1, $assetRepo->count([]));
$repoCourseCategory->delete($item);
$this->assertSame($defaultCount, $repoCourseCategory->count([]));
}
public function testDelete(): void
{
self::bootKernel();
$em = $this->getManager();
/** @var CourseCategoryRepository $repoCourseCategory */
$repoCourseCategory = self::getContainer()->get(CourseCategoryRepository::class);
$defaultCount = $repoCourseCategory->count([]);
/** @var AssetRepository $assetRepo */
$assetRepo = self::getContainer()->get(AssetRepository::class);
$file = $this->getUploadedFile();
// Create asset.
$asset = (new Asset())
->setTitle('file')
->setCategory(Asset::COURSE_CATEGORY)
->setFile($file)
;
$em->persist($asset);
$courseCategory = (new CourseCategory())
->setCode('cat')
->setName('cat')
->setAsset($asset)
;
$repoCourseCategory->save($courseCategory);
$url = $assetRepo->getAssetUrl($asset);
$this->assertNotEmpty($url);
$content = $assetRepo->getAssetContent($asset);
$this->assertNotEmpty($content);
$client = static::createClient();
$client->request('GET', $url);
$this->assertSame(Response::HTTP_OK, $client->getResponse()->getStatusCode());
$this->assertSame(1, $assetRepo->count([]));
$em->clear();
$courseCategory = $repoCourseCategory->find($courseCategory->getId());
$repoCourseCategory->delete($courseCategory);
$this->assertSame(0, $assetRepo->count([]));
$this->assertSame($defaultCount, $repoCourseCategory->count([]));
$content = $assetRepo->getAssetContent($asset);
$this->assertEmpty($content);
}
public function testEditAndDeleteAsset(): void
{
self::bootKernel();
$em = $this->getManager();
/** @var CourseCategoryRepository $repoCourseCategory */
$repoCourseCategory = self::getContainer()->get(CourseCategoryRepository::class);
$defaultCount = $repoCourseCategory->count([]);
/** @var AssetRepository $assetRepo */
$assetRepo = self::getContainer()->get(AssetRepository::class);
$file = $this->getUploadedFile();
// Create asset.
$asset = (new Asset())
->setTitle('file')
->setCategory(Asset::COURSE_CATEGORY)
->setFile($file)
;
$em->persist($asset);
$courseCategory = (new CourseCategory())
->setCode('cat')
->setName('cat')
->setAsset($asset)
;
$repoCourseCategory->save($courseCategory);
$this->assertSame($defaultCount + 1, $repoCourseCategory->count([]));
$this->assertSame(1, $assetRepo->count([]));
$courseCategory = $repoCourseCategory->find($courseCategory->getId());
$repoCourseCategory->deleteAsset($courseCategory);
$this->assertSame(0, $assetRepo->count([]));
$this->assertSame($defaultCount + 1, $repoCourseCategory->count([]));
}
}

Loading…
Cancel
Save