images styles generation custom module

This commit is contained in:
Bachir Soussi Chiadmi 2021-03-17 18:56:01 +01:00
parent 9bae6d15ff
commit 8964b94b9f
6 changed files with 449 additions and 0 deletions

View File

@ -92,6 +92,7 @@ module:
image_delta_formatter: 0
image_effects: 0
imagemagick: 0
images_styles_gen: 0
inline_entity_form: 0
interval: 0
jquery_ui: 0

View File

@ -0,0 +1,8 @@
name: 'images_styles_cron_gen'
type: module
description: 'helpers for progressive decoupling'
core: 8.x
package: 'custom'
# https://www.flocondetoile.fr/blog/generate-programmatically-image-styles-drupal-8
# https://www.flocondetoile.fr/blog/using-drupal-8-cron-api-generate-image-styles
# https://www.sitepoint.com/drupal-8-queue-api-powerful-manual-and-cron-queueing/

View File

@ -0,0 +1,95 @@
<?php
use Drupal\image\Entity\ImageStyle;
use Drupal\Core\Entity\EntityInterface;
use Drupal\file\FileInterface;
// /**
// * Implements hook_entity_insert().
// * Generate all image styles once an Image is uploaded.
// */
// function images_styles_gen_entity_insert(EntityInterface $entity) {
// /** @var \Drupal\file\Entity\File $entity */
// if ($entity instanceof FileInterface) {
// $image = \Drupal::service('image.factory')->get($entity->getFileUri());
// /** @var \Drupal\Core\Image\Image $image */
// if ($image->isValid()) {
// $styles = ImageStyle::loadMultiple();
// $image_uri = $entity->getFileUri();
// /** @var \Drupal\image\Entity\ImageStyle $style */
// foreach ($styles as $style) {
// $destination = $style->buildUri($image_uri);
// $style->createDerivative($image_uri, $destination);
// }
// }
// }
// }
/**
* Implements hook_entity_insert().
* Queue generation of all image styles once an Image is uploaded.
*/
// function images_styles_gen_entity_insert(EntityInterface $entity) {
// // TODO: IS THIS EVEN WORKING ????
// /** @var \Drupal\file\Entity\File $entity */
// if ($entity instanceof FileInterface) {
// $image = \Drupal::service('image.factory')->get($entity->getFileUri());
// /** @var \Drupal\Core\Image\Image $image */
// if ($image->isValid()) {
// $queue = \Drupal::queue('img_styles_gen');
// $item = new \stdClass();
// $item->fid = $entity->id();
// $queue->createItem($item);
// // $data = ['entity' => $entity];
// // $queue->createItem($data);
// }
// }
// }
// function images_styles_gen_cron_DISABLED(){
// $file_storage = \Drupal::entityTypeManager()->getStorage('file');
// $query = $file_storage->getQuery()
// ->condition('filemime', 'image/%', 'LIKE')
// ->accessCheck(TRUE);
// $results = $query->execute();
//
// // $styles_storage = \Drupal::entityTypeManager()->getStorage('image_style');
// // $styles = $styles_storage->loadMultiple();
//
// /** @var QueueFactory $queue_factory */
// $queue_factory = \Drupal::service('queue');
// /** @var QueueInterface $queue */
// $queue = $queue_factory->get('img_styles_gen');
//
// foreach ($results as $fid) {
// $item = new \stdClass();
// $item->fid = $fid;
// $queue->createItem($item);
//
// // $queue->createItem(["fid" => $fid]);
//
//
// // /** @var \Drupal\file\FileInterface|null $file*/
// // $file_entity = \Drupal::entityTypeManager()->getStorage('file')->load($fid);
// // $image = \Drupal::service('image.factory')->get($file_entity->getFileUri());
// //
// // if ($image->isValid()) {
// // $image_uri = $file_entity->getFileUri();
// // /** @var \Drupal\image\Entity\ImageStyle $style */
// // foreach ($styles as $style) {
// // $destination = $style->buildUri($image_uri);
// // // if destination exists skip
// // if (file_exists($destination)) continue; // skip existing files
// //
// // $data = [
// // 'style' => $style,
// // 'image_uri' => $image_uri,
// // 'destination' => $destination
// // ];
// // $queue->createItem($data);
// // \Drupal::logger('images_styles_gen')->notice("created queue from $image_uri to $destination");
// // }
//
// // }
// }
// }

View File

@ -0,0 +1,7 @@
images_styles_gen.form:
path: '/admin/config/media/imgstylesgen'
defaults:
_form: '\Drupal\images_styles_gen\Form\ImgStylesGenQueueForm'
_title: 'Images Styles Generator'
requirements:
_permission: 'administer site configuration'

View File

@ -0,0 +1,64 @@
<?php
namespace Drupal\images_styles_gen;
// use Drupal\node\Entity\Node;
class CreateImagesStyles {
public static function createStyles($item, &$context){
$context['sandbox']['progress']++;
$context['sandbox']['current_file'] = $item->uri;
// $message = 'Creating Styles ...';
$results = array();
// foreach ($items as $item) {
$results[] = $item->style->createDerivative($item->uri, $item->destination);
// }
// $styles_storage = \Drupal::entityTypeManager()->getStorage('image_style');
// $styles = $styles_storage->loadMultiple();
//
// foreach ($fids as $fid) {
// /** @var \Drupal\file\FileInterface|null $file*/
// $file_entity = \Drupal::entityTypeManager()->getStorage('file')->load($fid);
// $file_uri = $file_entity->getFileUri();
// $image = \Drupal::service('image.factory')->get($file_uri);
// // \Drupal::logger('images_styles_gen')->notice("file_uri is $file_uri");
//
// if ($image->isValid()) {
// /** @var \Drupal\image\Entity\ImageStyle $style */
// foreach ($styles as $style) {
// $destination = $style->buildUri($file_uri);
// // if destination exists skip
// if (file_exists($destination)) continue; // skip existing files
//
// $results[] = $style->createDerivative($file_uri, $destination);
// // \Drupal::logger('images_styles_gen')->notice("Generated style $file_uri to $destination");
// }
//
// }
//
//
// }
// $context['message'] = $message;
// $context['results'] = $results;
$context['message'] = $item->uri . ' processed.';
$context['results'][] = $item->destination;
}
public static function createStylesFinishedCallback($success, $results, $operations) {
// The 'success' parameter means no fatal PHP errors were detected. All
// other error management should be handled using 'results'.
if ($success) {
$message = \Drupal::translation()->formatPlural(
count($results),
'One image processed.', '@count image processed.'
);
}
else {
$message = t('Finished with an error.');
}
drupal_set_message($message);
}
}

View File

@ -0,0 +1,274 @@
<?php
/**
* @file
* Contains \Drupal\npq\Form\NodePublisherQueueForm.
*/
namespace Drupal\images_styles_gen\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Queue\QueueFactory;
use Drupal\Core\Queue\QueueInterface;
use Drupal\Core\Queue\QueueWorkerInterface;
use Drupal\Core\Queue\QueueWorkerManagerInterface;
use Drupal\Core\Queue\SuspendQueueException;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ImgStylesGenQueueForm extends FormBase {
/**
* @var QueueFactory
*/
protected $queueFactory;
/**
* @var QueueWorkerManagerInterface
*/
protected $queueManager;
/**
* {@inheritdoc}
*/
public function __construct(QueueFactory $queue, QueueWorkerManagerInterface $queue_manager) {
$this->queueFactory = $queue;
$this->queueManager = $queue_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('queue'),
$container->get('plugin.manager.queue_worker')
);
}
/**
* {@inheritdoc}.
*/
public function getFormId() {
return 'images_styles_gen_form';
}
/**
* {@inheritdoc}.
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$styles_storage = \Drupal::entityTypeManager()->getStorage('image_style');
$content_type_id = $form_state->getValue('node_type');
$style_id = $form_state->getValue('style');
$batch_size = (int)$form_state->getValue('batch_size');
$num_rows = 0;
if ( $content_type_id && $style_id ) {
$database = \Drupal::database();
$query = $database->select('file_managed', 'fm');
$query->join('file_usage', 'fu', 'fm.fid = fu.fid');
$query->join('node', 'n', 'fu.id = n.nid');
$query
->condition('fm.filemime', 'image/%', 'LIKE')
->condition('fu.type', 'node')
->condition('n.type', $content_type_id)
->fields('fm', ['fid', 'uri'])
->fields('fu', ['id']);
$results = $query->execute();
/** @var \Drupal\image\Entity\ImageStyle $style */
$style = $styles_storage->load($style_id);
foreach ($results as $file) {
$destination = $style->buildUri($file->uri);
if (file_exists($destination)) continue; // if destination exists skip
$num_rows++;
}
}
// select from content type we'll generate derivatives
$contentTypes = \Drupal::service('entity.manager')->
getStorage('node_type')->loadMultiple();
$contentTypesList = [0 => "please choose a content type"];
foreach ($contentTypes as $contentType) {
$contentTypesList[$contentType->id()] = $contentType->label();
}
$form['node_type'] = array(
"#type" => "select",
"#title" => "Content type",
'#options' => $contentTypesList,
'#ajax' => [
'callback' => '::countAjaxCallback', // don't forget :: when calling a class method.
//'callback' => [$this, 'myAjaxCallback'], //alternative notation
'disable-refocus' => FALSE, // Or TRUE to prevent re-focusing on the triggering element.
'event' => 'change',
'wrapper' => 'edit-help-wrapper', // This element is updated with this AJAX callback.
'progress' => [
'type' => 'throbber',
'message' => $this->t('counting entries...'),
],
]
);
// select for which style will generate derivatives
$styles = $styles_storage->loadMultiple(); //, 'card_full', 'linkedmaterial_card'
$stylesList = [0 => "please choose a style"];
foreach ($styles as $style) {
$stylesList[$style->id()] = $style->label();
}
$form['style'] = array(
"#type" => "select",
"#title" => "Images Styles",
'#options' => $stylesList,
'#ajax' => [
'callback' => '::countAjaxCallback', // don't forget :: when calling a class method.
//'callback' => [$this, 'myAjaxCallback'], //alternative notation
'disable-refocus' => FALSE, // Or TRUE to prevent re-focusing on the triggering element.
'event' => 'change',
'wrapper' => 'edit-help-wrapper', // This element is updated with this AJAX callback.
'progress' => [
'type' => 'throbber',
'message' => $this->t('counting entries...'),
],
]
);
$form['batch_size'] = array(
'#type' => 'select',
'#title' => 'Batch size',
'#options' => array(
10 => '10',
100 => '100',
500 => '500',
1000 => '1000',
50000 => '5000',
10000 => '10000',
0 => 'no limit'
),
'#ajax' => [
'callback' => '::countAjaxCallback', // don't forget :: when calling a class method.
//'callback' => [$this, 'myAjaxCallback'], //alternative notation
'disable-refocus' => FALSE, // Or TRUE to prevent re-focusing on the triggering element.
'event' => 'change',
'wrapper' => 'edit-help-wrapper', // This element is updated with this AJAX callback.
'progress' => [
'type' => 'throbber',
'message' => $this->t('counting entries...'),
],
]
);
$form['help-wrapper'] = array(
'#type' => 'container'
);
$form['help-wrapper']['help'] = array(
'#type' => 'markup',
// '#prefix' => '<div>',
'#markup' => $this->t('Please choose a content type and a style.'),
// '#suffix' => '</div>',
'#attributes' => array(
'id' => 'help'
)
);
if ($num_rows) {
if($batch_size == 0){
$batch_size = $num_rows;
}
$form['help-wrapper']['help']['#markup'] = $this->t('Submitting this form will process @batch_size of @number images.', array('@batch_size' => $batch_size, '@number' => $num_rows));
// $form['actions']['submit']['#disabled'] = FALSE;
// unset($form['actions']['submit']['#attributes']['disabled']);
}
$form['help-wrapper']['num_rows'] = array(
'#type' => 'hidden',
'#value' => $num_rows,
);
// Actions
$form['actions']['#type'] = 'actions';
$form['actions']['submit'] = array(
'#type' => 'submit',
'#value' => $this->t('Create image derivatives'),
'#button_type' => 'primary',
// '#disabled' => true,
'#states' => [
//show this submit only if the num rows is not empty
'visible' => [
//don't mistake :input for the type of field. You'll always use
//:input here, no matter whether your source is a select, radio or checkbox element.
':input[name="num_rows"]' => ['!value' => 0],
],
],
);
return $form;
}
// Get the value from example select field and fill
// the textbox with the selected text.
public function countAjaxCallback(array &$form, FormStateInterface $form_state) {
$form['help-wrapper']['#id'] = 'edit-help-wrapper';
return $form['help-wrapper'];
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$content_type_id = $form_state->getValue('node_type');
$style_id = $form_state->getValue('style');
$batch_size = (int)$form_state->getValue('batch_size');
$database = \Drupal::database();
$query = $database->select('file_managed', 'fm');
$query->join('file_usage', 'fu', 'fm.fid = fu.fid');
$query->join('node', 'n', 'fu.id = n.nid');
$query
->condition('fm.filemime', 'image/%', 'LIKE')
->condition('fu.type', 'node')
->condition('n.type', $content_type_id)
->fields('fm', ['fid', 'uri'])
->fields('fu', ['id']);
$results = $query->execute();
$styles_storage = \Drupal::entityTypeManager()->getStorage('image_style');
/** @var \Drupal\image\Entity\ImageStyle $style */
$style = $styles_storage->load($style_id);
$operations = [];
foreach ($results as $file) {
$destination = $style->buildUri($file->uri);
if (file_exists($destination)) continue; // skip existing files
$batch_item = new \stdClass();
$batch_item->style = $style;
$batch_item->uri = $file->uri;
$batch_item->destination = $destination;
$operations[] = ['\Drupal\images_styles_gen\CreateImagesStyles::createStyles', [$batch_item]];
if($batch_size && count($operations) >= $batch_size){
break;
}
}
$batch = array(
'title' => t('Creating images derivatives ...'),
'operations' => $operations,
'finished' => '\Drupal\images_styles_gen\CreateImagesStyles::createStylesFinishedCallback',
);
batch_set($batch);
}
}