[11/06/2024] Les premières modifs + installation de quelques modules indispensables

This commit is contained in:
2024-06-11 14:57:59 +02:00
parent 5ac5653ae5
commit 77cf2c7cc6
1626 changed files with 171457 additions and 131 deletions

View File

@@ -0,0 +1,6 @@
# 2.3.0-alpha1
- Moved the images from the directory 'media' in the module to thelia/local/media/images/carousel.
- The current images will be automatically copied in the new directory during the update of the module
- Removed AdminIncludes directory
- All html,js and css files are now in 'templates'

View File

@@ -0,0 +1,124 @@
<?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 Carousel;
use Propel\Runtime\Connection\ConnectionInterface;
use Symfony\Component\DependencyInjection\Loader\Configurator\ServicesConfigurator;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Thelia\Install\Database;
use Thelia\Model\ConfigQuery;
use Thelia\Module\BaseModule;
/**
* Class Carousel.
*
* @author Franck Allimant <franck@cqfdev.fr>
*/
class Carousel extends BaseModule
{
public const DOMAIN_NAME = 'carousel';
/**
* @return bool true to continue module activation, false to prevent it
*/
public function preActivation(ConnectionInterface $con = null)
{
if (!self::getConfigValue('is_initialized', false)) {
$database = new Database($con);
$database->insertSql(null, [__DIR__.'/Config/TheliaMain.sql']);
self::setConfigValue('is_initialized', true);
}
return true;
}
public function destroy(ConnectionInterface $con = null, $deleteModuleData = false): void
{
$database = new Database($con);
$database->insertSql(null, [__DIR__.'/Config/sql/destroy.sql']);
}
public function getUploadDir()
{
$uploadDir = ConfigQuery::read('images_library_path');
if ($uploadDir === null) {
$uploadDir = THELIA_LOCAL_DIR.'media'.DS.'images';
} else {
$uploadDir = THELIA_ROOT.$uploadDir;
}
return $uploadDir.DS.self::DOMAIN_NAME;
}
/**
* @param string $currentVersion
* @param string $newVersion
*
* @author Thomas Arnaud <tarnaud@openstudio.fr>
*/
public function update($currentVersion, $newVersion, ConnectionInterface $con = null): void
{
$uploadDir = $this->getUploadDir();
$fileSystem = new Filesystem();
if (!$fileSystem->exists($uploadDir) && $fileSystem->exists(__DIR__.DS.'media'.DS.'carousel')) {
$finder = new Finder();
$finder->files()->in(__DIR__.DS.'media'.DS.'carousel');
$fileSystem->mkdir($uploadDir);
/** @var SplFileInfo $file */
foreach ($finder as $file) {
copy($file, $uploadDir.DS.$file->getRelativePathname());
}
$fileSystem->remove(__DIR__.DS.'media');
}
$finder = (new Finder())->files()->name('#.*?\.sql#')->sortByName()->in(__DIR__.DS.'Config'.DS.'update');
if (0 === $finder->count()) {
return;
}
$database = new Database($con);
// apply update only if table exists
if ($database->execute("SHOW TABLES LIKE 'carousel'")->rowCount() === 0) {
return;
}
/** @var SplFileInfo $updateSQLFile */
foreach ($finder as $updateSQLFile) {
if (version_compare($currentVersion, str_replace('.sql', '', $updateSQLFile->getFilename()), '<')) {
$database->insertSql(null, [$updateSQLFile->getPathname()]);
}
}
}
/**
* 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);
}
}

View File

@@ -0,0 +1,51 @@
# 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;
-- ---------------------------------------------------------------------
-- carousel
-- ---------------------------------------------------------------------
DROP TABLE IF EXISTS `carousel`;
CREATE TABLE `carousel`
(
`id` INTEGER NOT NULL AUTO_INCREMENT,
`file` VARCHAR(255),
`position` INTEGER,
`disable` INTEGER,
`group` VARCHAR(255),
`url` VARCHAR(255),
`limited` INTEGER,
`start_date` DATETIME,
`end_date` DATETIME,
`created_at` DATETIME,
`updated_at` DATETIME,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
-- ---------------------------------------------------------------------
-- carousel_i18n
-- ---------------------------------------------------------------------
DROP TABLE IF EXISTS `carousel_i18n`;
CREATE TABLE `carousel_i18n`
(
`id` INTEGER NOT NULL,
`locale` VARCHAR(5) DEFAULT 'en_US' NOT NULL,
`alt` VARCHAR(255),
`title` VARCHAR(255),
`description` LONGTEXT,
`chapo` TEXT,
`postscriptum` TEXT,
PRIMARY KEY (`id`,`locale`),
CONSTRAINT `carousel_i18n_fk_2ec1b2`
FOREIGN KEY (`id`)
REFERENCES `carousel` (`id`)
ON DELETE CASCADE
) ENGINE=InnoDB;
# This restores the fkey checks, after having unset them earlier
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -0,0 +1,15 @@
<?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">
<hooks>
<hook id="carousel.hook">
<tag name="hook.event_listener" event="home.body" type="front" templates="render:carousel.html" />
<tag name="hook.event_listener" event="module.configuration" type="back" templates="render:module_configuration.html" />
<tag name="hook.event_listener" event="module.config-js" type="back" templates="js:assets/js/module-configuration.js" />
</hook>
<hook id="carousel.hook.back" class="Carousel\Hook\BackHook">
<tag name="hook.event_listener" event="main.top-menu-tools" type="back" />
</hook>
</hooks>
</config>

View File

@@ -0,0 +1,24 @@
<?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_1.xsd">
<fullnamespace>Carousel\Carousel</fullnamespace>
<descriptive locale="en_US">
<title>An image carousel</title>
</descriptive>
<descriptive locale="fr_FR">
<title>Un carrousel d'images</title>
</descriptive>
<languages>
<language>en_US</language>
<language>fr_FR</language>
</languages>
<version>2.5.4</version>
<author>
<name>Manuel Raynaud, Franck Allimant</name>
<email>manu@raynaud.io, franck@cqfdev.fr</email>
</author>
<type>classic</type>
<thelia>2.5.4</thelia>
<stability>alpha</stability>
</module>

View File

@@ -0,0 +1,42 @@
<?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/carousel/ 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/carousel">
<default key="_controller">Carousel\Full\Class\Name\Of\YourConfigurationController::methodName</default>
</route>
<route id="my_route_id" path="/admin/module/carousel/route-name">
<default key="_controller">Carousel\Full\Class\Name\Of\YourAdminController::methodName</default>
</route>
<route id="my_route_id" path="/my/route/name">
<default key="_controller">Carousel\Full\Class\Name\Of\YourOtherController::methodName</default>
</route>
...add as many routes as required.
<route>
...
</route>
-->
<route id="carousel.upload.image" path="/admin/module/carousel/upload" methods="post">
<default key="_controller">Carousel\Controller\ConfigurationController::uploadImage</default>
</route>
<route id="carousel.update" path="/admin/module/carousel/update" methods="post">
<default key="_controller">Carousel\Controller\ConfigurationController::updateAction</default>
</route>
<route id="carousel.delete" path="/admin/module/carousel/delete" methods="post">
<default key="_controller">Carousel\Controller\ConfigurationController::deleteAction</default>
</route>
</routes>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<database defaultIdMethod="native" name="TheliaMain" namespace="Carousel\Model">
<!--
See propel documentation on http://propelorm.org for all information about schema file
-->
<table name="carousel">
<column autoIncrement="true" name="id" primaryKey="true" required="true" type="INTEGER" />
<column name="file" type="VARCHAR" size="255" />
<column name="position" type="INTEGER" />
<column name="disable" type="INTEGER" />
<column name="group" size="255" type="VARCHAR" />
<column name="alt" size="255" type="VARCHAR" />
<column name="url" size="255" type="VARCHAR" />
<column name="title" size="255" type="VARCHAR" />
<column name="description" type="CLOB" />
<column name="chapo" type="LONGVARCHAR" />
<column name="postscriptum" type="LONGVARCHAR" />
<column name="limited" type="INTEGER" />
<column name="start_date" type="TIMESTAMP" />
<column name="end_date" type="TIMESTAMP" />
<behavior name="timestampable" />
<behavior name="i18n">
<parameter name="i18n_columns" value="alt, title, description, chapo, postscriptum" />
</behavior>
</table>
<external-schema filename="local/config/schema.xml" referenceOnly="true" />
</database>

View File

@@ -0,0 +1,6 @@
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `carousel`;
DROP TABLE IF EXISTS `carousel_i18n`;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -0,0 +1,2 @@
# Sqlfile -> Database map
TheliaMain.sql=TheliaMain

View File

@@ -0,0 +1 @@
ALTER TABLE `carousel` ADD (`disable` INTEGER, `group` VARCHAR(255),`limited` INTEGER, `start_date` DATETIME, `end_date` DATETIME);

View File

@@ -0,0 +1,196 @@
<?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 Carousel\Controller;
use Carousel\Form\CarouselImageForm;
use Carousel\Form\CarouselUpdateForm;
use Carousel\Model\Carousel;
use Carousel\Model\CarouselQuery;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use Thelia\Controller\Admin\BaseAdminController;
use Thelia\Core\Event\File\FileCreateOrUpdateEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Form\TheliaFormFactory;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\Security\AccessManager;
use Thelia\Core\Security\Resource\AdminResources;
use Thelia\Form\Exception\FormValidationException;
use Thelia\Model\Lang;
use Thelia\Model\LangQuery;
use Thelia\Tools\URL;
/**
* Class ConfigurationController.
*
* @author manuel raynaud <mraynaud@openstudio.fr>
*/
class ConfigurationController extends BaseAdminController
{
public function uploadImage(
Request $request,
TheliaFormFactory $formFactory,
EventDispatcherInterface $eventDispatcher
) {
if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::CREATE)) {
return $response;
}
$form = $formFactory->createForm(CarouselImageForm::class);
$error_message = null;
try {
$formData = $this->validateForm($form)->getData();
/** @var UploadedFile $fileBeingUploaded */
$fileBeingUploaded = $formData['file'];
$fileModel = new Carousel();
$fileCreateOrUpdateEvent = new FileCreateOrUpdateEvent(1);
$fileCreateOrUpdateEvent->setModel($fileModel);
$fileCreateOrUpdateEvent->setUploadedFile($fileBeingUploaded);
$eventDispatcher->dispatch(
$fileCreateOrUpdateEvent,
TheliaEvents::IMAGE_SAVE
);
// Compensate issue #1005
$langs = LangQuery::create()->find();
/** @var Lang $lang */
foreach ($langs as $lang) {
$fileCreateOrUpdateEvent->getModel()->setLocale($lang->getLocale())->setTitle('')->save();
}
$response = $this->redirectToConfigurationPage();
} catch (FormValidationException $e) {
$error_message = $this->createStandardFormValidationErrorMessage($e);
}
if (null !== $error_message) {
$this->setupFormErrorContext(
'carousel upload',
$error_message,
$form
);
$response = $this->render(
'module-configure',
[
'module_code' => 'Carousel',
]
);
}
return $response;
}
/**
* @param Form $form
* @param string $fieldName
* @param int $id
*
* @return string
*/
protected function getFormFieldValue($form, $fieldName, $id)
{
$value = $form->get(sprintf('%s%d', $fieldName, $id))->getData();
return $value;
}
public function updateAction(
TheliaFormFactory $formFactory
) {
if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::UPDATE)) {
return $response;
}
$form = $formFactory->createForm(CarouselUpdateForm::class);
$error_message = null;
try {
$updateForm = $this->validateForm($form);
$carousels = CarouselQuery::create()->findAllByPosition();
$locale = $this->getCurrentEditionLocale();
/** @var Carousel $carousel */
foreach ($carousels as $carousel) {
$id = $carousel->getId();
$carousel
->setPosition($this->getFormFieldValue($updateForm, 'position', $id))
->setDisable($this->getFormFieldValue($updateForm, 'disable', $id))
->setUrl($this->getFormFieldValue($updateForm, 'url', $id))
->setLocale($locale)
->setTitle($this->getFormFieldValue($updateForm, 'title', $id))
->setAlt($this->getFormFieldValue($updateForm, 'alt', $id))
->setChapo($this->getFormFieldValue($updateForm, 'chapo', $id))
->setDescription($this->getFormFieldValue($updateForm, 'description', $id))
->setPostscriptum($this->getFormFieldValue($updateForm, 'postscriptum', $id))
->setGroup($this->getFormFieldValue($updateForm, 'group', $id))
->setLimited($this->getFormFieldValue($updateForm, 'limited', $id))
->setStartDate($this->getFormFieldValue($updateForm, 'start_date', $id))
->setEndDate($this->getFormFieldValue($updateForm, 'end_date', $id))
->save();
}
$response = $this->redirectToConfigurationPage();
} catch (FormValidationException $e) {
$error_message = $this->createStandardFormValidationErrorMessage($e);
}
if (null !== $error_message) {
$this->setupFormErrorContext(
'carousel upload',
$error_message,
$form
);
$response = $this->render('module-configure', ['module_code' => 'Carousel']);
}
return $response;
}
public function deleteAction(
Request $request
) {
if (null !== $response = $this->checkAuth(AdminResources::MODULE, ['carousel'], AccessManager::DELETE)) {
return $response;
}
$imageId = $request->get('image_id');
if ($imageId != '') {
$carousel = CarouselQuery::create()->findPk($imageId);
if (null !== $carousel) {
$carousel->delete();
}
}
return $this->redirectToConfigurationPage();
}
protected function redirectToConfigurationPage()
{
return new RedirectResponse(URL::getInstance()->absoluteUrl('/admin/module/Carousel'));
}
}

View File

@@ -0,0 +1,46 @@
<?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 Carousel\Form;
use Carousel\Carousel;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\Image;
use Thelia\Core\Translation\Translator;
use Thelia\Form\BaseForm;
/**
* Class CarouselImageForm.
*
* @author manuel raynaud <mraynaud@openstudio.fr>
*/
class CarouselImageForm extends BaseForm
{
protected function buildForm(): void
{
$translator = Translator::getInstance();
$this->formBuilder
->add(
'file',
FileType::class,
[
'constraints' => [
new Image(),
],
'label' => $translator->trans('Carousel image', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'file',
],
]
);
}
}

View File

@@ -0,0 +1,222 @@
<?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 Carousel\Form;
use Carousel\Carousel;
use Carousel\Model\CarouselQuery;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\DateTimeType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\UrlType;
use Thelia\Form\BaseForm;
/**
* Class CarouselUpdateForm.
*
* @author manuel raynaud <mraynaud@openstudio.fr>
*/
class CarouselUpdateForm extends BaseForm
{
protected function buildForm(): void
{
$formBuilder = $this->formBuilder;
$carousels = CarouselQuery::create()->orderByPosition()->find();
/** @var \Carousel\Model\Carousel $carousel */
foreach ($carousels as $carousel) {
$id = $carousel->getId();
$formBuilder->add(
'position'.$id,
TextType::class,
[
'label' => $this->translator->trans('Image position in carousel', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'position'.$id,
],
'required' => false,
'attr' => [
'placeholder' => $this->translator->trans(
'Image position in carousel',
[],
Carousel::DOMAIN_NAME
),
],
]
)->add(
'alt'.$id,
TextType::class,
[
'label' => $this->translator->trans('Alternative image text', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'alt'.$id,
],
'required' => false,
'attr' => [
'placeholder' => $this->translator->trans(
'Displayed when image is not visible',
[],
Carousel::DOMAIN_NAME
),
],
]
)->add(
'group'.$id,
TextType::class,
[
'label' => $this->translator->trans('Group image', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'group'.$id,
],
'required' => false,
'attr' => [
'placeholder' => $this->translator->trans(
'Group of images',
[],
Carousel::DOMAIN_NAME
),
],
]
)->add(
'url'.$id,
UrlType::class,
[
'label' => $this->translator->trans('Image URL', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'url'.$id,
],
'required' => false,
'attr' => [
'placeholder' => $this->translator->trans(
'Please enter a valid URL',
[],
Carousel::DOMAIN_NAME
),
],
]
)->add(
'title'.$id,
TextType::class,
[
'constraints' => [],
'required' => false,
'label' => $this->translator->trans('Title', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'title_field'.$id,
],
'attr' => [
'placeholder' => $this->translator->trans('A descriptive title', [], Carousel::DOMAIN_NAME),
],
]
)->add(
'chapo'.$id,
TextareaType::class,
[
'constraints' => [],
'required' => false,
'label' => $this->translator->trans('Summary', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'summary_field'.$id,
'help' => $this->translator->trans(
'A short description, used when a summary or an introduction is required',
[],
Carousel::DOMAIN_NAME
),
],
'attr' => [
'rows' => 3,
'placeholder' => $this->translator->trans('Short description text', [], Carousel::DOMAIN_NAME),
],
]
)->add(
'description'.$id,
TextareaType::class,
[
'constraints' => [],
'required' => false,
'label' => $this->translator->trans('Detailed description', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'detailed_description_field'.$id,
'help' => $this->translator->trans('The detailed description.', [], Carousel::DOMAIN_NAME),
],
'attr' => [
'rows' => 5,
],
]
)->add(
'disable'.$id,
CheckboxType::class,
[
'required' => false,
'label' => $this->translator->trans('Disable image', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'enable'.$id,
],
]
)->add(
'limited'.$id,
CheckboxType::class,
[
'required' => false,
'label' => $this->translator->trans('Limited', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'limited'.$id,
],
]
)->add(
'start_date'.$id,
DateTimeType::class,
[
'label' => $this->translator->trans('Start date', [], Carousel::DOMAIN_NAME),
'widget' => 'single_text',
'required' => false,
]
)->add(
'end_date'.$id,
DateTimeType::class,
[
'label' => $this->translator->trans('End date', [], Carousel::DOMAIN_NAME),
'widget' => 'single_text',
'required' => false,
]
)->add(
'postscriptum'.$id,
TextareaType::class,
[
'constraints' => [],
'required' => false,
'label' => $this->translator->trans('Conclusion', [], Carousel::DOMAIN_NAME),
'label_attr' => [
'for' => 'conclusion_field'.$id,
'help' => $this->translator->trans(
'A short text, used when an additional or supplemental information is required.',
[],
Carousel::DOMAIN_NAME
),
],
'attr' => [
'placeholder' => $this->translator->trans('Short additional text', [], Carousel::DOMAIN_NAME),
'rows' => 3,
],
]
);
}
}
public static function getName()
{
return 'carousel_update';
}
}

View File

@@ -0,0 +1,43 @@
<?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 Carousel\Hook;
use Carousel\Carousel;
use Thelia\Core\Event\Hook\HookRenderBlockEvent;
use Thelia\Core\Hook\BaseHook;
use Thelia\Tools\URL;
/**
* Class BackHook.
*
* @author Emmanuel Nurit <enurit@openstudio.fr>
*/
class BackHook extends BaseHook
{
/**
* Add a new entry in the admin tools menu.
*
* should add to event a fragment with fields : id,class,url,title
*/
public function onMainTopMenuTools(HookRenderBlockEvent $event): void
{
$event->add(
[
'id' => 'tools_menu_carousel',
'class' => '',
'url' => URL::getInstance()->absoluteUrl('/admin/module/Carousel'),
'title' => $this->trans('Edit your carousel', [], Carousel::DOMAIN_NAME),
]
);
}
}

View File

@@ -0,0 +1,24 @@
<?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 [
'Add an image to the carousel' => 'Ein Bild zu Karussell hinzufügen',
'Add this image to the carousel' => 'Dieses Bild zu Karussell hinzufügen',
'Carousel image' => 'Karussell-Bild',
'Carousel images' => 'Karussell-Bilder',
'Delete a carousel image' => 'Ein Karussell-Bild löschen',
'Do you really want to remove this image from the carousel ?' => 'Wollen Sie dieses Bild wirklich aus dem Karussell entfernen?',
'Edit your carousel.' => 'Karussell bearbeiten.',
'Remove this image' => 'Dieses Bild entfernen',
'Your carousel contains no image. Please add one using the form above.' => 'Das Karussell enthält kein Bild. Bitte fügen Sie mit dem Formular oben eines hinzu.',
'Position' => 'Position',
];

View File

@@ -0,0 +1,25 @@
<?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 [
'Add an image to the carousel' => 'Add an image to the carousel',
'Add this image to the carousel' => 'Add this image to the carousel',
'Carousel image' => 'Carousel image',
'Carousel images' => 'Carousel images',
'Delete a carousel image' => 'Delete a carousel image',
'Do you really want to remove this image from the carousel ?' => 'Do you really want to remove this image from the carousel ?',
'Edit your carousel.' => 'Edit your carousel.',
'Remove this image' => 'Remove this image',
'Your carousel contains no image. Please add one using the form above.' => 'Your carousel contains no image. Please add one using the form above.',
'Position' => 'Position',
'YYYY-MM-DD' => 'YYYY-MM-DD',
];

View File

@@ -0,0 +1,25 @@
<?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 [
'Add an image to the carousel' => 'Ajouter une image au carrousel',
'Add this image to the carousel' => 'Ajouter l\'image au carrousel',
'Carousel image' => 'Image du carrousel',
'Carousel images' => 'Images du carrousel',
'Delete a carousel image' => 'Supprimer une image du carrousel',
'Do you really want to remove this image from the carousel ?' => 'Voulez-vous vraiment retirer cette image du carrousel ?',
'Edit your carousel.' => 'Modifier votre carrousel',
'Remove this image' => 'Supprimer cette image',
'Your carousel contains no image. Please add one using the form above.' => 'Votre carrousel ne contient aucune image. Ajoutez votre première image avec le formulaire ci-dessus',
'Position' => 'Position',
'YYYY-MM-DD' => 'AAAA-MM-JJ',
];

View File

@@ -0,0 +1,24 @@
<?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 [
'Add an image to the carousel' => 'Добавить изображение в карусель',
'Add this image to the carousel' => 'Добавить это изображение в карусель',
'Carousel image' => 'Изображение карусели',
'Carousel images' => 'Изображения карусели',
'Delete a carousel image' => 'Удалить изображение карусели',
'Do you really want to remove this image from the carousel ?' => 'Вы действительно хотите удалить это изображение из карусели ?',
'Edit your carousel.' => 'Редактировать вашу карусель.',
'Remove this image' => 'Удалить это изображение',
'Your carousel contains no image. Please add one using the form above.' => 'Ваша карусель не содержит изображений. Пожалуйста, добавьте одно используя форму ниже.',
'Position' => 'Позиция',
];

View File

@@ -0,0 +1,24 @@
<?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 [
'Add an image to the carousel' => 'Slayt için bir resim ekle',
'Add this image to the carousel' => 'slayt için bu resim ekleme',
'Carousel image' => 'slayt görüntü',
'Carousel images' => 'slayt görüntüleri',
'Delete a carousel image' => 'Bir slayt resmi silme',
'Do you really want to remove this image from the carousel ?' => 'Bu görüntüyü slayttan kaldırmak istiyor musunuz?',
'Edit your carousel.' => 'slayt düzenleyin.',
'Remove this image' => 'Bu resmi kaldırma',
'Your carousel contains no image. Please add one using the form above.' => 'Senin slayt hiçbir görüntü içermiyor . Lütfen yukarıdaki formu kullanarak ekleyin.',
'Position' => 'Pozisyon',
];

View File

@@ -0,0 +1,30 @@
<?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 [
'A descriptive title' => 'Beschreibungstitel',
'A short description, used when a summary or an introduction is required' => 'Eine kurze beschreibung, benutzt wenn eine Zusammenfassung order eine Einleitung ist nötig',
'A short text, used when an additional or supplemental information is required.' => 'Ein kurzer Text, der verwendet wird, wenn eine zusätzliche oder ergänzende Information erforderlich ist.',
'Alternative image text' => 'Alternativer Bildtext',
'Carousel image' => 'Karussell-Bild',
'Conclusion' => 'Abschluss',
'Detailed description' => 'Detaillierte Beschreibung',
'Displayed when image is not visible' => 'Angezeigt, wenn das Bild nicht sichtbar ist',
'Image URL' => 'Bild-URL',
'Image position in carousel' => 'Position des Bildes im Karussell',
'Please enter a valid URL' => 'Bitte geben Sie eine gültige URL ein',
'Short additional text' => 'Kurzer zusätzlicher Text',
'Short description text' => 'Kurzes Beschreibungstext',
'Summary' => 'Zusammenfassung',
'The detailed description.' => 'Die detaillierte Beschreibung.',
'Title' => 'Titel',
];

View File

@@ -0,0 +1,32 @@
<?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 [
'A descriptive title' => 'A descriptive title',
'A short description, used when a summary or an introduction is required' => 'A short description, used when a summary or an introduction is required',
'A short text, used when an additional or supplemental information is required.' => 'A short text, used when an additional or supplemental information is required.',
'Alternative image text' => 'Alternative image text',
'Carousel image' => 'Carousel image',
'Conclusion' => 'Conclusion',
'Detailed description' => 'Detailed description',
'Displayed when image is not visible' => 'Displayed when image is not visible',
'Edit your carousel' => 'Edit your carousel',
'Image URL' => 'Image URL',
'Image position in carousel' => 'Image position in carousel',
'Please enter a valid URL' => 'Please enter a valid URL',
'Short additional text' => 'Short additional text',
'Short description text' => 'Short description text',
'Summary' => 'Summary',
'The detailed description.' => 'The detailed description.',
'Title' => 'Title',
'YYYY-MM-DD' => 'AAAA-MM-JJ',
];

View File

@@ -0,0 +1,37 @@
<?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 [
'A descriptive title' => 'Un titre descriptif',
'A short description, used when a summary or an introduction is required' => 'Une courte description, utilisée lorsqu\'un résumé ou une introduction est requise',
'A short text, used when an additional or supplemental information is required.' => 'Un texte court, utilisé quand une conclusion ou une information complémentaire est nécessaire.',
'Alternative image text' => 'Texte alternatif de l\'image',
'Carousel image' => 'Image du carrousel',
'Conclusion' => 'Conclusion',
'Detailed description' => 'Description détaillée',
'Disable image' => 'Désactiver l\'image',
'Displayed when image is not visible' => 'Affiché lorsque l\'image n\'est pas visible',
'Edit your carousel' => 'Modifier votre carousel',
'End date' => 'Date de fin',
'Group image' => 'Groupe de l\'image',
'Group of images' => 'Nom du groupe auquel l\'image appartient',
'Image URL' => 'URL de l\'image',
'Image position in carousel' => 'Position de l\'image dans le carrousel',
'Limited' => 'Afficher l\'image entre les dates ci-dessous',
'Please enter a valid URL' => 'Merci d\'indiquer une URL valide',
'Short additional text' => 'Un court texte supplémentaire',
'Short description text' => 'Un court texte de description',
'Start date' => 'Date de début',
'Summary' => 'Résumé',
'The detailed description.' => 'La description détaillée.',
'Title' => 'Titre',
];

View File

@@ -0,0 +1,21 @@
<?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 [
'A descriptive title' => 'Un titolo descrittivo',
'A short description, used when a summary or an introduction is required' => 'Una breve descrizione, utilizzata quando è necessario un sommario o un\'introduzione',
'Conclusion' => 'Conclusione',
'Detailed description' => 'Descrizione dettagliata',
'Summary' => 'Riassunto',
'The detailed description.' => 'La descrizione dettagliata.',
'Title' => 'Titolo',
];

View 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.
*/
return [
'A descriptive title' => 'Описательный заголовок',
'A short description, used when a summary or an introduction is required' => 'Краткое описание, используется когда необходимо',
'A short text, used when an additional or supplemental information is required.' => 'Краткий текст используемый, когда необходима дополнительной информации.',
'Alternative image text' => 'Альтернативный текст изображения',
'Carousel image' => 'Изображение карусели',
'Conclusion' => 'Заключение',
'Detailed description' => 'Детальное описание',
'Displayed when image is not visible' => 'Отображается когда изображения не видно',
'Edit your carousel' => 'Редактировать вашу карусель',
'Image URL' => 'URL изображения',
'Image position in carousel' => 'Позиция изображения в карусели',
'Please enter a valid URL' => 'Пожалуйста введите корректный URL',
'Short additional text' => 'Краткий дополнительный текст',
'Short description text' => 'Текст краткого описания',
'Summary' => 'Краткое описание',
'The detailed description.' => 'Детальное описание',
'Title' => 'Заголовок',
];

View File

@@ -0,0 +1,30 @@
<?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 [
'A descriptive title' => 'Açıklayıcı bir başlık',
'A short description, used when a summary or an introduction is required' => 'Bir Özeti veya giriş gerekli olduğunda kullanılan kısa bir açıklama',
'A short text, used when an additional or supplemental information is required.' => 'Bir ek ya da tamamlayıcı bilgi gerekli olduğunda kullanılan kısa bir metin.',
'Alternative image text' => 'Alternatif resim metini',
'Carousel image' => 'slayt görüntü',
'Conclusion' => 'Sonuç',
'Detailed description' => 'Detaylııklama',
'Displayed when image is not visible' => 'resim görünür olmadığında görüntülenen',
'Image URL' => 'Resim Bağlantı [Link]',
'Image position in carousel' => 'slayt bulunduğu resim',
'Please enter a valid URL' => 'Lütfen geçerli bir URL girin',
'Short additional text' => 'Kısa ek metin',
'Short description text' => 'Kısa açıklama metni',
'Summary' => 'Özet',
'The detailed description.' => 'Ayrıntılııklama.',
'Title' => 'Başlık',
];

View File

@@ -0,0 +1,237 @@
<?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 Carousel\Loop;
use Carousel\Model\CarouselQuery;
use Propel\Runtime\ActiveQuery\Criteria;
use Thelia\Core\Event\Image\ImageEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Core\Template\Element\LoopResult;
use Thelia\Core\Template\Element\LoopResultRow;
use Thelia\Core\Template\Loop\Argument\Argument;
use Thelia\Core\Template\Loop\Argument\ArgumentCollection;
use Thelia\Core\Template\Loop\Image;
use Thelia\Log\Tlog;
use Thelia\Type\EnumListType;
use Thelia\Type\EnumType;
use Thelia\Type\TypeCollection;
/**
* Class CarouselLoop.
*
* @author manuel raynaud <mraynaud@openstudio.fr>
*/
class Carousel extends Image
{
protected function getArgDefinitions()
{
return new ArgumentCollection(
Argument::createIntTypeArgument('width'),
Argument::createIntTypeArgument('height'),
Argument::createIntTypeArgument('rotation', 0),
Argument::createAnyTypeArgument('background_color'),
Argument::createIntTypeArgument('quality'),
new Argument(
'resize_mode',
new TypeCollection(
new EnumType(['crop', 'borders', 'none'])
),
'none'
),
new Argument(
'order',
new TypeCollection(
new EnumListType(['alpha', 'alpha-reverse', 'manual', 'manual-reverse', 'random'])
),
'manual'
),
Argument::createAnyTypeArgument('effects'),
Argument::createBooleanTypeArgument('allow_zoom', false),
Argument::createBooleanTypeArgument('filter_disable_slides', true),
Argument::createAlphaNumStringTypeArgument('group'),
Argument::createAlphaNumStringTypeArgument('format')
);
}
/**
* @throws \Propel\Runtime\Exception\PropelException
*
* @return LoopResult
*/
public function parseResults(LoopResult $loopResult)
{
/** @var \Carousel\Model\Carousel $carousel */
foreach ($loopResult->getResultDataCollection() as $carousel) {
$imgSourcePath = $carousel->getUploadDir().DS.$carousel->getFile();
if (!file_exists($imgSourcePath)) {
Tlog::getInstance()->error(sprintf('Carousel source image file %s does not exists.', $imgSourcePath));
continue;
}
$startDate = $carousel->getStartDate();
$endDate = $carousel->getEndDate();
if ($carousel->getLimited()) {
$now = new \DateTime();
if ($carousel->getDisable()) {
if ($now > $startDate && $now < $endDate) {
$carousel
->setDisable(0)
->save();
}
} else {
if ($now < $startDate || $now > $endDate) {
$carousel
->setDisable(1)
->save();
}
}
}
if ($this->getFilterDisableSlides() && $carousel->getDisable()) {
continue;
}
$loopResultRow = new LoopResultRow($carousel);
$event = new ImageEvent();
$event->setSourceFilepath($imgSourcePath)
->setCacheSubdirectory('carousel');
switch ($this->getResizeMode()) {
case 'crop':
$resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_CROP;
break;
case 'borders':
$resize_mode = \Thelia\Action\Image::EXACT_RATIO_WITH_BORDERS;
break;
case 'none':
default:
$resize_mode = \Thelia\Action\Image::KEEP_IMAGE_RATIO;
}
// Prepare tranformations
$width = $this->getWidth();
$height = $this->getHeight();
$rotation = $this->getRotation();
$background_color = $this->getBackgroundColor();
$quality = $this->getQuality();
$effects = $this->getEffects();
$format = $this->getFormat();
if (null !== $width) {
$event->setWidth($width);
}
if (null !== $height) {
$event->setHeight($height);
}
$event->setResizeMode($resize_mode);
if (null !== $rotation) {
$event->setRotation($rotation);
}
if (null !== $background_color) {
$event->setBackgroundColor($background_color);
}
if (null !== $quality) {
$event->setQuality($quality);
}
if (null !== $effects) {
$event->setEffects($effects);
}
if (null !== $format) {
$event->setFormat($format);
}
$event->setAllowZoom($this->getAllowZoom());
// Dispatch image processing event
$this->dispatcher->dispatch($event, TheliaEvents::IMAGE_PROCESS);
if ($startDate) {
$startDate = $startDate->format('Y-m-d').'T'.$startDate->format('H:i');
}
if ($endDate) {
$endDate = $endDate->format('Y-m-d').'T'.$endDate->format('H:i');
}
$loopResultRow
->set('ID', $carousel->getId())
->set('LOCALE', $this->locale)
->set('IMAGE_URL', $event->getFileUrl())
->set('ORIGINAL_IMAGE_URL', $event->getOriginalFileUrl())
->set('IMAGE_PATH', $event->getCacheFilepath())
->set('ORIGINAL_IMAGE_PATH', $event->getSourceFilepath())
->set('TITLE', $carousel->getVirtualColumn('i18n_TITLE'))
->set('CHAPO', $carousel->getVirtualColumn('i18n_CHAPO'))
->set('DESCRIPTION', $carousel->getVirtualColumn('i18n_DESCRIPTION'))
->set('POSTSCRIPTUM', $carousel->getVirtualColumn('i18n_POSTSCRIPTUM'))
->set('ALT', $carousel->getVirtualColumn('i18n_ALT'))
->set('URL', $carousel->getUrl())
->set('POSITION', $carousel->getPosition())
->set('DISABLE', $carousel->getDisable())
->set('GROUP', $carousel->getGroup())
->set('LIMITED', $carousel->getLimited())
->set('START_DATE', $startDate)
->set('END_DATE', $endDate)
;
$loopResult->addRow($loopResultRow);
}
return $loopResult;
}
/**
* this method returns a Propel ModelCriteria.
*
* @return \Propel\Runtime\ActiveQuery\ModelCriteria
*/
public function buildModelCriteria()
{
$search = CarouselQuery::create();
$group = $this->getGroup();
$this->configureI18nProcessing($search, ['ALT', 'TITLE', 'CHAPO', 'DESCRIPTION', 'POSTSCRIPTUM']);
$orders = $this->getOrder();
// Results ordering
foreach ($orders as $order) {
switch ($order) {
case 'alpha':
$search->addAscendingOrderByColumn('i18n_TITLE');
break;
case 'alpha-reverse':
$search->addDescendingOrderByColumn('i18n_TITLE');
break;
case 'manual-reverse':
$search->orderByPosition(Criteria::DESC);
break;
case 'manual':
$search->orderByPosition(Criteria::ASC);
break;
case 'random':
$search->clearOrderByColumns();
$search->addAscendingOrderByColumn('RAND()');
break 2;
break;
}
}
if ($group) {
$search->filterByGroup($group);
}
return $search;
}
}

View File

@@ -0,0 +1,120 @@
<?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 Carousel\Model;
use Carousel\Model\Base\Carousel as BaseCarousel;
use Propel\Runtime\ActiveQuery\ModelCriteria;
use Propel\Runtime\Connection\ConnectionInterface;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
use Thelia\Files\FileModelInterface;
use Thelia\Files\FileModelParentInterface;
use Thelia\Form\BaseForm;
class Carousel extends BaseCarousel implements FileModelInterface
{
public function preDelete(ConnectionInterface $con = null)
{
$carousel = new \Carousel\Carousel();
$fs = new Filesystem();
try {
$fs->remove($carousel->getUploadDir().DS.$this->getFile());
return true;
} catch (IOException $e) {
return false;
}
}
/**
* Set file parent id.
*
* @param int $parentId parent id
*
* @return $this
*/
public function setParentId($parentId)
{
return $this;
}
/**
* Get file parent id.
*
* @return int parent id
*/
public function getParentId()
{
return $this->getId();
}
/**
* @return FileModelParentInterface the parent file model
*/
public function getParentFileModel()
{
return new static();
}
/**
* Get the ID of the form used to change this object information.
*
* @return BaseForm the form
*/
public function getUpdateFormId()
{
return 'carousel.image';
}
/**
* @return string the path to the upload directory where files are stored, without final slash
*/
public function getUploadDir()
{
$carousel = new \Carousel\Carousel();
return $carousel->getUploadDir();
}
/**
* @return string the URL to redirect to after update from the back-office
*/
public function getRedirectionUrl()
{
return '/admin/module/Carousel';
}
/**
* Get the Query instance for this object.
*
* @return ModelCriteria
*/
public function getQueryInstance()
{
return CarouselQuery::create();
}
/**
* @param bool $visible true if the file is visible, false otherwise
*
* @return FileModelInterface
*/
public function setVisible($visible)
{
// Not implemented
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?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 Carousel\Model;
use Carousel\Model\Base\CarouselI18n as BaseCarouselI18n;
class CarouselI18n extends BaseCarouselI18n
{
}

View 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 Carousel\Model;
use Carousel\Model\Base\CarouselI18nQuery as BaseCarouselI18nQuery;
/**
* Skeleton subclass for performing query and update operations on the 'carousel_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 CarouselI18nQuery extends BaseCarouselI18nQuery
{
} // CarouselI18nQuery

View 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 Carousel\Model;
use Carousel\Model\Base\CarouselQuery as BaseCarouselQuery;
/**
* Skeleton subclass for performing query and update operations on the 'carousel' 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 CarouselQuery extends BaseCarouselQuery
{
public function findAllByPosition()
{
return $this->orderByPosition()
->find();
}
} // CarouselQuery

View File

@@ -0,0 +1,69 @@
# Carousel
This module for Thelia add a customizable carousel on your home page. You can upload you own image and overload the default template in your template for using the carousel.
## Installation
* Copy the module into ```<thelia_root>/local/modules/``` directory and be sure that the name of the module is Carousel.
* Activate it in your thelia administration panel
## Usage
In the configuration panel of this module, you can upload as many images as you want.
## Hook
The carousel is installed in the "Home page - main area" (home.body) hook.
## Loop
Customize images with the `carousel` loop, which has the same arguments as the `image` loop. You can define a width, a height, and many other parameters
### Input arguments
|Argument |Description |
|--- |--- |
|**width** | A width in pixels, for resizing image. If only the width is provided, the image ratio is preserved. Example : width="200" |
|**height** | A height in pixels, for resizing image. If only the height is provided, the image ratio is preserved. example : height="200" |
|**rotation** |The rotation angle in degrees (positive or negative) applied to the image. The background color of the empty areas is the one specified by 'background_color'. example : rotation="90" |
|**background_color** |The color applied to empty image parts during processing. Use $rgb or $rrggbb color format. example : background_color="$cc8000"|
|**quality** |The generated image quality, from 0(!) to 100%. The default value is 75% (you can hange this in the Administration panel). example : quality="70"|
|**resize_mode** | If 'crop', the image will have the exact specified width and height, and will be cropped if required. If 'borders', the image will have the exact specified width and height, and some borders may be added. The border color is the one specified by 'background_color'. If 'none' or missing, the image ratio is preserved, and depending od this ratio, may not have the exact width and height required. resize_mode="crop"|
|**effects** |One or more comma separated effects definitions, that will be applied to the image in the specified order. Please see below a detailed description of available effects. Expected values :<ul><li>gamma:value : change the image Gamma to the specified value. Example: gamma:0.7.</li><li>grayscale or greyscale : switch image to grayscale.</li><li>colorize:color : apply a color mask to the image. The color format is $rgb or $rrggbb. Example: colorize:$ff2244.</li><li>negative : transform the image in its negative equivalent.</li><li>vflip or vertical_flip : flip the image vertically.</li><li>hflip or horizontal_flip : flip the image horizontally.</li></ul>example : effects="greyscale,gamma:0.7,vflip" |
|**group** |The name of an image group. Return only images from the specified group|
|**filter_disable_slides** |if true (the default), the disabled slides will not be displayed|
### Ouput arguments
|Variable |Description |
|--- |--- |
|$ID |the image ID |
|$IMAGE_URL |The absolute URL to the generated image |
|$ORIGINAL_IMAGE_URL |The absolute URL to the original image |
|$IMAGE_PATH |The absolute path to the generated image file |
|$ORIGINAL_IMAGE_PATH |The absolute path to the original image file |
|$ALT |alt text |
|$TITLE |the slide title |
|$CHAPO |the slide summary |
|$DESCRIPTION |the slide description |
|$POSTSCRIPTUM |the slide conclusion |
|$LOCALE |the textual elements locale |
|$POSITION |the slide position in the carousel |
|$URL |the related URL |
|$LIMITED| true if slide is disabled, false otherwise |
|$START_DATE| limited slide display start date |
|$END_DATE| limited slide display end date |
|$DISABLE| true if slide display is limited |
|$GROUP| name of the group the slide belong to |
### Exemple
```
{loop type="carousel" name="carousel.front" width="1200" height="390" resize_mode="borders"}
<img src="{$IMAGE_URL}" alt="{$ALT}">
{/loop}
```
## How to override ?
If you want your own carousel in your tempalte, create the directory ```modules/Carousel``` then create the template ```carousel.html``` in this directory. Here you can create your own carousel and the replace the default template provided in the module.

View File

@@ -0,0 +1,11 @@
{
"name": "thelia/carousel-module",
"license": "LGPL-3.0+",
"type": "thelia-module",
"require": {
"thelia/installer": "~1.1"
},
"extra": {
"installer-name": "Carousel"
}
}

View File

@@ -0,0 +1,6 @@
$(function() {
// Set proper image ID in delete from
$('a.image-delete').click(function(ev) {
$('#image_delete_id').val($(this).data('id'));
});
});

View File

@@ -0,0 +1,179 @@
<div class="general-block-decorator">
<div class="row">
<div class="col-md-12 title title-without-tabs">
{intl l='Edit your carousel.' d='carousel.bo.default'}
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-container">
{form name=Carousel\Form\CarouselImageForm::getName()}
<form method="POST" action="{url path="/admin/module/carousel/upload"}" {form_enctype} class="clearfix">
{form_hidden_fields}
{form_field field='file'}
<div class="form-group {if $error}has-error{/if}">
<label for="{$label_attr.for|default:null}" class="control-label">{intl d='carousel.bo.default' l='Add an image to the carousel'}</label>
<div class="input-group">
<input type="file" id="{$label_attr.for|default:null}" {if $required}required="required"{/if} name="{$name}" value="{$value}" title="{intl l='Carousel image' d='carousel.bo.default'}" placeholder="{intl l='Carousel image' d='carousel.bo.default'}" class="form-control">
<span class="input-group-btn">
<input type="submit" class="form-submit-button btn btn-sm btn-success" value="{intl d='carousel.bo.default' l='Add this image to the carousel'}" >
</span>
</div>
</div>
{/form_field}
</form>
{/form}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12 title title-without-tabs">
{intl l='Carousel images' d='carousel.bo.default'}
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="form-container">
{ifloop rel="carousel.image"}
{form name="Carousel\Form\CarouselUpdateForm"}
<form method="post" action="{url path="/admin/module/carousel/update"}" {form_enctype} class="clearfix">
{include
file = "includes/inner-form-toolbar.html"
page_url = "{url path='/admin/module/Carousel'}"
close_url = "{url path='/admin/modules'}"
}
{form_hidden_fields}
{loop name="carousel.image" type="carousel" width="550" height="200" resize_mode="borders" backend_context="1" lang="$edit_language_id" filter_disable_slides=false}
<div class="well well-sm">
<div class="row">
<div class="col-md-6">
<p>
<a href="{$ORIGINAL_IMAGE_URL}" class="thumbnail" target="_blank">
<img src="{$IMAGE_URL}" alt="{$ALT}">
</a>
</p>
<div class="btn-group">
<a class="btn btn-default btn-sm image-delete" href="#delete_carousel_dialog" data-toggle="modal" data-id="{$ID}">
<i class="glyphicon glyphicon-trash"></i> {intl d='carousel.bo.default' l='Remove this image'}
</a>
</div>
<div class="pull-right row" style="width:170px">
<div class="col-xs-5" style="padding-top:5px">
<label for="position{$ID}">{intl d='carousel.bo.default' l='Position'}:</label>
</div>
<div class="col-xs-7">
{form_field field="position{$ID}"}
<input id="position{$ID}" class="form-control" type="number" min="1" name="{$name}" value={$POSITION}>
{/form_field}
</div>
</div>
<div style="padding-top: 10px">
<div class="row col-md-12">
{form_field field="disable{$ID}"}
<input id="disable{$ID}" type="checkbox" name="{$name}" {if $DISABLE}checked{/if}>
<label for="disable{$ID}">{$label}</label>
{/form_field}
</div>
<div class="row col-md-12">
{form_field field="limited{$ID}"}
<input id="limited{$ID}" type="checkbox" name="{$name}" {if $LIMITED}checked{/if}>
<label for="limited{$ID}">{$label}</label>
{/form_field}
</div>
<div class="row col-md-6">
{form_field field="start_date{$ID}"}
<label class="row col-md-12" for="{$name}">{$label}</label>
<div class="col-md-10" style="padding: 0">
<input name="{$name}"
placeholder="{intl l='YYYY-MM-DD' d='carousel.bo.default'}"
id="start_date{$ID}"
type="datetime-local"
class="form-control datetime-picker"
value="{$START_DATE}"/>
</div>
{/form_field}
</div>
<div class="row col-md-6">
{form_field field="end_date{$ID}"}
<label class="row col-md-12" for="{$name}">{$label}</label>
<div class="col-md-10" style="padding: 0">
<input name="{$name}"
placeholder="{intl l='YYYY-MM-DD' d='carousel.bo.default'}"
id="end_date{$ID}"
type="datetime-local"
class="form-control datetime-picker"
value="{$END_DATE}"/>
</div>
{/form_field}
</div>
</div>
</div>
<div class="col-md-6">
{* Not yet implemented
{render_form_field field="chapo{$ID} value=$CHAPO"}
*}
{render_form_field field="title{$ID}" value=$TITLE}
{render_form_field field="alt{$ID}" value=$ALT}
{render_form_field field="url{$ID}" value=$URL}
{render_form_field field="description{$ID}" extra_class="wysiwyg" value=$DESCRIPTION}
{render_form_field field="group{$ID}" value=$GROUP}
{* Not yet implemented
{render_form_field field="postscriptum{$ID}" value=$POSTSCRIPTUM}
*}
</div>
</div>
</div>
{/loop}
{include
file = "includes/inner-form-toolbar.html"
page_url = "{url path='/admin/module/Carousel'}"
close_url = "{url path='/admin/modules'}"
page_bottom = true
}
</form>
{/form}
{/ifloop}
{elseloop rel="carousel.image"}
<div class="alert alert-info">
{intl d='carousel.bo.default' l="Your carousel contains no image. Please add one using the form above."}
</div>
{/elseloop}
</div>
</div>
</div>
</div>
{capture "delete_dialog"}
<input type="hidden" name="image_id" id="image_delete_id" value="" />
{/capture}
{include
file = "includes/generic-confirm-dialog.html"
dialog_id = "delete_carousel_dialog"
dialog_title = {intl l="Delete a carousel image" d="carousel.bo.default"}
dialog_message = {intl l="Do you really want to remove this image from the carousel ?" d="carousel.bo.default"}
form_action = {url path='/admin/module/carousel/delete'}
form_content = {$smarty.capture.delete_dialog nofilter}
}

View File

@@ -0,0 +1,24 @@
{ifloop rel="carousel.front"}
<section class="carousel-container">
<div id="carousel" class="carousel slide" data-ride="carousel">
<div class="carousel-wrapper">
<div class="carousel-inner">
{loop type="carousel" name="carousel.front" width="1200" height="390" resize_mode="borders"}
<figure class="item {if $LOOP_COUNT == 1}active{/if}">
{if $URL}<a href="{$URL|default:'#'}">{/if}
<img src="{$IMAGE_URL}" alt="{$ALT}">
{if $URL}</a>{/if}
<div class="carousel-caption">
{if $TITLE}<h3>{$TITLE}</h3>{/if}
{if $DESCRIPTION}{$DESCRIPTION nofilter}{/if}
</div>
</figure>
{/loop}
</div>
</div>
<a class="left carousel-control" href="#carousel" data-slide="prev"><span class="icon-prev"></span></a>
<a class="right carousel-control" href="#carousel" data-slide="next"><span class="icon-next"></span></a>
</div>
</section><!-- #carousel -->
{/ifloop}