Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
christophluehr committed Sep 8, 2019
0 parents commit 30cfb62
Show file tree
Hide file tree
Showing 17 changed files with 1,145 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.idea
15 changes: 15 additions & 0 deletions BasilicomThumbnailBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

namespace Basilicom\ThumbnailBundle;

use Pimcore\Extension\Bundle\AbstractPimcoreBundle;

class BasilicomThumbnailBundle extends AbstractPimcoreBundle
{
public function getJsPaths()
{
return [
'/bundles/basilicomthumbnail/js/pimcore/startup.js'
];
}
}
49 changes: 49 additions & 0 deletions Command/ThumbnailCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace Basilicom\ThumbnailBundle\Command;

use Basilicom\ThumbnailBundle\Message\ThumbnailJob;
use Pimcore\Console\AbstractCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Messenger\MessageBusInterface;

class ThumbnailCommand extends AbstractCommand
{

private $bus;

public function __construct(string $name = null, MessageBusInterface $bus)
{
parent::__construct($name);
$this->bus = $bus;
}

protected function configure()
{
$this->setName('basilicom:thumbnail')
->setDescription('Generates missing Thumbnails')
->setHelp('this command generates thumbnails');
}

/**
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int|null|void
*
* @example bin/console basilicom:thumbnail
*
* - is the input file in expected format:
* does it have a column 'key'
* are there any fields that pimcore doesn't know about
*
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->bus->dispatch(new ThumbnailJob(1));
$output->writeln('thumbnail creation');
}
}
19 changes: 19 additions & 0 deletions Controller/DefaultController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Basilicom\ThumbnailBundle\Controller;

use Pimcore\Controller\FrontendController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;

class DefaultController extends FrontendController
{
/**
* @Route("/basilicom_thumbnail")
*/
public function indexAction(Request $request)
{
return new Response('Hello world from basilicom_thumbnail');
}
}
28 changes: 28 additions & 0 deletions DependencyInjection/BasilicomThumbnailExtension.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Basilicom\ThumbnailBundle\DependencyInjection;

use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Loader;

/**
* This is the class that loads and manages your bundle configuration.
*
* @link http://symfony.com/doc/current/cookbook/bundles/extension.html
*/
class BasilicomThumbnailExtension extends Extension
{
/**
* {@inheritdoc}
*/
public function load(array $configs, ContainerBuilder $container)
{
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);

$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
}
}
29 changes: 29 additions & 0 deletions DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php

namespace Basilicom\ThumbnailBundle\DependencyInjection;

use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;

/**
* This is the class that validates and merges configuration from your app/config files.
*
* To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/configuration.html}
*/
class Configuration implements ConfigurationInterface
{
/**
* {@inheritdoc}
*/
public function getConfigTreeBuilder()
{
$treeBuilder = new TreeBuilder();
$rootNode = $treeBuilder->root('basilicom_thumbnail');

// Here you should define the parameters that are allowed to
// configure your bundle. See the documentation linked above for
// more information on that topic.

return $treeBuilder;
}
}
84 changes: 84 additions & 0 deletions EventListener/AssetListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php
namespace Basilicom\ThumbnailBundle\EventListener;

use Basilicom\ThumbnailBundle\Message\ThumbnailJob;
use Pimcore\Event\Model\ElementEventInterface;
use Pimcore\Model\Asset;
use Pimcore\Model\Asset\Image\Thumbnail\Config as ThumbnailConfig;
use Symfony\Component\Messenger\MessageBusInterface;
use Pimcore\Logger;

class AssetListener
{

private $bus;

private $placeholderAssetFile;
private $placeholderAsset = null; // unused for now

public function __construct(MessageBusInterface $bus)
{
$this->bus = $bus;
$this->placeholderAssetFile = __DIR__ . '/../Resources/public/img/thumbnail.jpg';

// @todo make file configurable, better use a "real" asset and generate
// "real" thumbnails!
}

public function onPostUpdate(ElementEventInterface $e)
{
/** @var Asset $asset */
$asset = $e->getAsset();

Logger::debug('BTB AssetListener onPostUpdate for asset with ID ' . $asset->getId());

if ($asset->getType() == 'folder') {
return;
}

// system Thumbnail
$systemPreviewConfig = ThumbnailConfig::getPreviewConfig();
$this->createThumbnailPlaceholder($asset, $systemPreviewConfig);

// thumbnail formats via CSV asset property "thumbnailConfig":
$thumbnailConfigs = $asset->getProperty('thumbnailConfig');
$thumbnailConfigList = explode(',', $thumbnailConfigs);
foreach ($thumbnailConfigList as $thumbnailConfigName) {
$thumbnailConfig = ThumbnailConfig::getByName($thumbnailConfigName);
if (is_object($thumbnailConfig)) {
$this->createThumbnailPlaceholder($asset, $thumbnailConfig);
}
}

$this->bus->dispatch(new ThumbnailJob($asset->getId()));
Logger::debug('BTB Dispatched ThumbnalJob for image with ID ' . $asset->getId());

}

public function onPostAdd(ElementEventInterface $e)
{
$this->onPostUpdate($e);
}

/**
* @param $asset
* @param $thumbnailConfig ThumbnailConfig
* @todo use a real asset as thumbnail preview
*/
private function createThumbnailPlaceholder($asset, $thumbnailConfig)
{

$path = $asset->getThumbnail($thumbnailConfig)->getFileSystemPath(true);
if (!file_exists($path)) {
$dir = dirname($path);
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
copy($this->placeholderAssetFile, $path);
@touch($path, $asset->getModificationDate());
Logger::debug('BTB Created Placeholder '.$thumbnailConfig->getName()
. ' for image with ID ' . $asset->getId()
. ' Path: ' . $path);
}
}
}
1 change: 1 addition & 0 deletions License.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GPLv3 - see gpl-3.0.txt
19 changes: 19 additions & 0 deletions Message/ThumbnailJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php
// src/Message/SmsNotification.php

namespace Basilicom\ThumbnailBundle\Message;

class ThumbnailJob
{
private $assetId;

public function __construct($assetId)
{
$this->assetId = $assetId;
}

public function getAssetId()
{
return $this->assetId;
}
}
50 changes: 50 additions & 0 deletions MessageHandler/ThumbnailHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
// src/Message/SmsNotification.php

namespace Basilicom\ThumbnailBundle\MessageHandler;

use Basilicom\ThumbnailBundle\Message\ThumbnailJob;
use Pimcore\Logger;
use Pimcore\Model\Asset;
use Pimcore\Model\Asset\Image\Thumbnail\Config as ThumbnailConfig;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface;

class ThumbnailHandler implements MessageHandlerInterface
{
public function __invoke(ThumbnailJob $message)
{
Logger::debug('BTB Reveived ThumbnailJob with asset ID'.$message->getAssetId());

$asset = Asset::getById($message->getAssetId());

if (!is_object($asset)) {
return;
}

// clear placeholders
$asset->clearThumbnail(ThumbnailConfig::getPreviewConfig()->getName());

// system thumbnail format
$path = $asset->getThumbnail(ThumbnailConfig::getPreviewConfig())->getFileSystemPath();

Logger::debug('BTB Generated thumbnail [system] for asset ID '
. $message->getAssetId()
. ' Path:' .$path);

// thumbnail formats via CSV asset property "thumbnailConfig":
$thumbnailConfigs = $asset->getProperty('thumbnailConfig');
$thumbnailConfigList = explode(',', $thumbnailConfigs);
foreach ($thumbnailConfigList as $thumbnailConfigName) {

$thumbnailConfig = ThumbnailConfig::getByName($thumbnailConfigName);
if (is_object($thumbnailConfig)) {
$asset->clearThumbnail($thumbnailConfig->getName());
$path = $asset->getThumbnail($thumbnailConfig)->getFileSystemPath();
Logger::debug('BTB Generated thumbnail ['.$thumbnailConfigName.'] for asset ID '
. $message->getAssetId()
. ' Path:' .$path);
}
}

}
}
75 changes: 75 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Basilicom Thumbnail bundle for Pimcore

Enables asynchronous, worker based thumbnail creation.

## License

GPLv3 - see: gpl-3.0.txt


## Requirements

* Pimcore >= 5.4.0
* RabbitMQ (for ampq on PHP 7.3 see: https://github.com/pdezwart/php-amqp/issues/337)


## Installation

1) Install the bundle using composer `composer require basilicom/thumbnail-bundle`.
2) Execute `bin/console pimcore:bundle:enable BasilicomThumbnailBundle`.


## Configuration

0) As long as there is no patch preventing Pimcore from
generating system thumbnails, change `vendor/pimcore/pimcore/models/Asset/Image.php`,
in method `update` the line `$path = $this->getThumbnail(Image\Thumbnail\Config::getPreviewConfig())->getFileSystemPath();` to
`$path = $this->getThumbnail(Image\Thumbnail\Config::getPreviewConfig())->getFileSystemPath(true);`
1) Disable low quality previwew generation:
```yaml
# app/config/config.yml - 'pimcore' section:
assets:
image:
low_quality_image_preview:
enabled: false
```
2) Configure the Symfony Messenger (see https://symfony.com/doc/current/messenger.html).
```yaml
# app/config/local/messenger.yaml
framework:
messenger:
transports:
#sample format:
#async: "%env(MESSENGER_TRANSPORT_DSN)%"
#redis (seems not to work, problems with timeouts?):
#async: "redis://redis:6379/messages"
#doctrine does not work on pimcore, as only dbal is loaded, not doctrine!
#async: "doctrine://default"
#rabbitmq - works!:
async: "amqp://rabbitmq:rabbitmq@rabbitmq:5672/%2f/messages"
routing:
# async is whatever name you gave your transport above
'Basilicom\ThumbnailBundle\Message\ThumbnailJob': async
# The bus that is going to be injected when injecting MessageBusInterface
default_bus: command.bus
buses:
command.bus:
middleware:
- validation
```
3) Process async messenges (jobs) via console (or supervisord, see: https://symfony.com/doc/current/messenger.html)
```
bin/console messenger:consume
```

### Configure additional thumbnail formats

If there is a text property `thumbnailConfig` on the asset
(possibly inherited from a parent folder) containing a
comma separated list of asset format names, thumbnails
for these formats are going to be generated, too.

### Configure thumbnail placeholders

@todo not implemented, yet

5 changes: 5 additions & 0 deletions Resources/config/pimcore/routing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
basilicom_thumbnail:
resource: "@BasilicomThumbnailBundle/Controller/"
type: annotation
prefix: /

Loading

0 comments on commit 30cfb62

Please sign in to comment.