[11/06/2024] Les premières modifs + installation de quelques modules indispensables
This commit is contained in:
7
domokits/local/modules/TheliaLibrary/.github/workflows/release.yml
vendored
Normal file
7
domokits/local/modules/TheliaLibrary/.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
name: "Auto Release"
|
||||
on:
|
||||
push:
|
||||
branches: [ master, main ]
|
||||
jobs:
|
||||
release:
|
||||
uses: thelia-modules/ReusableWorkflow/.github/workflows/auto_release.yml@main
|
||||
2
domokits/local/modules/TheliaLibrary/.gitignore
vendored
Normal file
2
domokits/local/modules/TheliaLibrary/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
4
domokits/local/modules/TheliaLibrary/.husky/pre-commit
Executable file
4
domokits/local/modules/TheliaLibrary/.husky/pre-commit
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npm run build
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace TheliaLibrary\ApiExtend;
|
||||
|
||||
use OpenApi\Events\ModelExtendDataEvent;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Model\Api\Product;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use TheliaLibrary\Model\LibraryItemImage;
|
||||
use TheliaLibrary\Model\LibraryItemImageQuery;
|
||||
|
||||
class ProductApiListener implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ModelFactory $modelFactory,
|
||||
private RequestStack $requestStack
|
||||
){
|
||||
}
|
||||
|
||||
/**
|
||||
* @OA\Schema(
|
||||
* schema="TheliaLibraryExtendProduct",
|
||||
* @OA\Property(
|
||||
* property="libraryImages",
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* ref="#/components/schemas/LibraryItemImage"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function addImageToProduct(ModelExtendDataEvent $event)
|
||||
{
|
||||
/** @var Product $product */
|
||||
$product = $event->getModel();
|
||||
|
||||
$productImage = LibraryItemImageQuery::create()
|
||||
->filterByItemType('product')
|
||||
->filterByItemId($product->getId())
|
||||
->filterByVisible(1)
|
||||
->find();
|
||||
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$locale = $request->get('locale');
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $request->getLocale();
|
||||
}
|
||||
|
||||
$images = array_map(
|
||||
function (LibraryItemImage $itemImage) use ($locale) {
|
||||
return $this->modelFactory->buildModel('LibraryItemImage', $itemImage, $locale);
|
||||
},
|
||||
iterator_to_array($productImage)
|
||||
);
|
||||
|
||||
if (!empty($images)) {
|
||||
$event->setExtendDataKeyValue('libraryImages', $images);
|
||||
}
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
$events = [];
|
||||
if (class_exists('OpenApi\Events\ModelExtendDataEvent')){
|
||||
$events[ModelExtendDataEvent::ADD_EXTEND_DATA_PREFIX.'product'] = ['addImageToProduct',0];
|
||||
}
|
||||
|
||||
return $events;
|
||||
}
|
||||
}
|
||||
122
domokits/local/modules/TheliaLibrary/Command/ImageMigrateCommand.php
Executable file
122
domokits/local/modules/TheliaLibrary/Command/ImageMigrateCommand.php
Executable file
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Command;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
use Symfony\Component\Console\Helper\ProgressBar;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Thelia\Command\ContainerAwareCommand;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\LangQuery;
|
||||
use TheliaLibrary\Service\LibraryItemImageService;
|
||||
|
||||
class ImageMigrateCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected LibraryItemImageService $libraryItemImageService;
|
||||
|
||||
public function __construct(LibraryItemImageService $libraryItemImageService)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->libraryItemImageService = $libraryItemImageService;
|
||||
}
|
||||
|
||||
protected function configure(): void
|
||||
{
|
||||
$this
|
||||
->setName('library:image:migrate')
|
||||
->setDescription('Reset all password and send reset link')
|
||||
->addOption(
|
||||
'itemTypes',
|
||||
null,
|
||||
InputOption::VALUE_OPTIONAL | InputOption::VALUE_IS_ARRAY,
|
||||
'Only image of this item type will be migrated',
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||
{
|
||||
$filesystem = new Filesystem();
|
||||
$itemTypes = $input->getOption('itemTypes');
|
||||
|
||||
$baseSourceFilePath = ConfigQuery::read('images_library_path');
|
||||
if ($baseSourceFilePath === null) {
|
||||
$baseSourceFilePath = THELIA_LOCAL_DIR.'media'.DS.'images';
|
||||
} else {
|
||||
$baseSourceFilePath = THELIA_ROOT.$baseSourceFilePath;
|
||||
}
|
||||
|
||||
$langs = LangQuery::create()
|
||||
->find();
|
||||
|
||||
foreach ($itemTypes as $itemType) {
|
||||
$output->writeln('<bg=blue>============================================================= </>');
|
||||
$output->writeln("<fg=blue>Image migration for item type $itemType started</>");
|
||||
|
||||
/** @var ModelCriteria $queryClass */
|
||||
$queryClass = 'Thelia\\Model\\'.ucfirst($itemType).'ImageQuery';
|
||||
|
||||
/** @var ModelCriteria $query */
|
||||
$images = $queryClass::create()->find();
|
||||
$output->writeln(\count($images)." image found for type $itemType");
|
||||
$progressBar = new ProgressBar($output, \count($images));
|
||||
$progressBar->start();
|
||||
|
||||
$itemIdGetter = 'get'.ucfirst($itemType).'Id';
|
||||
foreach ($images as $image) {
|
||||
$tmpFilePath = '/tmp/image/'.$image->getFile();
|
||||
$filesystem->copy($baseSourceFilePath.DS.$itemType.DS.$image->getFile(), $tmpFilePath);
|
||||
$uploadedFile = new File(
|
||||
$tmpFilePath
|
||||
);
|
||||
|
||||
$itemImage = $this->libraryItemImageService->createAndAssociateImage(
|
||||
$uploadedFile,
|
||||
$image->getTitle(),
|
||||
$image->getLocale(),
|
||||
$itemType,
|
||||
$image->$itemIdGetter(),
|
||||
'thelia',
|
||||
$image->getVisible(),
|
||||
$image->getPosition()
|
||||
);
|
||||
$libraryImage = $itemImage->getLibraryImage();
|
||||
$libraryFilePath = $libraryImage->getFileName();
|
||||
|
||||
foreach ($langs as $lang) {
|
||||
$image->setLocale($lang->getLocale());
|
||||
|
||||
if (empty($image->getTitle())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$libraryImage->setLocale($lang->getLocale())
|
||||
->setTitle($image->getTitle())
|
||||
->setFileName($libraryFilePath)
|
||||
->save();
|
||||
}
|
||||
$progressBar->advance();
|
||||
}
|
||||
$progressBar->finish();
|
||||
$output->writeln('');
|
||||
$output->writeln("<info>Image migration for item type $itemType ended</info>");
|
||||
$output->writeln('<bg=blue>============================================================= </>');
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
120
domokits/local/modules/TheliaLibrary/Config/TheliaMain.sql
Executable file
120
domokits/local/modules/TheliaLibrary/Config/TheliaMain.sql
Executable file
@@ -0,0 +1,120 @@
|
||||
|
||||
# This is a fix for InnoDB in MySQL >= 4.1.x
|
||||
# It "suspends judgement" for fkey relationships until are tables are set.
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_image
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_image`;
|
||||
|
||||
CREATE TABLE `library_image`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_item_image
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_item_image`;
|
||||
|
||||
CREATE TABLE `library_item_image`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`image_id` INTEGER,
|
||||
`item_type` VARCHAR(255),
|
||||
`item_id` INTEGER,
|
||||
`code` VARCHAR(255),
|
||||
`visible` TINYINT,
|
||||
`position` INTEGER,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `library_item_image_item_index` (`item_type`, `item_id`),
|
||||
INDEX `fi_library_item_image_image_id` (`image_id`),
|
||||
CONSTRAINT `fk_library_item_image_image_id`
|
||||
FOREIGN KEY (`image_id`)
|
||||
REFERENCES `library_image` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_tag
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_tag`;
|
||||
|
||||
CREATE TABLE `library_tag`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`color_code` VARCHAR(255),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_image_tag
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_image_tag`;
|
||||
|
||||
CREATE TABLE `library_image_tag`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`image_id` INTEGER,
|
||||
`tag_id` INTEGER,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `fi_library_image_tag_image_id` (`image_id`),
|
||||
INDEX `fi_library_image_tag_tag_id` (`tag_id`),
|
||||
CONSTRAINT `fk_library_image_tag_image_id`
|
||||
FOREIGN KEY (`image_id`)
|
||||
REFERENCES `library_image` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_library_image_tag_tag_id`
|
||||
FOREIGN KEY (`tag_id`)
|
||||
REFERENCES `library_tag` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_image_i18n
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_image_i18n`;
|
||||
|
||||
CREATE TABLE `library_image_i18n`
|
||||
(
|
||||
`id` INTEGER NOT NULL,
|
||||
`locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL,
|
||||
`title` VARCHAR(255),
|
||||
`file_name` VARCHAR(255),
|
||||
PRIMARY KEY (`id`,`locale`),
|
||||
CONSTRAINT `library_image_i18n_fk_0228d9`
|
||||
FOREIGN KEY (`id`)
|
||||
REFERENCES `library_image` (`id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_tag_i18n
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_tag_i18n`;
|
||||
|
||||
CREATE TABLE `library_tag_i18n`
|
||||
(
|
||||
`id` INTEGER NOT NULL,
|
||||
`locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL,
|
||||
`title` VARCHAR(255),
|
||||
PRIMARY KEY (`id`,`locale`),
|
||||
CONSTRAINT `library_tag_i18n_fk_b8e890`
|
||||
FOREIGN KEY (`id`)
|
||||
REFERENCES `library_tag` (`id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
# This restores the fkey checks, after having unset them earlier
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
55
domokits/local/modules/TheliaLibrary/Config/config.xml
Executable file
55
domokits/local/modules/TheliaLibrary/Config/config.xml
Executable file
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<config xmlns="http://thelia.net/schema/dic/config"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/config http://thelia.net/schema/dic/config/thelia-1.0.xsd">
|
||||
|
||||
<loops>
|
||||
<!-- sample definition
|
||||
<loop name="MySuperLoop" class="TheliaLibrary\Loop\MySuperLoop" />
|
||||
-->
|
||||
</loops>
|
||||
|
||||
<forms>
|
||||
<!--
|
||||
<form name="MyFormName" class="TheliaLibrary\Form\MySuperForm" />
|
||||
-->
|
||||
</forms>
|
||||
|
||||
<commands>
|
||||
<!--
|
||||
<command class="TheliaLibrary\Command\MySuperCommand" />
|
||||
-->
|
||||
</commands>
|
||||
|
||||
<services>
|
||||
<!-- needed to be used in loop... -->
|
||||
<service id="thelia_library_image" alias="TheliaLibrary\Service\LibraryImageService" public="true"/>
|
||||
</services>
|
||||
|
||||
|
||||
<hooks>
|
||||
<hook id="thelialibrary.tb.plugin" class="TheliaLibrary\Hook\BackHook">
|
||||
<tag name="hook.event_listener" event="thelia.blocks.plugins" type="back" templates="render:tb-plugin/import-plugin.html" />
|
||||
<tag name="hook.event_listener" event="thelia.blocks.plugincss" type="back" templates="render:tb-plugin/import-styles.html" />
|
||||
</hook>
|
||||
<!--
|
||||
<hook id="thelialibrary.item.editions" class="TheliaLibrary\Hook\BackHook">
|
||||
<tag name="hook.event_listener" event="item.edition.images" type="back" method="onItemEdition" />
|
||||
</hook>
|
||||
-->
|
||||
</hooks>
|
||||
|
||||
|
||||
<!--
|
||||
<exports>
|
||||
|
||||
</exports>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<imports>
|
||||
|
||||
</imports>
|
||||
-->
|
||||
</config>
|
||||
43
domokits/local/modules/TheliaLibrary/Config/module.xml
Executable file
43
domokits/local/modules/TheliaLibrary/Config/module.xml
Executable file
@@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module xmlns="http://thelia.net/schema/dic/module"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://thelia.net/schema/dic/module http://thelia.net/schema/dic/module/module-2_2.xsd">
|
||||
<fullnamespace>TheliaLibrary\TheliaLibrary</fullnamespace>
|
||||
<descriptive locale="en_US">
|
||||
<title>A media library for Thelia</title>
|
||||
<!--
|
||||
<subtitle></subtitle>
|
||||
<description></description>
|
||||
<postscriptum></postscriptum>
|
||||
-->
|
||||
</descriptive>
|
||||
<descriptive locale="fr_FR">
|
||||
<title>Une médiathéque pour Thelia</title>
|
||||
</descriptive>
|
||||
<!-- <logo></logo> -->
|
||||
<!--<images-folder>images</images-folder>-->
|
||||
<languages>
|
||||
<language>en_US</language>
|
||||
<language>fr_FR</language>
|
||||
</languages>
|
||||
<version>1.2.7</version>
|
||||
<authors>
|
||||
<author>
|
||||
<name></name>
|
||||
<email></email>
|
||||
</author>
|
||||
</authors>
|
||||
<type>classic</type>
|
||||
<!--
|
||||
module dependencies
|
||||
<required>
|
||||
<module version=">=0.1">Front</module>
|
||||
<module version="~1.0">HookCart</module>
|
||||
<module version=">0.2">HookSearch</module>
|
||||
</required>
|
||||
-->
|
||||
<thelia>2.5.0</thelia>
|
||||
<stability>other</stability>
|
||||
<mandatory>0</mandatory>
|
||||
<hidden>0</hidden>
|
||||
</module>
|
||||
31
domokits/local/modules/TheliaLibrary/Config/routing.xml
Executable file
31
domokits/local/modules/TheliaLibrary/Config/routing.xml
Executable file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<!--
|
||||
|
||||
if a /admin/module/thelialibrary/ route is provided, a "Configuration" button will be displayed
|
||||
for the module in the module list. Clicking this button will invoke this route.
|
||||
|
||||
<route id="my_route_id" path="/admin/module/thelialibrary">
|
||||
<default key="_controller">TheliaLibrary\Full\Class\Name\Of\YourConfigurationController::methodName</default>
|
||||
</route>
|
||||
|
||||
<route id="my_route_id" path="/admin/module/thelialibrary/route-name">
|
||||
<default key="_controller">TheliaLibrary\Full\Class\Name\Of\YourAdminController::methodName</default>
|
||||
</route>
|
||||
|
||||
<route id="my_route_id" path="/my/route/name">
|
||||
<default key="_controller">TheliaLibrary\Full\Class\Name\Of\YourOtherController::methodName</default>
|
||||
</route>
|
||||
|
||||
...add as many routes as required.
|
||||
|
||||
<route>
|
||||
...
|
||||
</route>
|
||||
-->
|
||||
|
||||
</routes>
|
||||
57
domokits/local/modules/TheliaLibrary/Config/schema.xml
Executable file
57
domokits/local/modules/TheliaLibrary/Config/schema.xml
Executable file
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<database defaultIdMethod="native" name="TheliaMain"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../../vendor/thelia/propel/resources/xsd/database.xsd" >
|
||||
|
||||
<table name="library_image" namespace="TheliaLibrary\Model">
|
||||
<column name="id" primaryKey="true" required="true" type="INTEGER" autoIncrement="true"/>
|
||||
<column name="title" type="VARCHAR" />
|
||||
<column name="file_name" type="VARCHAR" />
|
||||
<behavior name="i18n">
|
||||
<parameter name="i18n_columns" value="title, file_name" />
|
||||
</behavior>
|
||||
</table>
|
||||
|
||||
<table name="library_item_image" namespace="TheliaLibrary\Model">
|
||||
<column name="id" primaryKey="true" required="true" type="INTEGER" autoIncrement="true"/>
|
||||
<column name="image_id" type="INTEGER" />
|
||||
<column name="item_type" type="VARCHAR" />
|
||||
<column name="item_id" type="INTEGER" />
|
||||
<column name="code" type="VARCHAR"/>
|
||||
<column name="visible" type="TINYINT" />
|
||||
<column name="position" type="INTEGER" />
|
||||
<foreign-key foreignTable="library_image" name="fk_library_item_image_image_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="image_id" />
|
||||
</foreign-key>
|
||||
|
||||
<index name="library_item_image_item_index">
|
||||
<index-column name="item_type" />
|
||||
<index-column name="item_id" />
|
||||
</index>
|
||||
</table>
|
||||
|
||||
<table name="library_tag" namespace="TheliaLibrary\Model">
|
||||
<column name="id" primaryKey="true" required="true" type="INTEGER" autoIncrement="true"/>
|
||||
<column name="title" type="VARCHAR" />
|
||||
<column name="color_code" type="VARCHAR" />
|
||||
<behavior name="i18n">
|
||||
<parameter name="i18n_columns" value="title" />
|
||||
</behavior>
|
||||
</table>
|
||||
|
||||
<table name="library_image_tag" namespace="TheliaLibrary\Model">
|
||||
<column name="id" primaryKey="true" required="true" type="INTEGER" autoIncrement="true"/>
|
||||
<column name="image_id" type="INTEGER" />
|
||||
<column name="tag_id" type="INTEGER" />
|
||||
|
||||
<foreign-key foreignTable="library_image" name="fk_library_image_tag_image_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="image_id" />
|
||||
</foreign-key>
|
||||
|
||||
<foreign-key foreignTable="library_tag" name="fk_library_image_tag_tag_id" onDelete="CASCADE" onUpdate="RESTRICT">
|
||||
<reference foreign="id" local="tag_id" />
|
||||
</foreign-key>
|
||||
|
||||
</table>
|
||||
|
||||
</database>
|
||||
2
domokits/local/modules/TheliaLibrary/Config/sqldb.map
Executable file
2
domokits/local/modules/TheliaLibrary/Config/sqldb.map
Executable file
@@ -0,0 +1,2 @@
|
||||
# Sqlfile -> Database map
|
||||
TheliaMain.sql=TheliaMain
|
||||
57
domokits/local/modules/TheliaLibrary/Config/update/1.1.2.sql
Normal file
57
domokits/local/modules/TheliaLibrary/Config/update/1.1.2.sql
Normal file
@@ -0,0 +1,57 @@
|
||||
|
||||
# This is a fix for InnoDB in MySQL >= 4.1.x
|
||||
# It "suspends judgement" for fkey relationships until are tables are set.
|
||||
SET FOREIGN_KEY_CHECKS = 0;
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- library_tag_i18n
|
||||
-- ---------------------------------------------------------------------
|
||||
|
||||
DROP TABLE IF EXISTS `library_tag`;
|
||||
|
||||
CREATE TABLE `library_tag`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`color_code` VARCHAR(255),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS `library_image_tag`;
|
||||
|
||||
CREATE TABLE `library_image_tag`
|
||||
(
|
||||
`id` INTEGER NOT NULL AUTO_INCREMENT,
|
||||
`image_id` INTEGER,
|
||||
`tag_id` INTEGER,
|
||||
PRIMARY KEY (`id`),
|
||||
INDEX `fi_library_image_tag_image_id` (`image_id`),
|
||||
INDEX `fi_library_image_tag_tag_id` (`tag_id`),
|
||||
CONSTRAINT `fk_library_image_tag_image_id`
|
||||
FOREIGN KEY (`image_id`)
|
||||
REFERENCES `library_image` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_library_image_tag_tag_id`
|
||||
FOREIGN KEY (`tag_id`)
|
||||
REFERENCES `library_tag` (`id`)
|
||||
ON UPDATE RESTRICT
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS `library_tag_i18n`;
|
||||
|
||||
CREATE TABLE `library_tag_i18n`
|
||||
(
|
||||
`id` INTEGER NOT NULL,
|
||||
`locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL,
|
||||
`title` VARCHAR(255),
|
||||
PRIMARY KEY (`id`,`locale`),
|
||||
CONSTRAINT `library_tag_i18n_fk_b8e890`
|
||||
FOREIGN KEY (`id`)
|
||||
REFERENCES `library_tag` (`id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
|
||||
# This restores the fkey checks, after having unset them earlier
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
197
domokits/local/modules/TheliaLibrary/Controller/Admin/ImageController.php
Executable file
197
domokits/local/modules/TheliaLibrary/Controller/Admin/ImageController.php
Executable file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Admin;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Admin\BaseAdminOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Service\LibraryImageService;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/image", name="library_image")
|
||||
*/
|
||||
class ImageController extends BaseAdminOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_create", methods="POST")
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/library/image",
|
||||
* tags={ "Library image"},
|
||||
* summary="Create a new image",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="multipart/form-data",
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="title",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="locale",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="image",
|
||||
* type="string",
|
||||
* format="binary"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function createImage(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryImageService $libraryImageService
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
|
||||
$image = $libraryImageService->createImage(
|
||||
$request->files->get('image'),
|
||||
$request->request->get('title'),
|
||||
$locale
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryImage', $image, $locale));
|
||||
}
|
||||
|
||||
// Method POST because patch doesn't work with multipart/form-data
|
||||
|
||||
/**
|
||||
* @Route("/{imageId}", name="_update", methods="POST", requirements={"imageId"="\d+"})
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/library/image/{imageId}",
|
||||
* tags={ "Library image"},
|
||||
* summary="Update an image",
|
||||
* @OA\Parameter(
|
||||
* name="imageId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\MediaType(
|
||||
* mediaType="multipart/form-data",
|
||||
* @OA\Schema(
|
||||
* @OA\Property(
|
||||
* property="title",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="locale",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="image",
|
||||
* type="string",
|
||||
* format="binary"
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function updateImage(
|
||||
$imageId,
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryImageService $libraryImageService
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
$image = $libraryImageService->updateImage(
|
||||
$imageId,
|
||||
$request->files->get('image'),
|
||||
$request->request->get('title'),
|
||||
$locale
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryImage', $image, $locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{imageId}", name="_delete", methods="DELETE", requirements={"imageId"="\d+"})
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/library/image/{imageId}",
|
||||
* tags={ "Library image"},
|
||||
* summary="Delete an image",
|
||||
* @OA\Parameter(
|
||||
* name="imageId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="204",
|
||||
* description="Success"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function deleteImage(
|
||||
$imageId,
|
||||
LibraryImageService $libraryImageService
|
||||
) {
|
||||
$libraryImageService->deleteImage($imageId);
|
||||
|
||||
return new JsonResponse('Success', 204);
|
||||
}
|
||||
|
||||
protected function findLocale(Request $request)
|
||||
{
|
||||
$locale = $request->get('locale');
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $request->getSession()->getAdminEditionLang()->getLocale();
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Admin;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Admin\BaseAdminOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Model\LibraryImageTag;
|
||||
use TheliaLibrary\Model\LibraryTagQuery;
|
||||
use TheliaLibrary\Service\LibraryImageTagService;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/image_tag", name="library_image_tag")
|
||||
*/
|
||||
class ImageTagController extends BaseAdminOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_associate", methods="POST")
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/library/image_tag",
|
||||
* tags={ "Library tag"},
|
||||
* summary="Associate a tag to an image",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(
|
||||
* property="imageId",
|
||||
* type="integer",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="tagId",
|
||||
* type="integer",
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryImageTag")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function createAssociation(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryImageTagService $libraryImageTagService
|
||||
) {
|
||||
$data = json_decode($request->getContent(), true);
|
||||
/** @var LibraryImageTag $openApiLibraryImageTag */
|
||||
$openApiLibraryImageTag = $modelFactory->buildModel('LibraryImageTag', $data);
|
||||
$openApiLibraryImageTag->validate(self::GROUP_UPDATE);
|
||||
|
||||
$image = $libraryImageTagService->associateImage(
|
||||
$openApiLibraryImageTag->getImageId(),
|
||||
$openApiLibraryImageTag->getTagId(),
|
||||
);
|
||||
|
||||
$query = LibraryTagQuery::create();
|
||||
$tag = $query->findOneById($openApiLibraryImageTag->getTagId());
|
||||
|
||||
return OpenApiService::jsonResponse(['imageTag' => $modelFactory->buildModel('LibraryImageTag', $image), 'tag' => $modelFactory->buildModel('LibraryTag', $tag)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{imageTagId}", name="_delete_association", methods="DELETE", requirements={"imageTagId"="\d+"})
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/library/image_tag/{imageTagId}",
|
||||
* tags={ "Library tag"},
|
||||
* summary="Delete an association",
|
||||
* @OA\Parameter(
|
||||
* name="imageTagId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="204",
|
||||
* description="Success"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function deleteAssociation(
|
||||
$imageTagId,
|
||||
LibraryImageTagService $libraryImageTagService
|
||||
) {
|
||||
$libraryImageTagService->deleteImageAssociation($imageTagId);
|
||||
|
||||
return new JsonResponse('Success', 204);
|
||||
}
|
||||
}
|
||||
198
domokits/local/modules/TheliaLibrary/Controller/Admin/ItemImageController.php
Executable file
198
domokits/local/modules/TheliaLibrary/Controller/Admin/ItemImageController.php
Executable file
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Admin;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Admin\BaseAdminOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Model\Api\LibraryItemImage;
|
||||
use TheliaLibrary\Service\LibraryItemImageService;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/item_image", name="library_item_image")
|
||||
*/
|
||||
class ItemImageController extends BaseAdminOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_associate", methods="POST")
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/library/item_image",
|
||||
* tags={ "Library image"},
|
||||
* summary="Associate an image to an item",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(
|
||||
* property="imageId",
|
||||
* type="integer",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="itemType",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="itemId",
|
||||
* type="integer",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="code",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="visible",
|
||||
* type="boolean",
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryItemImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function createAssociation(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryItemImageService $libraryItemImageService
|
||||
) {
|
||||
$data = json_decode($request->getContent(), true);
|
||||
/** @var LibraryItemImage $openApiLibraryItemImage */
|
||||
$openApiLibraryItemImage = $modelFactory->buildModel('LibraryItemImage', $data);
|
||||
$openApiLibraryItemImage->validate(self::GROUP_UPDATE);
|
||||
|
||||
$image = $libraryItemImageService->associateImage(
|
||||
$openApiLibraryItemImage->getImageId(),
|
||||
$openApiLibraryItemImage->getItemType(),
|
||||
$openApiLibraryItemImage->getItemId(),
|
||||
$openApiLibraryItemImage->getCode(),
|
||||
$openApiLibraryItemImage->isVisible(),
|
||||
$openApiLibraryItemImage->getPosition()
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryItemImage', $image));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{itemImageId}", name="_update_association", methods="PATCH", requirements={"itemImageId"="\d+"})
|
||||
*
|
||||
* @OA\Patch(
|
||||
* path="/library/item_image/{itemImageId}",
|
||||
* tags={ "Library image"},
|
||||
* summary="Update an association",
|
||||
* @OA\Parameter(
|
||||
* name="itemImageId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(
|
||||
* property="visible",
|
||||
* type="boolean",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="code",
|
||||
* type="string",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="position",
|
||||
* type="integer",
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="positionMovement",
|
||||
* type="string",
|
||||
* enum={"up", "down"}
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryItemImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function updateAssociation(
|
||||
$itemImageId,
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryItemImageService $libraryItemImageService
|
||||
) {
|
||||
$data = json_decode($request->getContent(), true);
|
||||
|
||||
$image = $libraryItemImageService->updateImageAssociation(
|
||||
$itemImageId,
|
||||
$data['code'] ?? null,
|
||||
$data['visible'] ?? null,
|
||||
$data['position'] ?? null,
|
||||
$data['positionMovement'] ?? null
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryItemImage', $image));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{itemImageId}", name="_delete_association", methods="DELETE", requirements={"itemImageId"="\d+"})
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/library/item_image/{itemImageId}",
|
||||
* tags={ "Library image"},
|
||||
* summary="Delete an association",
|
||||
* @OA\Parameter(
|
||||
* name="itemImageId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="204",
|
||||
* description="Success"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function deleteAssociation(
|
||||
$itemImageId,
|
||||
LibraryItemImageService $libraryItemImageService
|
||||
) {
|
||||
$libraryItemImageService->deleteImageAssociation($itemImageId);
|
||||
|
||||
return new JsonResponse('Success', 204);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Admin;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Admin\BaseAdminOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\JsonResponse;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Model\Base\LibraryTagQuery;
|
||||
use TheliaLibrary\Model\LibraryTag;
|
||||
use TheliaLibrary\Service\LibraryTagService;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/tag", name="library_tag")
|
||||
*/
|
||||
class TagController extends BaseAdminOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_view", methods="GET")
|
||||
* @OA\Get(
|
||||
* path="/library/tag",
|
||||
* tags={"Library tag"},
|
||||
* summary="Get tags",
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryTag")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getTags(Request $request, ModelFactory $modelFactory)
|
||||
{
|
||||
$query = LibraryTagQuery::create();
|
||||
$locale = $this->findLocale($request);
|
||||
|
||||
return OpenApiService::jsonResponse(array_map(
|
||||
function (LibraryTag $tag) use ($modelFactory, $locale) {
|
||||
/** @var \TheliaLibrary\Model\Api\LibraryTag $tagModel */
|
||||
$tagModel = $modelFactory->buildModel('LibraryTag', $tag, $locale);
|
||||
|
||||
return $tagModel;
|
||||
},
|
||||
iterator_to_array($query->find())
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("", name="_create", methods="POST")
|
||||
*
|
||||
* @OA\Post(
|
||||
* path="/library/tag",
|
||||
* tags={ "Library tag"},
|
||||
* summary="Create a new tag",
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(
|
||||
* property="title",
|
||||
* type="string"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="colorCode",
|
||||
* default="#000000",
|
||||
* type="string"
|
||||
* ),
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryTag")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function createTag(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryTagService $libraryTagService
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
|
||||
$tag = $libraryTagService->createTag(
|
||||
$request->request->get('title'),
|
||||
$request->request->get('colorCode'),
|
||||
$locale
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryTag', $tag, $locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{tagId}", name="_update", methods="POST", requirements={"tagId"="\d+"})
|
||||
* @OA\Post(
|
||||
* path="/library/tag/{tagId}",
|
||||
* tags={ "Library tag"},
|
||||
* summary="update a tag",
|
||||
* @OA\Parameter(
|
||||
* name="tagId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\RequestBody(
|
||||
* required=true,
|
||||
* @OA\JsonContent(
|
||||
* @OA\Property(
|
||||
* property="title",
|
||||
* type="string"
|
||||
* ),
|
||||
* @OA\Property(
|
||||
* property="colorCode",
|
||||
* default="#000000",
|
||||
* type="string"
|
||||
* ),
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryTag")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function updateTag(
|
||||
$tagId,
|
||||
Request $request,
|
||||
ModelFactory $modelFactory,
|
||||
LibraryTagService $libraryTagService
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
$tag = $libraryTagService->updateTag(
|
||||
$tagId,
|
||||
$request->request->get('title'),
|
||||
$request->request->get('colorCode'),
|
||||
$locale
|
||||
);
|
||||
|
||||
return OpenApiService::jsonResponse($modelFactory->buildModel('LibraryTag', $tag, $locale));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{tagId}", name="_delete", methods="DELETE", requirements={"tagId"="\d+"})
|
||||
*
|
||||
* @OA\Delete(
|
||||
* path="/library/tag/{tagId}",
|
||||
* tags={ "Library tag"},
|
||||
* summary="Delete a tag",
|
||||
* @OA\Parameter(
|
||||
* name="tagId",
|
||||
* in="path",
|
||||
* required=true,
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="204",
|
||||
* description="Success"
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function deleteTag(
|
||||
$tagId,
|
||||
LibraryTagService $libraryTagService
|
||||
) {
|
||||
$libraryTagService->deleteTag($tagId);
|
||||
|
||||
return new JsonResponse('Success', 204);
|
||||
}
|
||||
|
||||
protected function findLocale(Request $request)
|
||||
{
|
||||
$locale = $request->get('locale');
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $request->getSession()->getAdminEditionLang()->getLocale();
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
75
domokits/local/modules/TheliaLibrary/Controller/Front/ImageController.php
Executable file
75
domokits/local/modules/TheliaLibrary/Controller/Front/ImageController.php
Executable file
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Front;
|
||||
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Core\HttpFoundation\Response;
|
||||
use Thelia\Tools\URL;
|
||||
use TheliaLibrary\Service\ImageService;
|
||||
|
||||
/**
|
||||
* @Route("/image-library", name="image_library_")
|
||||
*/
|
||||
class ImageController extends BaseFrontController
|
||||
{
|
||||
/**
|
||||
* @Route("/{identifier}/{region}/{size}/{rotation}/{quality}.{format}", name="view")
|
||||
*/
|
||||
public function getImage(
|
||||
$identifier,
|
||||
$region,
|
||||
$size,
|
||||
$rotation,
|
||||
$quality,
|
||||
$format,
|
||||
ImageService $imageService
|
||||
) {
|
||||
$imagePath = $imageService->geFormattedImage($identifier, $region, $size, $rotation, $quality, $format);
|
||||
|
||||
return new BinaryFileResponse($imagePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{identifier}/info.json", name="info")
|
||||
*/
|
||||
public function getImageInformation(
|
||||
$identifier,
|
||||
ImageService $imageService
|
||||
): Response {
|
||||
$image = $imageService->openImage($identifier);
|
||||
$size = $image->getSize();
|
||||
$maxSize = $imageService->getMaxSize($image);
|
||||
|
||||
return new Response(
|
||||
json_encode(
|
||||
[
|
||||
'@context' => 'http://iiif.io/api/image/3/context.json',
|
||||
'id' => URL::getInstance()->absoluteUrl('image-library/'.$identifier),
|
||||
'type' => 'ImageService3',
|
||||
'protocol' => 'http://iiif.io/api/image',
|
||||
'profile' => 'level2',
|
||||
'width' => $size->getWidth(),
|
||||
'height' => $size->getHeight(),
|
||||
'maxWidth' => $maxSize->getWidth(),
|
||||
'maxHeight' => $maxSize->getHeight(),
|
||||
]
|
||||
),
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/ld+json;profile="http://iiif.io/api/image/3/context.json"',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Front;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\ModelCriteria;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Core\HttpFoundation\Response;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\ProductImage;
|
||||
use Thelia\Tools\URL;
|
||||
use TheliaLibrary\Service\ImageService;
|
||||
use TheliaMain\PropelResolver;
|
||||
|
||||
/**
|
||||
* @Route("/legacy-image-library", name="legacy_image_library_")
|
||||
*/
|
||||
class LegacyImageController extends BaseFrontController
|
||||
{
|
||||
/**
|
||||
* @Route("/{itemType}_image_{imageId}/{region}/{size}/{rotation}/{quality}.{format}", name="view")
|
||||
*/
|
||||
public function getImage(
|
||||
$itemType,
|
||||
$imageId,
|
||||
$region,
|
||||
$size,
|
||||
$rotation,
|
||||
$quality,
|
||||
$format,
|
||||
ImageService $imageService
|
||||
) {
|
||||
$sourceFilePath = $this->getSourceFilePath($itemType, $imageId);
|
||||
|
||||
if (!\in_array(strtolower($format), ['jpg', 'jpeg', 'png', 'gif', 'jp2', 'webp'])) {
|
||||
throw new HttpException(400, 'Bad format value');
|
||||
}
|
||||
|
||||
$formattedImagePath = THELIA_WEB_DIR.'legacy-image-library'.DS.$itemType.'_image_'.$imageId.DS.$region.DS.$size.DS.$rotation;
|
||||
if (!is_dir($formattedImagePath)) {
|
||||
if (!@mkdir($formattedImagePath, 0755, true)) {
|
||||
throw new \RuntimeException(sprintf('Failed to create %s file in cache directory', $formattedImagePath));
|
||||
}
|
||||
}
|
||||
|
||||
$formattedImagePath .= DS.$quality.'.'.$format;
|
||||
|
||||
if (file_exists($formattedImagePath)) {
|
||||
return new BinaryFileResponse($formattedImagePath);
|
||||
}
|
||||
|
||||
$image = $imageService->getImagineInstance()->open($sourceFilePath);
|
||||
$image = $imageService->applyRegion($image, $region);
|
||||
$image = $imageService->applySize($image, $size);
|
||||
$image = $imageService->applyRotation($image, $rotation, $format);
|
||||
$image = $imageService->applyQuality($image, $quality);
|
||||
$image->save($formattedImagePath);
|
||||
|
||||
return new BinaryFileResponse($formattedImagePath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/{itemType}_image_{imageId}/info.json", name="info")
|
||||
*/
|
||||
public function getImageInformation(
|
||||
$itemType,
|
||||
$imageId,
|
||||
ImageService $imageService
|
||||
): Response {
|
||||
$sourceFilePath = $this->getSourceFilePath($itemType, $imageId);
|
||||
|
||||
$image = $imageService->getImagineInstance()->open($sourceFilePath);
|
||||
$size = $image->getSize();
|
||||
$maxSize = $imageService->getMaxSize($image);
|
||||
|
||||
return new Response(
|
||||
json_encode(
|
||||
[
|
||||
'@context' => 'http://iiif.io/api/image/3/context.json',
|
||||
'id' => URL::getInstance()->absoluteUrl('legacy-image-library/'.$itemType.'_image_'.$imageId),
|
||||
'type' => 'ImageService3',
|
||||
'protocol' => 'http://iiif.io/api/image',
|
||||
'profile' => 'level2',
|
||||
'width' => $size->getWidth(),
|
||||
'height' => $size->getHeight(),
|
||||
'maxWidth' => $maxSize->getWidth(),
|
||||
'maxHeight' => $maxSize->getHeight(),
|
||||
]
|
||||
),
|
||||
200,
|
||||
[
|
||||
'Content-Type' => 'application/ld+json;profile="http://iiif.io/api/image/3/context.json"',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function getSnakeFromCamelCase($camelCase): string
|
||||
{
|
||||
$pattern = '/(?<=\\w)(?=[A-Z])|(?<=[a-z])(?=[0-9])/';
|
||||
$snakeCase = preg_replace($pattern, '_', $camelCase);
|
||||
return strtolower($snakeCase);
|
||||
}
|
||||
|
||||
private function getSourceFilePath($itemType, $imageId)
|
||||
{
|
||||
$tableMapClass = PropelResolver::getTableMapByTableName($this->getSnakeFromCamelCase($itemType));
|
||||
$tableMap = new $tableMapClass();
|
||||
|
||||
/** @var ModelCriteria $queryClass */
|
||||
$queryClass = $tableMap->getClassName().'ImageQuery';
|
||||
|
||||
/** @var ProductImage $image */
|
||||
$image = $queryClass::create()
|
||||
->filterById($imageId)
|
||||
->filterByVisible(1)
|
||||
->findOne();
|
||||
|
||||
if (null === $image) {
|
||||
return new Response(null, 404);
|
||||
}
|
||||
|
||||
$baseSourceFilePath = ConfigQuery::read('images_library_path');
|
||||
if ($baseSourceFilePath === null) {
|
||||
$baseSourceFilePath = THELIA_LOCAL_DIR.'media'.DS.'images';
|
||||
} else {
|
||||
$baseSourceFilePath = THELIA_ROOT.$baseSourceFilePath;
|
||||
}
|
||||
|
||||
return sprintf(
|
||||
'%s/%s/%s',
|
||||
$baseSourceFilePath,
|
||||
$itemType,
|
||||
$image->getFile()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Front\OpenApi;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Front\BaseFrontOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Model\LibraryImage;
|
||||
use TheliaLibrary\Model\LibraryImageQuery;
|
||||
use TheliaLibrary\Model\LibraryItemImageQuery;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/image", name="front_library_image")
|
||||
*/
|
||||
class ImageController extends BaseFrontOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_get", methods="GET")
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/library/image",
|
||||
* tags={"Library image"},
|
||||
* summary="Get images",
|
||||
* @OA\Parameter(
|
||||
* name="id",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="itemId",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="itemType",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="title",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="code",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="onlyVisible",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="boolean",
|
||||
* default="true"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="offset",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="limit",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="tagId",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="width",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="height",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="locale",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getImage(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
|
||||
$imageQuery = LibraryImageQuery::create()->orderById(Criteria::DESC);
|
||||
|
||||
if (null !== $id = $request->get('id')) {
|
||||
$imageQuery->filterById($id);
|
||||
}
|
||||
|
||||
if (null !== $title = $request->get('title')) {
|
||||
$imageQuery->useLibraryImageI18nQuery()
|
||||
->filterByLocale($locale)
|
||||
->filterByTitle("%$title%", Criteria::LIKE)
|
||||
->endUse();
|
||||
}
|
||||
|
||||
$itemImageQuery = null;
|
||||
|
||||
if (null !== $itemId = $request->get('itemId')) {
|
||||
$itemImageQuery = $this->getOrInitItemJoin($imageQuery, $itemImageQuery)->filterByItemId($itemId);
|
||||
}
|
||||
|
||||
if (null !== $itemType = $request->get('itemType')) {
|
||||
$itemImageQuery = $this->getOrInitItemJoin($imageQuery, $itemImageQuery)->filterByItemType($itemType);
|
||||
}
|
||||
|
||||
if (null !== $code = $request->get('code')) {
|
||||
$itemImageQuery = $this->getOrInitItemJoin($imageQuery, $itemImageQuery)->filterByCode($code);
|
||||
}
|
||||
|
||||
if (true === $request->get('onlyVisible')) {
|
||||
$itemImageQuery = $this->getOrInitItemJoin($imageQuery, $itemImageQuery)->filterByVisible(true);
|
||||
}
|
||||
|
||||
if (null !== $itemImageQuery) {
|
||||
$itemImageQuery->orderByPosition();
|
||||
$itemImageQuery->endUse();
|
||||
}
|
||||
|
||||
if (null !== $tagId = $request->get('tagId')) {
|
||||
$itemImageQuery = $imageQuery->useLibraryImageTagQuery()->filterByTagId($tagId)->endUse();
|
||||
}
|
||||
|
||||
if (null !== $limit = $request->get('limit', 20)) {
|
||||
$imageQuery->limit($limit);
|
||||
}
|
||||
|
||||
if (null !== $offset = $request->get('offset', 0)) {
|
||||
$imageQuery->offset($offset);
|
||||
}
|
||||
|
||||
$width = $request->get('width');
|
||||
$height = $request->get('height');
|
||||
|
||||
return OpenApiService::jsonResponse(array_map(
|
||||
function (LibraryImage $image) use ($modelFactory, $locale, $width, $height) {
|
||||
/** @var \TheliaLibrary\Model\Api\LibraryImage $imageModel */
|
||||
$imageModel = $modelFactory->buildModel('LibraryImage', $image, $locale);
|
||||
$imageModel->setWidth($width);
|
||||
$imageModel->setHeight($height);
|
||||
|
||||
return $imageModel;
|
||||
},
|
||||
iterator_to_array($imageQuery->find())
|
||||
));
|
||||
}
|
||||
|
||||
protected function getOrInitItemJoin($query, $itemImageQuery = null): LibraryItemImageQuery
|
||||
{
|
||||
if (null !== $itemImageQuery) {
|
||||
return $itemImageQuery;
|
||||
}
|
||||
|
||||
return $query->useLibraryItemImageQuery();
|
||||
}
|
||||
|
||||
protected function findLocale(Request $request)
|
||||
{
|
||||
$locale = $request->get('locale');
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $request->getSession()->getLang()->getLocale();
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Controller\Front\OpenApi;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Controller\Front\BaseFrontOpenApiController;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use OpenApi\Service\OpenApiService;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use TheliaLibrary\Model\LibraryItemImage;
|
||||
use TheliaLibrary\Model\LibraryItemImageQuery;
|
||||
|
||||
/**
|
||||
* @Route("/open_api/library/item_image", name="front_library_item_image")
|
||||
*/
|
||||
class ItemImageController extends BaseFrontOpenApiController
|
||||
{
|
||||
/**
|
||||
* @Route("", name="_get", methods="GET")
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/library/item_image",
|
||||
* tags={"Library image"},
|
||||
* summary="Get item images association",
|
||||
* @OA\Parameter(
|
||||
* name="itemId",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="itemType",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="code",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="string"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="offset",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Parameter(
|
||||
* name="limit",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="integer"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(ref="#/components/schemas/LibraryItemImage")
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getItemImage(
|
||||
Request $request,
|
||||
ModelFactory $modelFactory
|
||||
) {
|
||||
$locale = $this->findLocale($request);
|
||||
|
||||
$itemImageQuery = LibraryItemImageQuery::create();
|
||||
|
||||
if (null !== $imageId = $request->get('imageId')) {
|
||||
$itemImageQuery->filterByImageId($imageId);
|
||||
}
|
||||
|
||||
if (null !== $itemType = $request->get('itemType')) {
|
||||
$itemImageQuery->filterByItemType($itemType);
|
||||
}
|
||||
|
||||
if (null !== $itemId = $request->get('itemId')) {
|
||||
$itemImageQuery->filterByItemId($itemId);
|
||||
}
|
||||
|
||||
if (null !== $code = $request->get('code')) {
|
||||
$itemImageQuery->filterByCode($code);
|
||||
}
|
||||
|
||||
if (null !== $limit = $request->get('limit', 20)) {
|
||||
$itemImageQuery->limit($limit);
|
||||
}
|
||||
|
||||
if (null !== $offset = $request->get('offset', 0)) {
|
||||
$itemImageQuery->offset($offset);
|
||||
}
|
||||
|
||||
$itemImageQuery->orderByPosition();
|
||||
|
||||
return OpenApiService::jsonResponse(array_map(
|
||||
function (LibraryItemImage $itemImage) use ($modelFactory, $locale) {
|
||||
return $modelFactory->buildModel('LibraryItemImage', $itemImage, $locale);
|
||||
},
|
||||
iterator_to_array($itemImageQuery->find())
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/types", name="_type_list", methods="GET")
|
||||
*
|
||||
* @OA\Get(
|
||||
* path="/library/item_image/types",
|
||||
* tags={"Library image"},
|
||||
* summary="Get all item types availables",
|
||||
* @OA\Parameter(
|
||||
* name="onlyExisting",
|
||||
* description="If false basic Thelia types will be added (product, content, ...) even if they have no image associated",
|
||||
* in="query",
|
||||
* @OA\Schema(
|
||||
* type="boolean",
|
||||
* default="false"
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="200",
|
||||
* description="Success",
|
||||
* @OA\JsonContent(
|
||||
* type="array",
|
||||
* @OA\Items(
|
||||
* type="string",
|
||||
* )
|
||||
* )
|
||||
* ),
|
||||
* @OA\Response(
|
||||
* response="400",
|
||||
* description="Bad request",
|
||||
* @OA\JsonContent(ref="#/components/schemas/Error")
|
||||
* )
|
||||
* )
|
||||
*/
|
||||
public function getItemTypes(
|
||||
Request $request
|
||||
) {
|
||||
$itemTypes = array_map(
|
||||
function (LibraryItemImage $libraryItemImage) {
|
||||
return $libraryItemImage->getItemType();
|
||||
},
|
||||
iterator_to_array(LibraryItemImageQuery::create()
|
||||
->groupByItemType()
|
||||
->find())
|
||||
);
|
||||
|
||||
if (false === $request->get('onlyExisting', false) || 'false' === $request->get('onlyExisting', false)) {
|
||||
$itemTypes = array_merge(
|
||||
[
|
||||
'product',
|
||||
'category',
|
||||
'content',
|
||||
'folder',
|
||||
],
|
||||
$itemTypes
|
||||
);
|
||||
}
|
||||
|
||||
return OpenApiService::jsonResponse(
|
||||
$itemTypes
|
||||
);
|
||||
}
|
||||
|
||||
protected function findLocale(Request $request)
|
||||
{
|
||||
$locale = $request->get('locale');
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $request->getSession()->getAdminEditionLang()->getLocale();
|
||||
}
|
||||
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
31
domokits/local/modules/TheliaLibrary/Hook/BackHook.php
Normal file
31
domokits/local/modules/TheliaLibrary/Hook/BackHook.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Hook;
|
||||
|
||||
use Thelia\Core\Event\Hook\HookRenderEvent;
|
||||
use Thelia\Core\Hook\BaseHook;
|
||||
|
||||
class BackHook extends BaseHook
|
||||
{
|
||||
public function onItemEdition(HookRenderEvent $event): void
|
||||
{
|
||||
if (!$this->getRequest()->get('force_legacy_imagemanager')) {
|
||||
$content = $this->render('item-edition.html', [
|
||||
'itemType' => $event->getArgument('itemType'),
|
||||
'itemId' => $event->getArgument('itemId'),
|
||||
]);
|
||||
|
||||
$event->add($content);
|
||||
}
|
||||
}
|
||||
}
|
||||
15
domokits/local/modules/TheliaLibrary/I18n/en_US.php
Executable file
15
domokits/local/modules/TheliaLibrary/I18n/en_US.php
Executable file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
return [
|
||||
// 'an english string' => 'The displayed english string',
|
||||
];
|
||||
15
domokits/local/modules/TheliaLibrary/I18n/fr_FR.php
Executable file
15
domokits/local/modules/TheliaLibrary/I18n/fr_FR.php
Executable file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
return [
|
||||
// 'an english string' => 'La traduction française de la chaine',
|
||||
];
|
||||
145
domokits/local/modules/TheliaLibrary/Loop/LibraryImage.php
Executable file
145
domokits/local/modules/TheliaLibrary/Loop/LibraryImage.php
Executable file
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Loop;
|
||||
|
||||
use Thelia\Action\Image;
|
||||
use Thelia\Core\Template\Element\BaseI18nLoop;
|
||||
use Thelia\Core\Template\Element\LoopResult;
|
||||
use Thelia\Core\Template\Element\LoopResultRow;
|
||||
use Thelia\Core\Template\Element\PropelSearchLoopInterface;
|
||||
use Thelia\Core\Template\Loop\Argument\Argument;
|
||||
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
|
||||
use Thelia\Type\EnumType;
|
||||
use Thelia\Type\TypeCollection;
|
||||
use TheliaLibrary\Model\LibraryImage as LibraryImageModel;
|
||||
use TheliaLibrary\Model\LibraryImageQuery;
|
||||
use TheliaLibrary\Model\LibraryItemImageQuery;
|
||||
use TheliaLibrary\Service\LibraryImageService;
|
||||
|
||||
/**
|
||||
* Class LibraryImage.
|
||||
*
|
||||
* @method int getId()
|
||||
* @method int getItemId()
|
||||
* @method string getItemType()
|
||||
* @method string getCode()
|
||||
* @method bool getOnlyVisible()
|
||||
* @method int getWidth()
|
||||
* @method int getHeight()
|
||||
*/
|
||||
class LibraryImage extends BaseI18nLoop implements PropelSearchLoopInterface
|
||||
{
|
||||
protected function getArgDefinitions()
|
||||
{
|
||||
return new ArgumentCollection(
|
||||
Argument::createIntTypeArgument('id'),
|
||||
Argument::createIntTypeArgument('item_id'),
|
||||
Argument::createAlphaNumStringTypeArgument('item_type'),
|
||||
Argument::createAlphaNumStringTypeArgument('code'),
|
||||
Argument::createBooleanTypeArgument('only_visible'),
|
||||
Argument::createIntTypeArgument('width'),
|
||||
Argument::createIntTypeArgument('height'),
|
||||
Argument::createAlphaNumStringTypeArgument('format'),
|
||||
new Argument(
|
||||
'resize_mode',
|
||||
new TypeCollection(
|
||||
new EnumType([
|
||||
Image::EXACT_RATIO_WITH_BORDERS,
|
||||
Image::EXACT_RATIO_WITH_CROP,
|
||||
Image::KEEP_IMAGE_RATIO,
|
||||
])
|
||||
),
|
||||
'none'
|
||||
),
|
||||
Argument::createBooleanTypeArgument('allow_zoom', false),
|
||||
);
|
||||
}
|
||||
|
||||
public function buildModelCriteria()
|
||||
{
|
||||
$query = LibraryImageQuery::create();
|
||||
|
||||
if (null !== $id = $this->getId()) {
|
||||
$query->filterById($id);
|
||||
}
|
||||
|
||||
if (null !== $itemId = $this->getItemId()) {
|
||||
$query = $this->getOrInitItemJoin($query)->filterByItemId($itemId);
|
||||
}
|
||||
|
||||
if (null !== $itemType = $this->getItemType()) {
|
||||
$query = $this->getOrInitItemJoin($query)->filterByItemType($itemType);
|
||||
}
|
||||
|
||||
if (null !== $code = $this->getCode()) {
|
||||
$query = $this->getOrInitItemJoin($query)->filterByCode($code);
|
||||
}
|
||||
|
||||
if (true === $this->getOnlyVisible()) {
|
||||
$query = $this->getOrInitItemJoin($query)->filterByVisible(true);
|
||||
}
|
||||
|
||||
if ($query instanceof LibraryItemImageQuery) {
|
||||
$query->orderByPosition();
|
||||
$query = $query->endUse();
|
||||
}
|
||||
|
||||
$this->configureI18nProcessing(
|
||||
$query,
|
||||
[
|
||||
'TITLE',
|
||||
'FILE_NAME',
|
||||
]
|
||||
);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
{
|
||||
/** @var LibraryImageModel $image */
|
||||
foreach ($loopResult->getResultDataCollection() as $image) {
|
||||
/** @var LibraryImageService $libraryImageService */
|
||||
$libraryImageService = $this->container->get('thelia_library_image');
|
||||
$imageUrl = $libraryImageService->getImagePublicUrl(
|
||||
$image,
|
||||
$this->getWidth(),
|
||||
$this->getHeight(),
|
||||
$this->getFormat()
|
||||
);
|
||||
|
||||
$row = new LoopResultRow($image);
|
||||
$row
|
||||
->set('ID', $image->getId())
|
||||
->set('TITLE', $image->getVirtualColumn('i18n_TITLE'))
|
||||
->set('FILE_NAME', $image->getVirtualColumn('i18n_FILE_NAME'))
|
||||
->set('URL', $imageUrl)
|
||||
;
|
||||
|
||||
$this->addOutputFields($row, $image);
|
||||
|
||||
$loopResult->addRow($row);
|
||||
}
|
||||
|
||||
return $loopResult;
|
||||
}
|
||||
|
||||
protected function getOrInitItemJoin($query): LibraryItemImageQuery
|
||||
{
|
||||
if ($query instanceof LibraryItemImageQuery) {
|
||||
return $query;
|
||||
}
|
||||
|
||||
return $query->useLibraryItemImageQuery();
|
||||
}
|
||||
}
|
||||
233
domokits/local/modules/TheliaLibrary/Model/Api/LibraryImage.php
Executable file
233
domokits/local/modules/TheliaLibrary/Model/Api/LibraryImage.php
Executable file
@@ -0,0 +1,233 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model\Api;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Constraint;
|
||||
use OpenApi\Model\Api\BaseApiModel;
|
||||
use OpenApi\Model\Api\ModelFactory;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\Validator\Validator\ValidatorInterface;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Thelia\TaxEngine\TaxEngine;
|
||||
use TheliaLibrary\Model\LibraryImageTagQuery;
|
||||
use TheliaLibrary\Model\LibraryTagQuery;
|
||||
use TheliaLibrary\Service\LibraryImageService;
|
||||
|
||||
/**
|
||||
* Class LibraryImage.
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="LibraryImage",
|
||||
* title="LibraryImage",
|
||||
* )
|
||||
*/
|
||||
class LibraryImage extends BaseApiModel
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $fileName;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $url = null;
|
||||
|
||||
protected $width = null;
|
||||
protected $height = null;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* @OA\Property(
|
||||
* readOnly=true,
|
||||
* type="array",
|
||||
* @OA\Items(type="string")
|
||||
* )
|
||||
*/
|
||||
protected $tags = [];
|
||||
|
||||
/**
|
||||
* @var LibraryImageService
|
||||
*/
|
||||
protected $libraryImageService;
|
||||
|
||||
public function __construct(
|
||||
ModelFactory $modelFactory,
|
||||
RequestStack $requestStack,
|
||||
TaxEngine $taxEngine,
|
||||
EventDispatcherInterface $dispatcher,
|
||||
LibraryImageService $libraryImageService,
|
||||
ValidatorInterface $validator
|
||||
) {
|
||||
parent::__construct($modelFactory, $requestStack, $taxEngine, $dispatcher, $validator);
|
||||
$this->libraryImageService = $libraryImageService;
|
||||
}
|
||||
|
||||
public function createOrUpdateFromData($data, $locale = null): void
|
||||
{
|
||||
parent::createOrUpdateFromData($data, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(int $id): self
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle(?string $title): self
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFileName(): ?string
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
|
||||
public function setFileName(?string $fileName = null): self
|
||||
{
|
||||
$this->fileName = $fileName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl(): ?string
|
||||
{
|
||||
return $this->libraryImageService->getImagePublicUrl($this->getTheliaModel(), $this->width, $this->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $width
|
||||
*/
|
||||
public function setWidth($width): void
|
||||
{
|
||||
$this->width = $width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $height
|
||||
*/
|
||||
public function setHeight($height): void
|
||||
{
|
||||
$this->height = $height;
|
||||
}
|
||||
|
||||
public function getTags(): array
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $tags
|
||||
*/
|
||||
public function setTags($tags): void
|
||||
{
|
||||
$this->tags = $tags;
|
||||
}
|
||||
|
||||
protected function getTheliaModel($propelModelName = null)
|
||||
{
|
||||
return parent::getTheliaModel(\TheliaLibrary\Model\LibraryImage::class);
|
||||
}
|
||||
|
||||
public function createFromTheliaModel($theliaModel, $locale = null): void
|
||||
{
|
||||
parent::createFromTheliaModel($theliaModel, $locale);
|
||||
|
||||
$tags = array_map(
|
||||
function ($item) use ($locale) {
|
||||
$query = LibraryTagQuery::create()
|
||||
->filterById($item['TagId'])
|
||||
->useI18nQuery()
|
||||
->filterByLocale($locale)
|
||||
->filterById($item['TagId'])
|
||||
->endUse()
|
||||
->with('LibraryTagI18n');
|
||||
|
||||
$tag = $query->find()->getFirst();
|
||||
$association = LibraryImageTagQuery::create()->filterByImageId($this->getId())->filterByTagId($tag->getId())->findOne();
|
||||
|
||||
return [
|
||||
'tag' => [
|
||||
'id' => $tag->getId(),
|
||||
'title' => $tag->getTitle(),
|
||||
'colorCode' => $tag->getColorCode(),
|
||||
],
|
||||
'imageTag' => [
|
||||
'id' => $association->getId(),
|
||||
'imageId' => $this->getId(),
|
||||
'tagId' => $tag->getId(),
|
||||
],
|
||||
];
|
||||
},
|
||||
LibraryImageTagQuery::create()
|
||||
->filterByImageId($this->getId())
|
||||
->find()
|
||||
->toArray()
|
||||
);
|
||||
|
||||
$this->setTags($tags);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model\Api;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Constraint;
|
||||
use OpenApi\Model\Api\BaseApiModel;
|
||||
|
||||
/**
|
||||
* Class LibraryImageTag.
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="LibraryImageTag",
|
||||
* title="LibraryImageTag",
|
||||
* )
|
||||
*/
|
||||
class LibraryImageTag extends BaseApiModel
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $imageId;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $tagId;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(int $id): self
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getImageId(): ?int
|
||||
{
|
||||
return $this->imageId;
|
||||
}
|
||||
|
||||
public function setImageId(int $id): self
|
||||
{
|
||||
$this->imageId = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTagId(): ?int
|
||||
{
|
||||
return $this->tagId;
|
||||
}
|
||||
|
||||
public function setTagId(int $tagId): self
|
||||
{
|
||||
$this->tagId = $tagId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
213
domokits/local/modules/TheliaLibrary/Model/Api/LibraryItemImage.php
Executable file
213
domokits/local/modules/TheliaLibrary/Model/Api/LibraryItemImage.php
Executable file
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model\Api;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Constraint;
|
||||
use OpenApi\Model\Api\BaseApiModel;
|
||||
|
||||
/**
|
||||
* Class LibraryItemImage.
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="LibraryItemImage",
|
||||
* title="LibraryItemImage",
|
||||
* )
|
||||
*/
|
||||
class LibraryItemImage extends BaseApiModel
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
*/
|
||||
protected $imageId;
|
||||
|
||||
/**
|
||||
* @var LibraryImage
|
||||
* @OA\Property(
|
||||
* readOnly=true,
|
||||
* ref="#/components/schemas/LibraryImage"
|
||||
* )
|
||||
*/
|
||||
protected $image;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $itemType;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
*/
|
||||
protected $itemId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* @OA\Property(
|
||||
* type="boolean",
|
||||
* )
|
||||
*/
|
||||
protected $visible = true;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
*/
|
||||
protected $position;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LibraryImage
|
||||
*/
|
||||
public function setId(int $id): self
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getImageId(): int
|
||||
{
|
||||
return $this->imageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LibraryImage
|
||||
*/
|
||||
public function getImage(): ?LibraryImage
|
||||
{
|
||||
return $this->image;
|
||||
}
|
||||
|
||||
public function setLibraryImage(LibraryImage $image): self
|
||||
{
|
||||
$this->image = $image;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setImageId(int $imageId): self
|
||||
{
|
||||
$this->imageId = $imageId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getItemType(): string
|
||||
{
|
||||
return $this->itemType;
|
||||
}
|
||||
|
||||
public function setItemType(string $itemType): self
|
||||
{
|
||||
$this->itemType = $itemType;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getItemId(): int
|
||||
{
|
||||
return $this->itemId;
|
||||
}
|
||||
|
||||
public function setItemId(int $itemId): self
|
||||
{
|
||||
$this->itemId = $itemId;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCode(): ?string
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
public function setCode(?string $code): self
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isVisible(): bool
|
||||
{
|
||||
return $this->visible;
|
||||
}
|
||||
|
||||
public function setVisible(bool $visible = true): self
|
||||
{
|
||||
$this->visible = $visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPosition(): ?int
|
||||
{
|
||||
return $this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $position
|
||||
*/
|
||||
public function setPosition(?int $position): self
|
||||
{
|
||||
$this->position = $position;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function getTheliaModel($propelModelName = null)
|
||||
{
|
||||
return parent::getTheliaModel(\TheliaLibrary\Model\LibraryItemImage::class);
|
||||
}
|
||||
}
|
||||
101
domokits/local/modules/TheliaLibrary/Model/Api/LibraryTag.php
Normal file
101
domokits/local/modules/TheliaLibrary/Model/Api/LibraryTag.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model\Api;
|
||||
|
||||
use OpenApi\Annotations as OA;
|
||||
use OpenApi\Constraint;
|
||||
use OpenApi\Model\Api\BaseApiModel;
|
||||
|
||||
/**
|
||||
* Class LibraryTag.
|
||||
*
|
||||
* @OA\Schema(
|
||||
* schema="LibraryTag",
|
||||
* title="LibraryTag",
|
||||
* )
|
||||
*/
|
||||
class LibraryTag extends BaseApiModel
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
* @OA\Property(
|
||||
* type="integer",
|
||||
* )
|
||||
* @Constraint\NotBlank(groups={"read"})
|
||||
*/
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $title;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* @OA\Property(
|
||||
* type="string",
|
||||
* )
|
||||
*/
|
||||
protected $colorCode;
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setId(int $id): self
|
||||
{
|
||||
$this->id = $id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTitle(): ?string
|
||||
{
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $title
|
||||
*/
|
||||
public function setTitle(?string $title): self
|
||||
{
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getColorCode(): ?string
|
||||
{
|
||||
return $this->colorCode;
|
||||
}
|
||||
|
||||
public function setColorCode(?string $colorCode = null): self
|
||||
{
|
||||
$this->colorCode = $colorCode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryImage.php
Executable file
26
domokits/local/modules/TheliaLibrary/Model/LibraryImage.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImage as BaseLibraryImage;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_image' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImage extends BaseLibraryImage
|
||||
{
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageI18n.php
Executable file
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageI18n.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImageI18n as BaseLibraryImageI18n;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_image_i18n' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImageI18n extends BaseLibraryImageI18n
|
||||
{
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageI18nQuery.php
Executable file
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageI18nQuery.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImageI18nQuery as BaseLibraryImageI18nQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_image_i18n' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImageI18nQuery extends BaseLibraryImageI18nQuery
|
||||
{
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageQuery.php
Executable file
26
domokits/local/modules/TheliaLibrary/Model/LibraryImageQuery.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImageQuery as BaseLibraryImageQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_image' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImageQuery extends BaseLibraryImageQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImageTag as BaseLibraryImageTag;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_image_tag' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImageTag extends BaseLibraryImageTag
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryImageTagQuery as BaseLibraryImageTagQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_image_tag' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryImageTagQuery extends BaseLibraryImageTagQuery
|
||||
{
|
||||
}
|
||||
65
domokits/local/modules/TheliaLibrary/Model/LibraryItemImage.php
Executable file
65
domokits/local/modules/TheliaLibrary/Model/LibraryItemImage.php
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Thelia\Model\Tools\PositionManagementTrait;
|
||||
use TheliaLibrary\Model\Base\LibraryItemImage as BaseLibraryItemImage;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_item_image' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryItemImage extends BaseLibraryItemImage
|
||||
{
|
||||
use PositionManagementTrait;
|
||||
|
||||
/**
|
||||
* Calculate next position relative to our product.
|
||||
*/
|
||||
protected function addCriteriaToPositionQuery($query): void
|
||||
{
|
||||
/* @var $query LibraryItemImageQuery */
|
||||
$query->filterByItemId($this->getItemId())
|
||||
->filterByItemType($this->getItemType());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function preInsert(ConnectionInterface $con = null)
|
||||
{
|
||||
$this->setPosition($this->getNextPosition());
|
||||
|
||||
parent::preInsert($con);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function preDelete(ConnectionInterface $con = null)
|
||||
{
|
||||
parent::preDelete($con);
|
||||
|
||||
$this->reorderBeforeDelete(
|
||||
[
|
||||
'item_id' => $this->getItemId(),
|
||||
'item_type' => $this->getItemType(),
|
||||
]
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryItemImageQuery.php
Executable file
26
domokits/local/modules/TheliaLibrary/Model/LibraryItemImageQuery.php
Executable file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryItemImageQuery as BaseLibraryItemImageQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_item_image' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryItemImageQuery extends BaseLibraryItemImageQuery
|
||||
{
|
||||
}
|
||||
26
domokits/local/modules/TheliaLibrary/Model/LibraryTag.php
Normal file
26
domokits/local/modules/TheliaLibrary/Model/LibraryTag.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryTag as BaseLibraryTag;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_tag' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryTag extends BaseLibraryTag
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryTagI18n as BaseLibraryTagI18n;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for representing a row from the 'library_tag_i18n' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryTagI18n extends BaseLibraryTagI18n
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryTagI18nQuery as BaseLibraryTagI18nQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_tag_i18n' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryTagI18nQuery extends BaseLibraryTagI18nQuery
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Model;
|
||||
|
||||
use TheliaLibrary\Model\Base\LibraryTagQuery as BaseLibraryTagQuery;
|
||||
|
||||
/**
|
||||
* Skeleton subclass for performing query and update operations on the 'library_tag' table.
|
||||
*
|
||||
* You should add additional methods to this class to meet the
|
||||
* application requirements. This class will only be generated as
|
||||
* long as it does not already exist in the output directory.
|
||||
*/
|
||||
class LibraryTagQuery extends BaseLibraryTagQuery
|
||||
{
|
||||
}
|
||||
15
domokits/local/modules/TheliaLibrary/Readme.md
Executable file
15
domokits/local/modules/TheliaLibrary/Readme.md
Executable file
@@ -0,0 +1,15 @@
|
||||
# Thelia Library
|
||||
|
||||
Add a media library on Thelia.
|
||||
|
||||
### Composer
|
||||
|
||||
Add it in your main thelia composer.json file
|
||||
|
||||
```
|
||||
composer require thelia/thelia-library-module:~1.0.0
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
For now this module doesn't have an interface, only an api documented on {your_website_url}/open_api/doc
|
||||
325
domokits/local/modules/TheliaLibrary/Service/ImageService.php
Executable file
325
domokits/local/modules/TheliaLibrary/Service/ImageService.php
Executable file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Service;
|
||||
|
||||
use Imagine\Gd\Imagine;
|
||||
use Imagine\Gmagick\Imagine as GmagickImagine;
|
||||
use Imagine\Image\Box;
|
||||
use Imagine\Image\ImageInterface;
|
||||
use Imagine\Image\Palette\RGB;
|
||||
use Imagine\Image\Point;
|
||||
use Imagine\Imagick\Imagine as ImagickImagine;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Thelia\Model\ConfigQuery;
|
||||
use Thelia\Model\Lang;
|
||||
use TheliaLibrary\Model\LibraryImage;
|
||||
use TheliaLibrary\Model\LibraryImageQuery;
|
||||
use TheliaLibrary\TheliaLibrary;
|
||||
|
||||
class ImageService
|
||||
{
|
||||
public const MAX_ALLOWED_SIZE_FACTOR = 2;
|
||||
|
||||
public function __construct(private RequestStack $requestStack)
|
||||
{
|
||||
}
|
||||
|
||||
public function getUrlForImage(
|
||||
$identifier,
|
||||
$format,
|
||||
$region = 'full',
|
||||
$size = 'max',
|
||||
$rotation = 0,
|
||||
$quality = 'default'
|
||||
) {
|
||||
return "/image-library/$identifier/$region/$size/$rotation/$quality.$format";
|
||||
}
|
||||
|
||||
public function geFormattedImage(
|
||||
$identifier,
|
||||
$region,
|
||||
$size,
|
||||
$rotation,
|
||||
$quality,
|
||||
$format
|
||||
) {
|
||||
if (!\in_array(strtolower($format), ['jpg', 'jpeg', 'png', 'gif', 'jp2', 'webp'])) {
|
||||
throw new HttpException(400, 'Bad format value');
|
||||
}
|
||||
|
||||
$formattedImagePath = THELIA_WEB_DIR.'image-library'.DS.$identifier.DS.$region.DS.$size.DS.$rotation;
|
||||
if (!is_dir($formattedImagePath)) {
|
||||
if (!@mkdir($formattedImagePath, 0755, true)) {
|
||||
throw new \RuntimeException(sprintf('Failed to create %s file in cache directory', $formattedImagePath));
|
||||
}
|
||||
}
|
||||
|
||||
$formattedImagePath .= DS.$quality.'.'.$format;
|
||||
|
||||
if (file_exists($formattedImagePath)) {
|
||||
return $formattedImagePath;
|
||||
}
|
||||
|
||||
$image = $this->openImage($identifier);
|
||||
$image = $this->applyRegion($image, $region);
|
||||
$image = $this->applySize($image, $size);
|
||||
$image = $this->applyRotation($image, $rotation, $format);
|
||||
$image = $this->applyQuality($image, $quality);
|
||||
$image->save($formattedImagePath);
|
||||
|
||||
return $formattedImagePath;
|
||||
}
|
||||
|
||||
public function applyRegion(ImageInterface $image, $region)
|
||||
{
|
||||
if ($region === 'full') {
|
||||
return $image;
|
||||
}
|
||||
|
||||
$height = $image->getSize()->getHeight();
|
||||
$width = $image->getSize()->getWidth();
|
||||
|
||||
if ($region === 'square') {
|
||||
$squareSize = min($width, $height);
|
||||
|
||||
return $image->crop(
|
||||
new Point(($width - $squareSize) / 2, ($height - $squareSize) / 2),
|
||||
new Box($squareSize, $squareSize)
|
||||
);
|
||||
}
|
||||
|
||||
// If region start with pct: values are percent of size
|
||||
$regionMode = strpos($region, 'pct:') === false ? 'value' : 'percentage';
|
||||
$values = explode(',', str_replace('pct:', '', $region));
|
||||
|
||||
if (\count($values) !== 4) {
|
||||
throw new HttpException(400, 'Bad region value');
|
||||
}
|
||||
|
||||
$xPositionValue = $regionMode === 'value' ? $values[0] : $width * $values[0] / 100;
|
||||
$yPositionValue = $regionMode === 'value' ? $values[1] : $height * $values[1] / 100;
|
||||
|
||||
$widthValue = $regionMode === 'value' ? $values[2] : $width * $values[2] / 100;
|
||||
$heightValue = $regionMode === 'value' ? $values[3] : $height * $values[3] / 100;
|
||||
|
||||
// If width or height + start position go outside of image crop the width and/or height
|
||||
if (($xPositionValue + $widthValue) > $width) {
|
||||
$widthValue = $width - $xPositionValue;
|
||||
}
|
||||
if (($yPositionValue + $heightValue) > $height) {
|
||||
$heightValue = $height - $yPositionValue;
|
||||
}
|
||||
|
||||
if ($height <= 0 || $width <= 0) {
|
||||
throw new HttpException(400, 'Size out of bound');
|
||||
}
|
||||
|
||||
return $image->crop(
|
||||
new Point($xPositionValue, $yPositionValue),
|
||||
new Box($widthValue, $heightValue)
|
||||
);
|
||||
}
|
||||
|
||||
public function applySize(ImageInterface $image, $size)
|
||||
{
|
||||
$upscaleMode = false !== strpos($size, '^');
|
||||
$keepAspectRatio = false !== strpos($size, '!');
|
||||
$borders = false !== strpos($size, '*');
|
||||
$size = str_replace('^', '', $size);
|
||||
$size = str_replace('!', '', $size);
|
||||
$size = str_replace('*', '', $size);
|
||||
|
||||
if ($size === 'max') {
|
||||
if (!$upscaleMode) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
return $image->resize($this->getMaxSize($image));
|
||||
}
|
||||
|
||||
$width = $image->getSize()->getWidth();
|
||||
$height = $image->getSize()->getHeight();
|
||||
|
||||
if (false !== strpos($size, 'pct:')) {
|
||||
$values = explode(':', $size);
|
||||
if (!isset($values[1])) {
|
||||
throw new HttpException(400, 'Bad size values');
|
||||
}
|
||||
|
||||
$percent = $values[1];
|
||||
|
||||
if (!$upscaleMode && $percent > 100) {
|
||||
throw new HttpException(400, 'Size out of bound');
|
||||
}
|
||||
|
||||
return $image->resize(
|
||||
new Box(
|
||||
$percent * $width / 100,
|
||||
$percent * $height / 100,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$values = explode(',', $size);
|
||||
|
||||
if (\count($values) !== 2) {
|
||||
throw new HttpException(400, 'Bad size values');
|
||||
}
|
||||
|
||||
$newWidth = $values[0] != '' ? $values[0] : $values[1];
|
||||
$newHeight = $values[1] != '' ? $values[1] : $values[0];
|
||||
|
||||
if ($keepAspectRatio) {
|
||||
$originalRatio = $width / $height;
|
||||
$askedRatio = $newWidth / $newHeight;
|
||||
// Keep the ratio and take the larger image possible but not greater than asked width and height
|
||||
$newWidth = $askedRatio <= $originalRatio ? $newWidth : $newHeight * $originalRatio;
|
||||
$newHeight = $askedRatio >= $originalRatio ? $newHeight : $newWidth / $originalRatio;
|
||||
}
|
||||
|
||||
if (!$upscaleMode && ($newWidth > $width || $newHeight > $height)) {
|
||||
throw new HttpException(400, 'Size out of bound');
|
||||
}
|
||||
|
||||
$resizedImage = $image->resize(
|
||||
new Box(
|
||||
$newWidth,
|
||||
$newHeight,
|
||||
)
|
||||
);
|
||||
|
||||
if ($borders) {
|
||||
$palette = new RGB();
|
||||
$canvas = new Box($values[0], $values[1]);
|
||||
$canvasInstance = $this->getImagineInstance()
|
||||
->create($canvas, $palette->color('fff', 0));
|
||||
|
||||
$borderWidth = (int) (($values[0] - $resizedImage->getSize()->getWidth()) / 2);
|
||||
$borderHeight = (int) (($values[1] - $resizedImage->getSize()->getHeight()) / 2);
|
||||
|
||||
return $canvasInstance
|
||||
->paste($resizedImage, new Point($borderWidth, $borderHeight));
|
||||
}
|
||||
|
||||
return $resizedImage;
|
||||
}
|
||||
|
||||
public function applyRotation(ImageInterface $image, $rotation, $format)
|
||||
{
|
||||
if (false !== strpos($rotation, '!')) {
|
||||
$image = $image->flipHorizontally();
|
||||
}
|
||||
|
||||
$rotation = str_replace('!', '', $rotation);
|
||||
|
||||
if (!is_numeric($rotation)) {
|
||||
throw new HttpException(400, 'Bad rotation values');
|
||||
}
|
||||
|
||||
$rotationValue = (float) $rotation;
|
||||
|
||||
if (0 > $rotationValue || $rotationValue > 360) {
|
||||
throw new HttpException(400, 'Rotation out of bound');
|
||||
}
|
||||
|
||||
$color = new RGB();
|
||||
$alpha = \in_array(
|
||||
strtolower($format),
|
||||
[
|
||||
'png',
|
||||
'gif',
|
||||
'webp',
|
||||
'tiff',
|
||||
'jp2',
|
||||
]
|
||||
) ? 0 : 100;
|
||||
|
||||
return $image->rotate($rotationValue, $color->color('fff', $alpha));
|
||||
}
|
||||
|
||||
public function applyQuality(ImageInterface $image, $quality)
|
||||
{
|
||||
if (!\in_array($quality, ['color', 'gray', 'default', 'bitonal'])) {
|
||||
throw new HttpException(400, 'Bad quality values');
|
||||
}
|
||||
|
||||
if ($quality === 'gray') {
|
||||
$image->effects()->grayscale();
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
public function getImageFileName(
|
||||
LibraryImage $image = null
|
||||
) {
|
||||
if (null == $image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$locale = $this->requestStack?->getCurrentRequest()?->getSession()?->getLang()->getLocale();
|
||||
|
||||
if (null !== $locale) {
|
||||
$image->setLocale($locale);
|
||||
}
|
||||
|
||||
$fileName = $image->getFileName();
|
||||
|
||||
if (null === $fileName) {
|
||||
$fileName = $image->setLocale(Lang::getDefaultLanguage()->getLocale())->getFileName() ?? null;
|
||||
$image->setLocale($locale);
|
||||
}
|
||||
|
||||
return $fileName;
|
||||
}
|
||||
|
||||
public function openImage($identifier)
|
||||
{
|
||||
$imageModel = LibraryImageQuery::create()
|
||||
->filterById($identifier)
|
||||
->findOne();
|
||||
|
||||
if (null === $imageModel) {
|
||||
throw new HttpException(404, 'Image not found');
|
||||
}
|
||||
|
||||
$fileName = $this->getImageFileName($imageModel);
|
||||
|
||||
return $this->getImagineInstance()->open(TheliaLibrary::getImageDirectory().$fileName);
|
||||
}
|
||||
|
||||
public function getImagineInstance()
|
||||
{
|
||||
$driver = ConfigQuery::read('imagine_graphic_driver', 'gd');
|
||||
|
||||
switch ($driver) {
|
||||
case 'imagick':
|
||||
$image = new ImagickImagine();
|
||||
break;
|
||||
case 'gmagick':
|
||||
$image = new GmagickImagine();
|
||||
break;
|
||||
case 'gd':
|
||||
default:
|
||||
$image = new Imagine();
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
public function getMaxSize(ImageInterface $image)
|
||||
{
|
||||
return new Box($image->getSize()->getWidth() * 2, $image->getSize()->getHeight() * 2);
|
||||
}
|
||||
}
|
||||
172
domokits/local/modules/TheliaLibrary/Service/LibraryImageService.php
Executable file
172
domokits/local/modules/TheliaLibrary/Service/LibraryImageService.php
Executable file
@@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Service;
|
||||
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use TheliaLibrary\Model\LibraryImage;
|
||||
use TheliaLibrary\Model\LibraryImageI18nQuery;
|
||||
use TheliaLibrary\Model\LibraryImageQuery;
|
||||
use TheliaLibrary\TheliaLibrary;
|
||||
|
||||
class LibraryImageService
|
||||
{
|
||||
public const LIBRARY_IMAGE_DIR = THELIA_WEB_DIR.'library'.DS.'images'.DS;
|
||||
public const LIBRARY_IMAGE_BASE_ROUTE = '/library/images/';
|
||||
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
protected RequestStack $requestStack;
|
||||
|
||||
protected ImageService $imageService;
|
||||
|
||||
public function __construct(
|
||||
EventDispatcherInterface $eventDispatcher,
|
||||
RequestStack $requestStack,
|
||||
ImageService $imageService
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->requestStack = $requestStack;
|
||||
$this->imageService = $imageService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function createImage(
|
||||
File $file,
|
||||
string $title = null,
|
||||
string $locale = null
|
||||
): LibraryImage {
|
||||
return $this->createOrUpdateImage($file, $title, $locale);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateImage(
|
||||
$imageId,
|
||||
File $file = null,
|
||||
string $title = null,
|
||||
string $locale = null
|
||||
): LibraryImage {
|
||||
return $this->createOrUpdateImage($file, $title, $locale, $imageId);
|
||||
}
|
||||
|
||||
public function deleteImage(
|
||||
$imageId
|
||||
): bool {
|
||||
$image = LibraryImageQuery::create()
|
||||
->filterById($imageId)
|
||||
->findOne();
|
||||
|
||||
if (null === $image) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageFiles = LibraryImageI18nQuery::create()->filterById($imageId)
|
||||
->find();
|
||||
|
||||
foreach ($imageFiles as $imageFile) {
|
||||
if (null === $imageFile->getFileName()) {
|
||||
continue;
|
||||
}
|
||||
$fileSystem = new Filesystem();
|
||||
$fileSystem->remove(TheliaLibrary::getImageDirectory().$imageFile->getFileName());
|
||||
}
|
||||
|
||||
$image->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getImagePublicUrl(
|
||||
LibraryImage $image = null,
|
||||
$width = null,
|
||||
$height = null,
|
||||
$format = null
|
||||
) {
|
||||
if (null == $image) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$fileName = $this->imageService->getImageFileName($image);
|
||||
|
||||
$format = $format ?? pathinfo($fileName, \PATHINFO_EXTENSION);
|
||||
$size = 'max';
|
||||
if ($width || $height) {
|
||||
$size = $width.','.$height;
|
||||
}
|
||||
|
||||
return $this->imageService->getUrlForImage($image->getId(), $format, 'full', $size);
|
||||
}
|
||||
|
||||
protected function createOrUpdateImage(
|
||||
File $file = null,
|
||||
string $title = null,
|
||||
string $locale = null,
|
||||
int $imageId = null
|
||||
) {
|
||||
$image = null !== $imageId
|
||||
? LibraryImageQuery::create()->filterById($imageId)->findOne()
|
||||
: (new LibraryImage());
|
||||
|
||||
if (null === $image) {
|
||||
throw new \Exception(Translator::getInstance()->trans("Can't update an image that doesn't exist"));
|
||||
}
|
||||
|
||||
if (null == $locale) {
|
||||
$locale = $this->requestStack->getCurrentRequest()->getSession()->getAdminEditionLang()->getLocale();
|
||||
}
|
||||
|
||||
$image->setLocale($locale);
|
||||
$imageName = null;
|
||||
|
||||
if (null !== $file) {
|
||||
$fileName = method_exists($file, 'getClientOriginalName') ? $file->getClientOriginalName() : $file->getFilename();
|
||||
|
||||
// Remove old file if already exist for this locale
|
||||
if (null !== $image->getFileName()) {
|
||||
$fileSystem = new Filesystem();
|
||||
$fileSystem->remove(TheliaLibrary::getImageDirectory().$image->getFileName());
|
||||
}
|
||||
$imageName = bin2hex(random_bytes(5)).'_'.$fileName;
|
||||
$file->move(TheliaLibrary::getImageDirectory(), $imageName);
|
||||
if (null === $title && null === $image->getTitle()) {
|
||||
$title = $fileName;
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $imageName && null !== $imageId) {
|
||||
$i18nWithFilename = LibraryImageI18nQuery::create()
|
||||
->filterById($imageId)
|
||||
->filterByFileName(null, Criteria::ISNOTNULL)
|
||||
->findOne();
|
||||
|
||||
$imageName = $i18nWithFilename?->getFileName();
|
||||
}
|
||||
|
||||
if (null != $title) {
|
||||
$image->setTitle($title);
|
||||
}
|
||||
|
||||
$image->setFileName($imageName);
|
||||
$image->save();
|
||||
|
||||
return $image;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Service;
|
||||
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use TheliaLibrary\Model\LibraryImageTag;
|
||||
use TheliaLibrary\Model\LibraryImageTagQuery;
|
||||
|
||||
class LibraryImageTagService
|
||||
{
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
public function __construct(
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
}
|
||||
|
||||
public function associateImage(
|
||||
string $imageId,
|
||||
string $tagId
|
||||
): LibraryImageTag {
|
||||
$imageTag = (new LibraryImageTag())
|
||||
->setImageId($imageId)
|
||||
->setTagId($tagId);
|
||||
|
||||
$imageTag->save();
|
||||
|
||||
return $imageTag;
|
||||
}
|
||||
|
||||
public function deleteImageAssociation(
|
||||
$tagImageId
|
||||
): bool {
|
||||
$imageTag = LibraryImageTagQuery::create()
|
||||
->filterById($tagImageId)
|
||||
->findOne();
|
||||
|
||||
if (null === $imageTag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$imageTag->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
148
domokits/local/modules/TheliaLibrary/Service/LibraryItemImageService.php
Executable file
148
domokits/local/modules/TheliaLibrary/Service/LibraryItemImageService.php
Executable file
@@ -0,0 +1,148 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Service;
|
||||
|
||||
use Symfony\Component\HttpFoundation\File\File;
|
||||
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use TheliaLibrary\Model\LibraryImageQuery;
|
||||
use TheliaLibrary\Model\LibraryItemImage;
|
||||
use TheliaLibrary\Model\LibraryItemImageQuery;
|
||||
|
||||
class LibraryItemImageService
|
||||
{
|
||||
protected LibraryImageService $libraryImageService;
|
||||
|
||||
protected EventDispatcherInterface $eventDispatcher;
|
||||
|
||||
public function __construct(
|
||||
LibraryImageService $libraryImageService,
|
||||
EventDispatcherInterface $eventDispatcher
|
||||
) {
|
||||
$this->eventDispatcher = $eventDispatcher;
|
||||
$this->libraryImageService = $libraryImageService;
|
||||
}
|
||||
|
||||
public function createAndAssociateImage(
|
||||
File $file,
|
||||
string $imageTitle = null,
|
||||
string $locale = null,
|
||||
$itemType,
|
||||
$itemId,
|
||||
$code = null,
|
||||
$visible = true,
|
||||
$position = null,
|
||||
$replaceOld = false
|
||||
): LibraryItemImage {
|
||||
if ($replaceOld) {
|
||||
$existingImages = LibraryImageQuery::create()
|
||||
->useLibraryItemImageQuery()
|
||||
->filterByItemType($itemType)
|
||||
->filterByItemId($itemId)
|
||||
->filterByCode($code)
|
||||
->endUse()
|
||||
->find();
|
||||
|
||||
if (!empty($existingImages)) {
|
||||
foreach ($existingImages as $existingImage) {
|
||||
$this->libraryImageService->deleteImage($existingImage->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$image = $this->libraryImageService->createImage($file, $imageTitle, $locale);
|
||||
|
||||
return $this->associateImage(
|
||||
$image->getId(),
|
||||
$itemType,
|
||||
$itemId,
|
||||
$code,
|
||||
$visible,
|
||||
$position
|
||||
);
|
||||
}
|
||||
|
||||
public function associateImage(
|
||||
$imageId,
|
||||
$itemType,
|
||||
$itemId,
|
||||
$code = null,
|
||||
$visible = true,
|
||||
$position = null
|
||||
): LibraryItemImage {
|
||||
$itemImage = (new LibraryItemImage())
|
||||
->setImageId($imageId)
|
||||
->setItemType($itemType)
|
||||
->setItemId($itemId)
|
||||
->setCode($code)
|
||||
->setVisible($visible);
|
||||
|
||||
$itemImage->save();
|
||||
|
||||
if (null != $position) {
|
||||
$itemImage->changeAbsolutePosition($position);
|
||||
}
|
||||
|
||||
return $itemImage;
|
||||
}
|
||||
|
||||
public function updateImageAssociation(
|
||||
$itemImageId,
|
||||
$code = null,
|
||||
$visible = true,
|
||||
$position = null,
|
||||
$positionMovement = null
|
||||
): LibraryItemImage {
|
||||
$itemImage = LibraryItemImageQuery::create()
|
||||
->filterById($itemImageId)
|
||||
->findOne();
|
||||
|
||||
if (null === $itemImage) {
|
||||
throw new \Exception(Translator::getInstance()->trans("Can't update an item image that doesn't exist"));
|
||||
}
|
||||
|
||||
$itemImage->setCode($code);
|
||||
$itemImage->setVisible($visible);
|
||||
$itemImage->save();
|
||||
|
||||
if (null != $position) {
|
||||
$itemImage->changeAbsolutePosition($position);
|
||||
}
|
||||
|
||||
if ('up' === strtolower($positionMovement)) {
|
||||
$itemImage->movePositionUp();
|
||||
}
|
||||
|
||||
if ('down' === strtolower($positionMovement)) {
|
||||
$itemImage->movePositionDown();
|
||||
}
|
||||
|
||||
return $itemImage;
|
||||
}
|
||||
|
||||
public function deleteImageAssociation(
|
||||
$itemImageId
|
||||
): bool {
|
||||
$itemImage = LibraryItemImageQuery::create()
|
||||
->filterById($itemImageId)
|
||||
->findOne();
|
||||
|
||||
if (null === $itemImage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$itemImage->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary\Service;
|
||||
|
||||
use Thelia\Core\Translation\Translator;
|
||||
use TheliaLibrary\Model\LibraryTag;
|
||||
use TheliaLibrary\Model\LibraryTagQuery;
|
||||
|
||||
class LibraryTagService
|
||||
{
|
||||
public function createTag(
|
||||
string $title,
|
||||
string $colorCode
|
||||
): LibraryTag {
|
||||
$imageTag = (new LibraryTag())
|
||||
->setTitle($title)
|
||||
->setColorCode($colorCode);
|
||||
|
||||
$imageTag->save();
|
||||
|
||||
return $imageTag;
|
||||
}
|
||||
|
||||
public function updateTag(
|
||||
int $tagId,
|
||||
string $title = null,
|
||||
string $colorCode = null
|
||||
): LibraryTag {
|
||||
$tag = LibraryTagQuery::create()
|
||||
->filterById($tagId)
|
||||
->findOne();
|
||||
|
||||
if (null === $tag) {
|
||||
throw new \Exception(Translator::getInstance()->trans("Can't update a tag that doesn't exist"));
|
||||
}
|
||||
|
||||
if (null != $title) {
|
||||
$tag->setTitle($title);
|
||||
}
|
||||
if (null != $colorCode) {
|
||||
$tag->setColorCode($colorCode);
|
||||
}
|
||||
|
||||
$tag->save();
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
public function deleteTag(
|
||||
$tagId
|
||||
): bool {
|
||||
$tag = LibraryTagQuery::create()
|
||||
->filterById($tagId)
|
||||
->findOne();
|
||||
|
||||
if (null === $tag) {
|
||||
throw new \Exception(Translator::getInstance()->trans("Can't delete a tag that doesn't exist"));
|
||||
}
|
||||
|
||||
$tag->delete();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
89
domokits/local/modules/TheliaLibrary/TheliaLibrary.php
Executable file
89
domokits/local/modules/TheliaLibrary/TheliaLibrary.php
Executable file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Thelia package.
|
||||
* http://www.thelia.net
|
||||
*
|
||||
* (c) OpenStudio <info@thelia.net>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace TheliaLibrary;
|
||||
|
||||
use Propel\Runtime\Connection\ConnectionInterface;
|
||||
use Symfony\Component\DependencyInjection\Loader\Configurator\ServicesConfigurator;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Thelia\Install\Database;
|
||||
use Thelia\Module\BaseModule;
|
||||
|
||||
class TheliaLibrary extends BaseModule
|
||||
{
|
||||
/** @var string */
|
||||
public const DOMAIN_NAME = 'thelialibrary';
|
||||
|
||||
public const DEFAULT_IMAGE_DIRECTORY = THELIA_LOCAL_DIR.'library/images/';
|
||||
|
||||
public function preActivation(ConnectionInterface $con = null): bool
|
||||
{
|
||||
if (!$this->getConfigValue('is_initialized', false)) {
|
||||
$database = new Database($con);
|
||||
|
||||
$database->insertSql(null, [__DIR__.'/Config/TheliaMain.sql']);
|
||||
|
||||
$this->setConfigValue('is_initialized', true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute sql files in Config/update/ folder named with module version (ex: 1.0.1.sql).
|
||||
*
|
||||
* @param $currentVersion
|
||||
* @param $newVersion
|
||||
*/
|
||||
public function update($currentVersion, $newVersion, ConnectionInterface $con = null): void
|
||||
{
|
||||
if (file_exists(__DIR__.DS.'Config'.DS.'update')) {
|
||||
$finder = Finder::create()
|
||||
->name('*.sql')
|
||||
->depth(0)
|
||||
->sortByName()
|
||||
->in(__DIR__.DS.'Config'.DS.'update');
|
||||
|
||||
$database = new Database($con);
|
||||
|
||||
/** @var \SplFileInfo $file */
|
||||
foreach ($finder as $file) {
|
||||
if (version_compare($currentVersion, $file->getBasename('.sql'), '<')) {
|
||||
$database->insertSql(null, [$file->getPathname()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function getImageDirectory(): string
|
||||
{
|
||||
return self::getConfigValue('image_directory', self::DEFAULT_IMAGE_DIRECTORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* You may now override BaseModuleInterface methods, such as:
|
||||
* install, destroy, preActivation, postActivation, preDeactivation, postDeactivation
|
||||
*
|
||||
* Have fun !
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines how services are loaded in your modules.
|
||||
*/
|
||||
public static function configureServices(ServicesConfigurator $servicesConfigurator): void
|
||||
{
|
||||
$servicesConfigurator->load(self::getModuleCode().'\\', __DIR__)
|
||||
->exclude([THELIA_MODULE_DIR.ucfirst(self::getModuleCode()).'/I18n/*'])
|
||||
->autowire(true)
|
||||
->autoconfigure(true);
|
||||
}
|
||||
}
|
||||
13
domokits/local/modules/TheliaLibrary/composer.json
Executable file
13
domokits/local/modules/TheliaLibrary/composer.json
Executable file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "thelia/thelia-library-module",
|
||||
"description": "Add a media library to Thelia",
|
||||
"license": "LGPL-3.0-or-later",
|
||||
"type": "thelia-module",
|
||||
"require": {
|
||||
"thelia/installer": "~1.3",
|
||||
"thelia/open-api-module": "^2.1.1"
|
||||
},
|
||||
"extra": {
|
||||
"installer-name": "TheliaLibrary"
|
||||
}
|
||||
}
|
||||
17
domokits/local/modules/TheliaLibrary/gulpfile.js
Normal file
17
domokits/local/modules/TheliaLibrary/gulpfile.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const { src, dest, watch } = require("gulp");
|
||||
|
||||
function copy() {
|
||||
return src("node_modules/@thelia/media-library/dist/*").pipe(
|
||||
dest("templates/backOffice/default/tb-plugin/vendor/")
|
||||
);
|
||||
}
|
||||
|
||||
function defaultTask() {
|
||||
if (process.env.NODE_ENV === "production") {
|
||||
return copy();
|
||||
} else {
|
||||
watch(["node_modules/@thelia/media-library/dist/*"], copy);
|
||||
}
|
||||
}
|
||||
|
||||
exports.default = defaultTask;
|
||||
8067
domokits/local/modules/TheliaLibrary/package-lock.json
generated
Normal file
8067
domokits/local/modules/TheliaLibrary/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
23
domokits/local/modules/TheliaLibrary/package.json
Normal file
23
domokits/local/modules/TheliaLibrary/package.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "tb-plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"prepare": "husky install",
|
||||
"build": "NODE_ENV=production node_modules/.bin/gulp",
|
||||
"dev": "node_modules/.bin/gulp"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"gulp": "^4.0.2",
|
||||
"husky": "^8.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"@thelia/blocks-editor": "^1.3.9",
|
||||
"@thelia/media-library": "^1.1.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
itemType: {$itemType} <br>
|
||||
itemId: {$itemId}
|
||||
<a href="{navigate to="current" force_legacy_imagemanager=true}">
|
||||
use old image manager
|
||||
</a>
|
||||
|
||||
<div id="imageManager"></div>
|
||||
|
||||
<script type="text/javascript" crossorigin src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script>
|
||||
<script type="text/javascript" crossorigin src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script>
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
<script src="{encore_module_asset file="tb-plugin/vendor/index.global.js" module="TheliaLibrary"}"></script>
|
||||
@@ -0,0 +1 @@
|
||||
<link rel="stylesheet" href="{encore_module_asset file='tb-plugin/vendor/index.css' module="TheliaLibrary"}" />
|
||||
488
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.css
vendored
Normal file
488
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.css
vendored
Normal file
@@ -0,0 +1,488 @@
|
||||
/* src/Input/Inputs.css */
|
||||
.Input {
|
||||
&__Wrapper {
|
||||
@apply relative;
|
||||
&__Header {
|
||||
@apply flex justify-between;
|
||||
}
|
||||
&__Error {
|
||||
@apply text-error mt-1 text-sm;
|
||||
}
|
||||
}
|
||||
&__Text {
|
||||
@apply relative w-full rounded-md border border-mediumGrey outline-none py-2 px-4;
|
||||
height: 40px;
|
||||
&__Wrapper {
|
||||
@apply relative w-full flex flex-wrap items-stretch;
|
||||
}
|
||||
&:hover,
|
||||
&:focus {
|
||||
@apply border-darkCharbon;
|
||||
}
|
||||
&--withIcon {
|
||||
@apply pl-10;
|
||||
}
|
||||
&--withIcons {
|
||||
@apply px-10;
|
||||
}
|
||||
&--emphasize {
|
||||
@apply text-vermillon;
|
||||
}
|
||||
}
|
||||
&__Select {
|
||||
background: url("data:image/svg+xml,<svg height='10px' width='10px' viewBox='0 0 16 16' fill='currentcolor' xmlns='http://www.w3.org/2000/svg'><path d='M7.247 11.14 2.451 5.658C1.885 5.013 2.345 4 3.204 4h9.592a1 1 0 0 1 .753 1.659l-4.796 5.48a1 1 0 0 1-1.506 0z'/></svg>") no-repeat;
|
||||
background-color: white;
|
||||
background-position: calc(100% - 12px) center;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
&__Separator {
|
||||
@apply absolute h-6 bg-darkCharbon bottom-2 right-8 z-10;
|
||||
width: 1px;
|
||||
}
|
||||
}
|
||||
&__Icon {
|
||||
@apply absolute py-1 h-full leading-snug rounded text-base font-normal text-center flex items-center justify-center;
|
||||
&--left {
|
||||
@apply left-0 pr-5 pl-4;
|
||||
}
|
||||
&--right {
|
||||
@apply right-0 pr-4 pl-5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* src/Library/Library.css */
|
||||
.Modal-Library {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
height: max-content;
|
||||
width: 90%;
|
||||
max-height: 90%;
|
||||
overflow: auto;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 350ms;
|
||||
}
|
||||
.Modal-Upload {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
height: max-content;
|
||||
width: 50%;
|
||||
max-height: 90%;
|
||||
overflow: auto;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
transition-property: all;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transition-duration: 350ms;
|
||||
}
|
||||
.Modal-Tags {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
margin: auto;
|
||||
width: max-content;
|
||||
max-width: 700px;
|
||||
height: max-content;
|
||||
max-height: 80%;
|
||||
border-radius: 8px;
|
||||
background-color: white;
|
||||
}
|
||||
.Modal__Content__Loader {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.Modal__Content__Loader span {
|
||||
display: block;
|
||||
}
|
||||
.Library__NoContent {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
.Library {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 30px;
|
||||
}
|
||||
.Library__Filters {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
}
|
||||
.Library__Filters .Input__Wrapper {
|
||||
width: 400px;
|
||||
}
|
||||
.Library__Content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 16px;
|
||||
}
|
||||
.Library__Image {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
max-width: 160px;
|
||||
height: max-content;
|
||||
border: 1px solid #EBEBEB;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
.Library__Image img {
|
||||
border-radius: 4px;
|
||||
object-fit: contain;
|
||||
}
|
||||
.Library__Image__Title {
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 130px;
|
||||
}
|
||||
.Library__Image__Action__Title {
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-weight: 600;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 120px;
|
||||
color: white;
|
||||
}
|
||||
.Library__Image__Tags {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 4px;
|
||||
flex-wrap: wrap;
|
||||
top: 7px;
|
||||
right: 7px;
|
||||
}
|
||||
.Library__Image__Tag {
|
||||
width: 50px;
|
||||
height: 20px;
|
||||
border-radius: 20px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
background-color: white;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
.Library__Image__Actions {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: rgba(0, 0, 0, 0.9);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.Library__Image__Actions__Wrapper {
|
||||
display: flex;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
.Library__Add__Button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
border-radius: 100%;
|
||||
background-color: #D21919;
|
||||
cursor: pointer;
|
||||
}
|
||||
.Library__Add__Button:disabled {
|
||||
background-color: #EBEBEB;
|
||||
color: #fff;
|
||||
}
|
||||
.Library__Add__Button:enabled:hover {
|
||||
background-color: #FA533C;
|
||||
color: #fff;
|
||||
}
|
||||
.Library__Add__Button:hover {
|
||||
background-color: transparent;
|
||||
color: #222222;
|
||||
}
|
||||
.Library__Image:hover .Library__Image__Actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.Library__Image__Select__Action {
|
||||
background: transparent;
|
||||
border: 1px solid #fff;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
padding: 6px 15px;
|
||||
letter-spacing: 0.05em;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.Library__Image__Select__Action:hover {
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
.Library__Image__Delete__Action {
|
||||
background-color: #D21919;
|
||||
border-radius: 100%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
.Library__Image__Tag__Action {
|
||||
background-color: #008958;
|
||||
border-radius: 100%;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
color: #fff;
|
||||
}
|
||||
.BlockImage__TagSelector {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
border-radius: 6px;
|
||||
outline: none;
|
||||
border: 1px solid #9B9B9B;
|
||||
height: max-content;
|
||||
min-height: 40px;
|
||||
padding: 5px;
|
||||
}
|
||||
.BlockImage__TagSelector__Add {
|
||||
position: absolute;
|
||||
bottom: 3px;
|
||||
right: 3px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
background-color: #444444;
|
||||
}
|
||||
.BlockImage__TagSelector__Add:hover {
|
||||
background-color: #333333;
|
||||
}
|
||||
.BlockImage__TagSelector__Tags {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
.BlockImage__TagSelector__Tag {
|
||||
max-width: 100px;
|
||||
width: max-content;
|
||||
max-height: 30px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
border-radius: 90px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background-color: #333333;
|
||||
color: white;
|
||||
align-items: center;
|
||||
padding: 4px;
|
||||
padding-left: 14px;
|
||||
}
|
||||
.BlockImage__TagSelector__Tag > span {
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
margin-right: 7px;
|
||||
}
|
||||
.BlockImage__TagSelector__Tag__Remove {
|
||||
background-color: white;
|
||||
color: #111;
|
||||
border-radius: 90px;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.TagList {
|
||||
top: 100%;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
border-radius: 6px;
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
z-index: 30;
|
||||
max-height: 200px;
|
||||
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.TagList__Item {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px 15px;
|
||||
}
|
||||
.Select__Wrapper {
|
||||
position: relative;
|
||||
width: 250px;
|
||||
}
|
||||
@media screen and (max-width: 768px) {
|
||||
.Library__Image__Title {
|
||||
max-width: 100px;
|
||||
}
|
||||
.Library__Filters {
|
||||
flex-direction: column;
|
||||
}
|
||||
.Library__Filters .Input__Wrapper,
|
||||
.Library__Filters .Select__Wrapper {
|
||||
width: auto;
|
||||
}
|
||||
.Library__Item {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
/* src/Image/Image.css */
|
||||
.BlockImage__Upload__Wrapper {
|
||||
display: flex;
|
||||
gap: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
.BlockImage__FromLibrary {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
padding: 50px 20px;
|
||||
height: 200px;
|
||||
}
|
||||
.BlockImage__FromLibrary__Icon {
|
||||
background-color: #f5f5f5;
|
||||
padding: 10px;
|
||||
border-radius: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.BlockImage__FromLocal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
padding: 50px 20px;
|
||||
height: 200px;
|
||||
border: 1px dashed #787878;
|
||||
}
|
||||
.BlockImage__FromLocal.BlockImage__FromLocal--active {
|
||||
border: 2px dashed #dc3018;
|
||||
}
|
||||
input.BlockImage__FromLocal__FileInput {
|
||||
display: none;
|
||||
}
|
||||
.BlockImage__Button {
|
||||
display: block;
|
||||
cursor: pointer;
|
||||
color: #dc3018;
|
||||
font-weight: 600;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
text-align: center;
|
||||
letter-spacing: 0.05em;
|
||||
text-transform: uppercase;
|
||||
border: 1px solid #dc3018;
|
||||
border-radius: 4px;
|
||||
padding: 6px 15px;
|
||||
}
|
||||
.BlockImage__Button:hover {
|
||||
background-color: #dc3018;
|
||||
color: #fff;
|
||||
}
|
||||
.BlockImage__FromLocal__Icon {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.BlockImage__Infos__Form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
}
|
||||
.BlockImage__Preview {
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
gap: 18px;
|
||||
max-width: 290px;
|
||||
}
|
||||
.BlockImage__Preview__Infos {
|
||||
width: 100%;
|
||||
}
|
||||
.BlockImage__Preview img {
|
||||
border: 1px solid #EBEBEB;
|
||||
padding: 5px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.BlockImage__Preview__FileName {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #333333;
|
||||
margin-bottom: 10px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.BlockImage__Infos {
|
||||
display: flex;
|
||||
gap: 40px;
|
||||
}
|
||||
.BlockImage__Upload--light .BlockImage__FromLocal,
|
||||
.BlockImage__Upload--light .BlockImage__FromLibrary {
|
||||
border: none;
|
||||
background-color: inherit;
|
||||
padding: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
.BlockImage__Upload--light .BlockImage__FromLocal .BlockImage__FromLocal__Icon,
|
||||
.BlockImage__Upload--light .BlockImage__FromLibrary .BlockImage__FromLibrary__Icon {
|
||||
display: none;
|
||||
}
|
||||
@media screen and (max-width: 1366px) {
|
||||
.BlockImage__Upload__Wrapper {
|
||||
flex-direction: column;
|
||||
}
|
||||
.BlockImage__FromLibrary {
|
||||
width: 100%;
|
||||
}
|
||||
.BlockImage__FromLocal {
|
||||
width: 100%;
|
||||
}
|
||||
.BlockImage__Infos {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
/*# sourceMappingURL=index.css.map */
|
||||
File diff suppressed because one or more lines are too long
44
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.d.ts
vendored
Normal file
44
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.d.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import { BlockPluginDefinition } from '@thelia/blocks-editor';
|
||||
|
||||
declare type ImageTag = {
|
||||
imageTag: {
|
||||
id: number;
|
||||
imageId: number;
|
||||
tagId: number;
|
||||
};
|
||||
tag: {
|
||||
id: number;
|
||||
title: string;
|
||||
colorCode: string;
|
||||
};
|
||||
};
|
||||
declare type LibraryImage = {
|
||||
id: number | null;
|
||||
fileName: string;
|
||||
title: string;
|
||||
tags: ImageTag[];
|
||||
width: string;
|
||||
height: string;
|
||||
link?: {
|
||||
url: string;
|
||||
target?: string;
|
||||
};
|
||||
target: HTMLAnchorElement["target"];
|
||||
};
|
||||
|
||||
declare const UploadImage: ({ onSelect, compact, uploadModes, }: {
|
||||
onSelect: (image: LibraryImage) => void;
|
||||
compact?: boolean | undefined;
|
||||
uploadModes?: ("local" | "library")[] | undefined;
|
||||
}) => JSX.Element;
|
||||
declare const initialData: LibraryImage;
|
||||
declare const blockImage: BlockPluginDefinition<LibraryImage>;
|
||||
|
||||
declare function WrappedComponent(props: {
|
||||
isOpen: boolean;
|
||||
setIsOpen: Function;
|
||||
limit?: number;
|
||||
onSelect: (image: LibraryImage) => void;
|
||||
}): JSX.Element;
|
||||
|
||||
export { blockImage as BlockImage, initialData as BlockImageInitialData, LibraryImage, UploadImage, WrappedComponent as default };
|
||||
16566
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.global.js
vendored
Normal file
16566
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.global.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
13822
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.mjs
vendored
Normal file
13822
domokits/local/modules/TheliaLibrary/templates/backOffice/default/tb-plugin/vendor/index.mjs
vendored
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,14 @@
|
||||
{$hasLink = isset($data['link']) && isset($data['link']['url']) && $data['link']['url']}
|
||||
{if $hasLink}
|
||||
<a href="{$data['link']['url']}" {if isset($data['link']['target']) && $data['link']['target']}target="{$data['link']['target']}"{/if}>
|
||||
{/if}
|
||||
{if isset($data['id']|default:null)}
|
||||
{loop type="library_image" name="library_image" id=$data['id']|default:null}
|
||||
<img class="tb-{$type['id']|default:null}" src="{$URL}" alt="{$TITLE}" loading="lazy" style="{if $data['width'] != ""}width: {$data['width']};{/if} {if $data['height'] != ""}height: {$data['height']};{/if}" />
|
||||
{/loop}
|
||||
{else}
|
||||
<img class="tb-{$type['id']|default:null}" src="{$data['url']|default:null}" alt="{$data['alt']|default:null}" loading="lazy" style="{if $data['width'] != ""}width: {$data['width']};{/if} {if $data['height'] != ""}height: {$data['height']};{/if}" />
|
||||
{/if}
|
||||
{if $hasLink}
|
||||
</a>
|
||||
{/if}
|
||||
Reference in New Issue
Block a user