images styles generation custom module
This commit is contained in:
parent
9bae6d15ff
commit
8964b94b9f
|
@ -92,6 +92,7 @@ module:
|
||||||
image_delta_formatter: 0
|
image_delta_formatter: 0
|
||||||
image_effects: 0
|
image_effects: 0
|
||||||
imagemagick: 0
|
imagemagick: 0
|
||||||
|
images_styles_gen: 0
|
||||||
inline_entity_form: 0
|
inline_entity_form: 0
|
||||||
interval: 0
|
interval: 0
|
||||||
jquery_ui: 0
|
jquery_ui: 0
|
||||||
|
|
|
@ -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/
|
|
@ -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");
|
||||||
|
// // }
|
||||||
|
//
|
||||||
|
// // }
|
||||||
|
// }
|
||||||
|
// }
|
|
@ -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'
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue