Course: Add custom image support for course links in homepage tools - refs #2863
parent
c07fb75078
commit
abc0f7cf7d
@ -0,0 +1,126 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
/* For licensing terms, see /license.txt */ |
||||
|
||||
namespace Chamilo\CoreBundle\Controller\Api; |
||||
|
||||
use Chamilo\CoreBundle\Entity\Asset; |
||||
use Chamilo\CourseBundle\Entity\CLink; |
||||
use Doctrine\ORM\EntityManagerInterface; |
||||
use Symfony\Component\HttpFoundation\File\File; |
||||
use Symfony\Component\HttpFoundation\Request; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
|
||||
class CLinkImageController |
||||
{ |
||||
private EntityManagerInterface $entityManager; |
||||
|
||||
public function __construct(EntityManagerInterface $entityManager) |
||||
{ |
||||
$this->entityManager = $entityManager; |
||||
} |
||||
|
||||
public function __invoke(CLink $link, Request $request): Response |
||||
{ |
||||
$removeImage = $request->request->getBoolean('removeImage', false); |
||||
$file = $request->files->get('customImage'); |
||||
|
||||
if ($removeImage) { |
||||
if ($link->getCustomImage()) { |
||||
$this->entityManager->remove($link->getCustomImage()); |
||||
$link->setCustomImage(null); |
||||
$this->entityManager->persist($link); |
||||
$this->entityManager->flush(); |
||||
|
||||
if (!$file) { |
||||
return new Response('Image removed successfully', Response::HTTP_OK); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (!$file || !$file->isValid()) { |
||||
return new Response('Invalid or missing file', Response::HTTP_BAD_REQUEST); |
||||
} |
||||
|
||||
try { |
||||
$asset = new Asset(); |
||||
$asset->setFile($file) |
||||
->setCategory(Asset::LINK) |
||||
->setTitle($file->getClientOriginalName()); |
||||
|
||||
$this->entityManager->persist($asset); |
||||
$this->entityManager->flush(); |
||||
|
||||
$uploadedFilePath = $file->getPathname(); |
||||
|
||||
$croppedFilePath = $this->cropImage($uploadedFilePath); |
||||
|
||||
if (!file_exists($croppedFilePath)) { |
||||
@unlink($uploadedFilePath); |
||||
return new Response('Error creating cropped image', Response::HTTP_INTERNAL_SERVER_ERROR); |
||||
} |
||||
|
||||
$asset->setFile(new File($croppedFilePath)); |
||||
$this->entityManager->persist($asset); |
||||
$this->entityManager->flush(); |
||||
|
||||
$link->setCustomImage($asset); |
||||
$this->entityManager->persist($link); |
||||
$this->entityManager->flush(); |
||||
|
||||
return new Response('Image uploaded and linked successfully', Response::HTTP_OK); |
||||
|
||||
} catch (\Exception $e) { |
||||
return new Response('Error processing image: ' . $e->getMessage(), Response::HTTP_INTERNAL_SERVER_ERROR); |
||||
} |
||||
} |
||||
|
||||
private function cropImage(string $filePath): string |
||||
{ |
||||
[$originalWidth, $originalHeight, $imageType] = getimagesize($filePath); |
||||
|
||||
if (!$originalWidth || !$originalHeight) { |
||||
throw new \RuntimeException('Invalid image file'); |
||||
} |
||||
|
||||
switch ($imageType) { |
||||
case IMAGETYPE_JPEG: |
||||
$sourceImage = imagecreatefromjpeg($filePath); |
||||
break; |
||||
case IMAGETYPE_PNG: |
||||
$sourceImage = imagecreatefrompng($filePath); |
||||
break; |
||||
case IMAGETYPE_GIF: |
||||
$sourceImage = imagecreatefromgif($filePath); |
||||
break; |
||||
default: |
||||
throw new \RuntimeException('Unsupported image type'); |
||||
} |
||||
|
||||
$croppedImage = imagecreatetruecolor(120, 120); |
||||
|
||||
$cropWidth = min($originalWidth, $originalHeight); |
||||
$cropHeight = $cropWidth; |
||||
$srcX = (int) (($originalWidth - $cropWidth) / 2); |
||||
$srcY = (int) (($originalHeight - $cropHeight) / 2); |
||||
|
||||
imagecopyresampled( |
||||
$croppedImage, |
||||
$sourceImage, |
||||
0, 0, |
||||
$srcX, $srcY, |
||||
$cropWidth, $cropHeight, |
||||
120, 120 |
||||
); |
||||
|
||||
$croppedFilePath = sys_get_temp_dir() . '/' . uniqid('cropped_', true) . '.png'; |
||||
imagepng($croppedImage, $croppedFilePath); |
||||
|
||||
imagedestroy($sourceImage); |
||||
imagedestroy($croppedImage); |
||||
|
||||
return $croppedFilePath; |
||||
} |
||||
} |
@ -0,0 +1,36 @@ |
||||
<?php |
||||
|
||||
declare(strict_types=1); |
||||
|
||||
namespace Chamilo\CoreBundle\Migrations\Schema\V200; |
||||
|
||||
use Chamilo\CoreBundle\Migrations\AbstractMigrationChamilo; |
||||
use Doctrine\DBAL\Schema\Schema; |
||||
|
||||
final class Version20250118000100 extends AbstractMigrationChamilo |
||||
{ |
||||
public function getDescription(): string |
||||
{ |
||||
return 'Add custom_image_id field to c_link table and set up the foreign key to asset table.'; |
||||
} |
||||
|
||||
public function up(Schema $schema): void |
||||
{ |
||||
// Add the new column and foreign key |
||||
$this->addSql(' |
||||
ALTER TABLE c_link |
||||
ADD custom_image_id BINARY(16) DEFAULT NULL COMMENT \'(DC2Type:uuid)\', |
||||
ADD CONSTRAINT FK_9209C2A0D877C209 FOREIGN KEY (custom_image_id) REFERENCES asset (id) ON DELETE SET NULL |
||||
'); |
||||
} |
||||
|
||||
public function down(Schema $schema): void |
||||
{ |
||||
// Remove the custom_image_id column and foreign key |
||||
$this->addSql(' |
||||
ALTER TABLE c_link |
||||
DROP FOREIGN KEY FK_9209C2A0D877C209, |
||||
DROP custom_image_id |
||||
'); |
||||
} |
||||
} |
Loading…
Reference in new issue