dynamic_image_generator-1.0.x-dev/dynamic_image_generator.install
dynamic_image_generator.install
<?php
/**
* @file
* Install, update and uninstall functions for the dynamic_image_generator module.
*
* This file contains all installation, update, and uninstallation hooks
* for the Dynamic Image Generator module. It handles:
* - Directory creation
* - Media type creation
* - Field configuration
* - View creation
* - Cleanup operations
*/
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\media\Entity\MediaType;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
use Drupal\Core\File\FileSystemInterface;
use Drupal\views\Entity\View;
/**
* Implements hook_install().
*
* Performs initial setup when the module is installed:
* - Creates necessary directories for image storage
* - Sets up the dynamic image media type with required fields
* - Creates the gallery view for browsing generated images
*/
function dynamic_image_generator_install() {
// Create necessary directories first.
dynamic_image_generator_create_directories();
// Create the dynamic image media type during module installation.
dynamic_image_generator_create_dynamic_image_media_type();
// Schedule view creation for after all caches are cleared
\Drupal::state()->set('dynamic_image_generator_create_view_on_next_cache_clear', TRUE);
// Display success message.
\Drupal::messenger()->addMessage(t('Dynamic Image Generator module installed successfully. Directories created and media type configured.'));
}
/**
* Implements hook_cache_flush().
*
* Create the view after caches are flushed during installation.
*/
function dynamic_image_generator_cache_flush() {
if (\Drupal::state()->get('dynamic_image_generator_create_view_on_next_cache_clear')) {
\Drupal::state()->delete('dynamic_image_generator_create_view_on_next_cache_clear');
dynamic_image_generator_create_generated_images_view();
}
}
/**
* Creates necessary directories for image generation (safe method).
*/
function dynamic_image_generator_create_directories() {
$file_system = \Drupal::service('file_system');
$directories = [
'public://dynamic_image_generator',
'public://dynamic_image_generator/generated',
'public://dynamic_image_generator/backgrounds',
];
$created_dirs = [];
$failed_dirs = [];
foreach ($directories as $directory) {
try {
// Use Drupal's prepareDirectory which handles permissions properly
$result = $file_system->prepareDirectory(
$directory,
FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS
);
if ($result) {
$created_dirs[] = $directory;
$real_path = $file_system->realpath($directory);
\Drupal::logger('dynamic_image_generator')->info('Successfully created/verified directory: @dir (real path: @real)', [
'@dir' => $directory,
'@real' => $real_path,
]);
} else {
$failed_dirs[] = $directory;
\Drupal::logger('dynamic_image_generator')->warning('Failed to create directory: @dir', ['@dir' => $directory]);
}
}
catch (\Exception $e) {
$failed_dirs[] = $directory;
\Drupal::logger('dynamic_image_generator')->error('Exception creating directory @dir: @error', [
'@dir' => $directory,
'@error' => $e->getMessage(),
]);
}
}
// Log results
if (!empty($created_dirs)) {
\Drupal::logger('dynamic_image_generator')->info('Created/verified directories: @dirs', [
'@dirs' => implode(', ', $created_dirs),
]);
\Drupal::messenger()->addMessage(t('Dynamic image generator directories created successfully.'));
}
if (!empty($failed_dirs)) {
\Drupal::logger('dynamic_image_generator')->error('Failed to create directories: @dirs', [
'@dirs' => implode(', ', $failed_dirs),
]);
$message = t('Some directories could not be created automatically: @dirs. Please ensure the web server has write permissions to the files directory.', [
'@dirs' => implode(', ', $failed_dirs),
]);
\Drupal::messenger()->addWarning($message);
}
}
/**
* Creates the dynamic image media type with required fields.
*/
function dynamic_image_generator_create_dynamic_image_media_type() {
// Check if media type already exists
$media_type = MediaType::load('dynamic_image');
if ($media_type) {
return;
}
// Create the media type
$media_type = MediaType::create([
'id' => 'dynamic_image',
'label' => 'Dynamic Image',
'description' => 'Media type for storing generated dynamic images',
'source' => 'image',
'source_configuration' => [
'source_field' => 'field_dynamic_image',
],
'field_map' => [
'name' => 'name',
],
'status' => TRUE,
]);
$media_type->save();
// Create required fields for the media type - programmatically, not using config files
dynamic_image_generator_create_media_fields();
\Drupal::logger('dynamic_image_generator')->info('Dynamic image media type created successfully');
}
/**
* Creates media fields for the dynamic image media type.
*/
function dynamic_image_generator_create_media_fields() {
// Clear caches first to ensure proper field creation
drupal_flush_all_caches();
// --- Dynamic Image field (image) ---
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_dynamic_image')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_dynamic_image',
'entity_type' => 'media',
'type' => 'image',
'settings' => [
'target_type' => 'file',
'display_field' => FALSE,
'display_default' => FALSE,
'uri_scheme' => 'public',
],
'cardinality' => 1,
]);
$field_storage->save();
\Drupal::logger('dynamic_image_generator')->info('Created field storage: field_dynamic_image');
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_dynamic_image')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_dynamic_image'),
'bundle' => 'dynamic_image',
'label' => 'Dynamic Image',
'description' => 'The generated dynamic image file',
'required' => TRUE,
'settings' => [
'file_directory' => 'dynamic_image_generator/generated',
'file_extensions' => 'png jpg jpeg',
'max_filesize' => '10 MB',
'max_resolution' => '2000x2000',
'min_resolution' => '100x100',
'alt_field' => TRUE,
'alt_field_required' => FALSE,
'title_field' => FALSE,
'title_field_required' => FALSE,
],
]);
$field_config->save();
\Drupal::logger('dynamic_image_generator')->info('Created field config: field_dynamic_image');
}
// --- Source Entity field (entity reference to node) ---
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_source_entity')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_source_entity',
'entity_type' => 'media',
'type' => 'entity_reference',
'settings' => [
'target_type' => 'node',
],
'cardinality' => 1,
]);
$field_storage->save();
\Drupal::logger('dynamic_image_generator')->info('Created field storage: field_source_entity');
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_source_entity')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_source_entity'),
'bundle' => 'dynamic_image',
'label' => 'Source Entity',
'description' => 'The entity this image was generated from',
'required' => FALSE,
'settings' => [
'handler' => 'default:node',
'handler_settings' => [],
],
]);
$field_config->save();
\Drupal::logger('dynamic_image_generator')->info('Created field config: field_source_entity');
}
// --- Template field (entity reference to Image Template) ---
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_template_id')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_template_id',
'entity_type' => 'media',
'type' => 'entity_reference',
'settings' => [
'target_type' => 'poster_entity',
],
'cardinality' => 1,
]);
$field_storage->save();
\Drupal::logger('dynamic_image_generator')->info('Created field storage: field_template_id');
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_template_id')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_template_id'),
'bundle' => 'dynamic_image',
'label' => 'Template',
'description' => 'The template used to generate this image',
'required' => TRUE,
'settings' => [
'handler' => 'default:poster_entity',
'handler_settings' => [],
],
]);
$field_config->save();
\Drupal::logger('dynamic_image_generator')->info('Created field config: field_template_id');
}
// Clear caches after field creation
drupal_flush_all_caches();
\Drupal::logger('dynamic_image_generator')->info('All media fields created successfully');
}
/**
* Creates the Generated Dynamic Images view programmatically.
*/
function dynamic_image_generator_create_generated_images_view() {
// Check if view already exists
$view = \Drupal\views\Entity\View::load('generated_dynamic_images');
if ($view) {
return; // View already exists
}
// Create a simple, working view configuration
$view_config = [
'langcode' => 'en',
'status' => TRUE,
'dependencies' => [
'module' => ['media', 'user', 'views'],
],
'id' => 'generated_dynamic_images',
'label' => 'Generated Dynamic Images',
'module' => 'views',
'description' => 'View all generated dynamic images',
'tag' => 'Dynamic Image Generator',
'base_table' => 'media_field_data',
'base_field' => 'mid',
'display' => [
'default' => [
'display_plugin' => 'default',
'id' => 'default',
'display_title' => 'Default',
'position' => 0,
'display_options' => [
'title' => 'Generated Dynamic Images',
'access' => [
'type' => 'perm',
'options' => ['perm' => 'access content'],
],
'cache' => [
'type' => 'tag',
'options' => [],
],
'query' => [
'type' => 'views_query',
'options' => [
'disable_sql_rewrite' => FALSE,
'distinct' => FALSE,
'replica' => FALSE,
'query_comment' => '',
'query_tags' => [],
],
],
'exposed_form' => [
'type' => 'basic',
'options' => [
'submit_button' => 'Apply',
'reset_button' => TRUE,
'reset_button_label' => 'Reset',
'exposed_sorts_label' => 'Sort by',
'expose_sort_order' => TRUE,
'sort_asc_label' => 'Asc',
'sort_desc_label' => 'Desc',
],
],
'pager' => [
'type' => 'full',
'options' => [
'items_per_page' => 20,
'offset' => 0,
'id' => 0,
'total_pages' => NULL,
'tags' => [
'next' => '››',
'previous' => '‹‹',
'first' => '« First',
'last' => 'Last »',
],
'expose' => [
'items_per_page' => FALSE,
'items_per_page_label' => 'Items per page',
'items_per_page_options' => '5, 10, 25, 50',
'items_per_page_options_all' => FALSE,
'items_per_page_options_all_label' => '- All -',
'offset' => FALSE,
'offset_label' => 'Offset',
],
'quantity' => 9,
],
],
'style' => [
'type' => 'table',
'options' => [
'grouping' => [],
'row_class' => '',
'default_row_class' => TRUE,
'columns' => [
'name' => 'name',
'created' => 'created',
],
'default' => 'created',
'info' => [
'name' => [
'sortable' => TRUE,
'default_sort_order' => 'asc',
'align' => '',
'separator' => '',
'empty_column' => FALSE,
'responsive' => '',
],
'created' => [
'sortable' => TRUE,
'default_sort_order' => 'desc',
'align' => '',
'separator' => '',
'empty_column' => FALSE,
'responsive' => '',
],
],
'override' => TRUE,
'sticky' => TRUE,
'summary' => '',
'empty_table' => FALSE,
'caption' => '',
'description' => '',
],
],
'row' => [
'type' => 'fields',
'options' => [
'default_field_elements' => TRUE,
'inline' => [],
'separator' => '',
'hide_empty' => FALSE,
],
],
'fields' => [
'name' => [
'id' => 'name',
'table' => 'media_field_data',
'field' => 'name',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'field',
'label' => 'Image Name',
'exclude' => FALSE,
'alter' => [
'alter_text' => FALSE,
'make_link' => FALSE,
'absolute' => FALSE,
'external' => FALSE,
'replace_spaces' => FALSE,
'path_case' => 'none',
'trim_whitespace' => FALSE,
'alt' => '',
'rel' => '',
'link_class' => '',
'prefix' => '',
'suffix' => '',
'target' => '',
'nl2br' => FALSE,
'max_length' => 0,
'word_boundary' => TRUE,
'ellipsis' => TRUE,
'more_link' => FALSE,
'more_link_text' => '',
'more_link_path' => '',
'strip_tags' => FALSE,
'trim' => FALSE,
'preserve_tags' => '',
'html' => FALSE,
],
'element_type' => '',
'element_class' => '',
'element_label_type' => '',
'element_label_class' => '',
'element_label_colon' => TRUE,
'element_wrapper_type' => '',
'element_wrapper_class' => '',
'element_default_classes' => TRUE,
'empty' => '',
'hide_empty' => FALSE,
'empty_zero' => FALSE,
'hide_alter_empty' => TRUE,
'click_sort_column' => 'value',
'type' => 'string',
'settings' => [
'link_to_entity' => FALSE,
],
'group_column' => 'value',
'group_columns' => [],
'group_rows' => TRUE,
'delta_limit' => 0,
'delta_offset' => 0,
'delta_reversed' => FALSE,
'delta_first_last' => FALSE,
'multi_type' => 'separator',
'separator' => ', ',
'field_api_classes' => FALSE,
],
'created' => [
'id' => 'created',
'table' => 'media_field_data',
'field' => 'created',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'field',
'label' => 'Created',
'exclude' => FALSE,
'alter' => [
'alter_text' => FALSE,
'make_link' => FALSE,
'absolute' => FALSE,
'external' => FALSE,
'replace_spaces' => FALSE,
'path_case' => 'none',
'trim_whitespace' => FALSE,
'alt' => '',
'rel' => '',
'link_class' => '',
'prefix' => '',
'suffix' => '',
'target' => '',
'nl2br' => FALSE,
'max_length' => 0,
'word_boundary' => TRUE,
'ellipsis' => TRUE,
'more_link' => FALSE,
'more_link_text' => '',
'more_link_path' => '',
'strip_tags' => FALSE,
'trim' => FALSE,
'preserve_tags' => '',
'html' => FALSE,
],
'element_type' => '',
'element_class' => '',
'element_label_type' => '',
'element_label_class' => '',
'element_label_colon' => TRUE,
'element_wrapper_type' => '',
'element_wrapper_class' => '',
'element_default_classes' => TRUE,
'empty' => '',
'hide_empty' => FALSE,
'empty_zero' => FALSE,
'hide_alter_empty' => TRUE,
'click_sort_column' => 'value',
'type' => 'timestamp_ago',
'settings' => [
'future_format' => '@interval hence',
'past_format' => '@interval ago',
'granularity' => 2,
],
'group_column' => 'value',
'group_columns' => [],
'group_rows' => TRUE,
'delta_limit' => 0,
'delta_offset' => 0,
'delta_reversed' => FALSE,
'delta_first_last' => FALSE,
'multi_type' => 'separator',
'separator' => ', ',
'field_api_classes' => FALSE,
],
],
'filters' => [
'status' => [
'id' => 'status',
'table' => 'media_field_data',
'field' => 'status',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'boolean',
'operator' => '=',
'value' => '1',
'group' => 1,
'exposed' => FALSE,
'expose' => [
'operator_id' => '',
'label' => '',
'description' => '',
'use_operator' => FALSE,
'operator' => '',
'operator_limit_selection' => FALSE,
'operator_list' => [],
'identifier' => '',
'required' => FALSE,
'remember' => FALSE,
'multiple' => FALSE,
'remember_roles' => [
'authenticated' => 'authenticated',
],
],
'is_grouped' => FALSE,
'group_info' => [
'label' => '',
'description' => '',
'identifier' => '',
'optional' => TRUE,
'widget' => 'select',
'multiple' => FALSE,
'remember' => FALSE,
'default_group' => 'All',
'default_group_multiple' => [],
'group_items' => [],
],
],
'bundle' => [
'id' => 'bundle',
'table' => 'media_field_data',
'field' => 'bundle',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'bundle',
'operator' => 'in',
'value' => [
'dynamic_image' => 'dynamic_image',
],
'group' => 1,
'exposed' => FALSE,
'expose' => [
'operator_id' => '',
'label' => '',
'description' => '',
'use_operator' => FALSE,
'operator' => '',
'operator_limit_selection' => FALSE,
'operator_list' => [],
'identifier' => '',
'required' => FALSE,
'remember' => FALSE,
'multiple' => FALSE,
'remember_roles' => [
'authenticated' => 'authenticated',
],
'reduce' => FALSE,
],
'is_grouped' => FALSE,
'group_info' => [
'label' => '',
'description' => '',
'identifier' => '',
'optional' => TRUE,
'widget' => 'select',
'multiple' => FALSE,
'remember' => FALSE,
'default_group' => 'All',
'default_group_multiple' => [],
'group_items' => [],
],
],
],
'sorts' => [
'created' => [
'id' => 'created',
'table' => 'media_field_data',
'field' => 'created',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'date',
'order' => 'DESC',
'exposed' => TRUE,
'expose' => [
'label' => 'Creation date',
'field_identifier' => 'created',
],
'granularity' => 'second',
],
],
'empty' => [
'area' => [
'id' => 'area',
'table' => 'views',
'field' => 'area',
'relationship' => 'none',
'group_type' => 'group',
'admin_label' => '',
'plugin_id' => 'text',
'empty' => TRUE,
'content' => [
'value' => '<div class="empty-images-state">
<h3>No Generated Images Found</h3>
<p>No images have been generated yet.</p>
<p><a href="/admin/structure/dynamic-image-templates/add" class="button button--primary">Create Image Template</a></p>
</div>',
'format' => 'full_html',
],
'tokenize' => FALSE,
],
],
'arguments' => [],
'display_extenders' => [],
'cache_metadata' => [
'max-age' => -1,
'contexts' => [
'languages:language_content',
'languages:language_interface',
'url.query_args',
'user.permissions',
],
'tags' => [],
],
],
],
'page_1' => [
'display_plugin' => 'page',
'id' => 'page_1',
'display_title' => 'Page',
'position' => 1,
'display_options' => [
'display_extenders' => [],
'path' => 'admin/content/generated-dynamic-images',
'menu' => [
'type' => 'normal',
'title' => 'Generated Images',
'description' => 'View gallery of generated dynamic images',
'expanded' => FALSE,
'parent' => 'system.admin_content',
'weight' => 5,
'context' => '0',
'menu_name' => 'admin',
],
],
'cache_metadata' => [
'max-age' => -1,
'contexts' => [
'languages:language_content',
'languages:language_interface',
'url.query_args',
'user.permissions',
],
'tags' => [],
],
],
],
];
try {
$view = \Drupal\views\Entity\View::create($view_config);
$view->save();
\Drupal::logger('dynamic_image_generator')->info('Created Generated Dynamic Images view successfully');
\Drupal::messenger()->addMessage(t('Generated Dynamic Images view created successfully.'));
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Failed to create Generated Dynamic Images view: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Update to enhance the view with custom fields after module is fully installed.
*/
function dynamic_image_generator_update_8002() {
// Clear caches first
drupal_flush_all_caches();
// Check if view exists and if fields are available
$view = \Drupal\views\Entity\View::load('generated_dynamic_images');
if (!$view) {
return t('View not found.');
}
// Check if our custom fields exist
$field_storage_dynamic_image = \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_dynamic_image');
$field_storage_source_entity = \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_source_entity');
$field_storage_template_id = \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_template_id');
if (!$field_storage_dynamic_image || !$field_storage_source_entity || !$field_storage_template_id) {
return t('Custom fields not ready yet. Fields will be added to view when available.');
}
// If fields exist, recreate the view with enhanced configuration
$view->delete();
dynamic_image_generator_create_enhanced_images_view();
return t('Enhanced Generated Dynamic Images view has been created with custom fields.');
}
/**
* Creates an enhanced view with custom fields after they're available.
*/
function dynamic_image_generator_create_enhanced_images_view() {
// Enhanced view configuration with custom fields
$view_config = [
'langcode' => 'en',
'status' => TRUE,
'dependencies' => [
'module' => ['dynamic_image_generator', 'image', 'media', 'node', 'user', 'views'],
],
'id' => 'generated_dynamic_images',
'label' => 'Generated Dynamic Images',
'module' => 'views',
'description' => 'Gallery view of all generated dynamic images with thumbnails and links',
'tag' => 'Dynamic Image Generator',
'base_table' => 'media_field_data',
'base_field' => 'mid',
'display' => [
'default' => [
'display_plugin' => 'default',
'id' => 'default',
'display_title' => 'Default',
'position' => 0,
'display_options' => [
'title' => 'Generated Dynamic Images Gallery',
'access' => [
'type' => 'perm',
'options' => ['perm' => 'access content'],
],
'cache' => ['type' => 'tag', 'options' => []],
'query' => [
'type' => 'views_query',
'options' => [
'disable_sql_rewrite' => FALSE,
'distinct' => FALSE,
],
],
'exposed_form' => [
'type' => 'basic',
'options' => [
'submit_button' => 'Apply Filters',
'reset_button' => TRUE,
'reset_button_label' => 'Reset Filters',
],
],
'pager' => [
'type' => 'full',
'options' => [
'items_per_page' => 20,
'offset' => 0,
'id' => 0,
],
],
'style' => [
'type' => 'grid',
'options' => [
'columns' => 4,
'automatic_width' => TRUE,
'alignment' => 'horizontal',
'col_class_default' => TRUE,
'row_class_default' => TRUE,
'row_class_custom' => 'dynamic-image-row',
],
],
'row' => [
'type' => 'fields',
'options' => [
'default_field_elements' => FALSE,
'inline' => [],
'separator' => '',
'hide_empty' => FALSE,
],
],
'fields' => [
'field_dynamic_image' => [
'id' => 'field_dynamic_image',
'table' => 'media__field_dynamic_image',
'field' => 'field_dynamic_image',
'plugin_id' => 'field',
'label' => '',
'exclude' => FALSE,
'type' => 'image',
'settings' => [
'image_style' => 'medium',
'image_link' => 'file',
'image_loading' => ['attribute' => 'lazy'],
],
],
'name' => [
'id' => 'name',
'table' => 'media_field_data',
'field' => 'name',
'plugin_id' => 'field',
'label' => '',
'exclude' => FALSE,
'type' => 'string',
'settings' => ['link_to_entity' => FALSE],
],
'created' => [
'id' => 'created',
'table' => 'media_field_data',
'field' => 'created',
'plugin_id' => 'field',
'label' => '',
'exclude' => FALSE,
'type' => 'timestamp_ago',
'settings' => [
'future_format' => '@interval hence',
'past_format' => '@interval ago',
'granularity' => 2,
],
],
],
'filters' => [
'status' => [
'id' => 'status',
'table' => 'media_field_data',
'field' => 'status',
'plugin_id' => 'boolean',
'operator' => '=',
'value' => '1',
'group' => 1,
'exposed' => FALSE,
],
'bundle' => [
'id' => 'bundle',
'table' => 'media_field_data',
'field' => 'bundle',
'plugin_id' => 'bundle',
'operator' => 'in',
'value' => ['dynamic_image' => 'dynamic_image'],
'group' => 1,
'exposed' => FALSE,
],
],
'sorts' => [
'created' => [
'id' => 'created',
'table' => 'media_field_data',
'field' => 'created',
'plugin_id' => 'date',
'order' => 'DESC',
'exposed' => TRUE,
'expose' => [
'label' => 'Creation date',
'field_identifier' => 'created',
],
],
],
'header' => [
'area_text_custom' => [
'id' => 'area_text_custom',
'table' => 'views',
'field' => 'area_text_custom',
'plugin_id' => 'text_custom',
'empty' => FALSE,
'content' => '<div class="gallery-header">
<h2>Generated Dynamic Images Gallery</h2>
<p>Browse all automatically generated dynamic images. Click images to view full size.</p>
</div>',
'tokenize' => FALSE,
],
],
'empty' => [
'area' => [
'id' => 'area',
'table' => 'views',
'field' => 'area',
'plugin_id' => 'text',
'empty' => TRUE,
'content' => [
'value' => '<div class="empty-images-state">
<div class="empty-icon"></div>
<h3>No Generated Images Found</h3>
<p>No images have been generated yet.</p>
<div class="empty-actions">
<a href="/admin/structure/dynamic-image-templates/add" class="button button--primary">Create Image Template</a>
<a href="/admin/structure/dynamic-image-templates" class="button">Manage Templates</a>
</div>
</div>',
'format' => 'full_html',
],
],
],
],
],
'page_1' => [
'display_plugin' => 'page',
'id' => 'page_1',
'display_title' => 'Gallery Page',
'position' => 1,
'display_options' => [
'path' => 'admin/content/generated-dynamic-images',
'menu' => [
'type' => 'normal',
'title' => 'Generated Images',
'description' => 'View gallery of generated dynamic images',
'expanded' => FALSE,
'parent' => 'system.admin_content',
'weight' => 5,
'context' => '0',
'menu_name' => 'admin',
],
],
],
],
];
try {
$view = \Drupal\views\Entity\View::create($view_config);
$view->save();
\Drupal::logger('dynamic_image_generator')->info('Created enhanced Generated Dynamic Images view successfully');
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Failed to create enhanced Generated Dynamic Images view: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Fix missing fields and view issues - update hook.
*/
function dynamic_image_generator_update_8003() {
// Clear all caches first
drupal_flush_all_caches();
// Force recreate media type and fields
dynamic_image_generator_create_dynamic_image_media_type();
// Verify all fields exist and create missing ones
dynamic_image_generator_verify_and_create_missing_fields();
// Recreate the view
$view = \Drupal\views\Entity\View::load('generated_dynamic_images');
if ($view) {
$view->delete();
}
dynamic_image_generator_create_generated_images_view();
// Clear caches again
drupal_flush_all_caches();
return t('Fixed missing fields and view configuration.');
}
/**
* Verify all required fields exist and create missing ones.
*/
function dynamic_image_generator_verify_and_create_missing_fields() {
$created_fields = [];
$missing_fields = [];
// Check and create field_dynamic_image
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_dynamic_image')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_dynamic_image',
'entity_type' => 'media',
'type' => 'image',
'settings' => [
'target_type' => 'file',
'display_field' => FALSE,
'display_default' => FALSE,
'uri_scheme' => 'public',
],
'cardinality' => 1,
]);
$field_storage->save();
$created_fields[] = 'field_dynamic_image storage';
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_dynamic_image')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_dynamic_image'),
'bundle' => 'dynamic_image',
'label' => 'Dynamic Image',
'description' => 'The generated dynamic image file',
'required' => TRUE,
'settings' => [
'file_directory' => 'dynamic_image_generator/generated',
'file_extensions' => 'png jpg jpeg',
'max_filesize' => '10 MB',
'max_resolution' => '2000x2000',
'min_resolution' => '100x100',
'alt_field' => TRUE,
'alt_field_required' => FALSE,
'title_field' => FALSE,
'title_field_required' => FALSE,
],
]);
$field_config->save();
$created_fields[] = 'field_dynamic_image config';
}
// Check and create field_source_entity
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_source_entity')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_source_entity',
'entity_type' => 'media',
'type' => 'entity_reference',
'settings' => [
'target_type' => 'node',
],
'cardinality' => 1,
]);
$field_storage->save();
$created_fields[] = 'field_source_entity storage';
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_source_entity')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_source_entity'),
'bundle' => 'dynamic_image',
'label' => 'Source Entity',
'description' => 'The entity this image was generated from',
'required' => FALSE,
'settings' => [
'handler' => 'default:node',
'handler_settings' => [],
],
]);
$field_config->save();
$created_fields[] = 'field_source_entity config';
}
// Check and create field_template_id
if (!\Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_template_id')) {
$field_storage = \Drupal\field\Entity\FieldStorageConfig::create([
'field_name' => 'field_template_id',
'entity_type' => 'media',
'type' => 'entity_reference',
'settings' => [
'target_type' => 'poster_entity',
],
'cardinality' => 1,
]);
$field_storage->save();
$created_fields[] = 'field_template_id storage';
}
if (!\Drupal\field\Entity\FieldConfig::loadByName('media', 'dynamic_image', 'field_template_id')) {
$field_config = \Drupal\field\Entity\FieldConfig::create([
'field_storage' => \Drupal\field\Entity\FieldStorageConfig::loadByName('media', 'field_template_id'),
'bundle' => 'dynamic_image',
'label' => 'Template',
'description' => 'The template used to generate this image',
'required' => TRUE,
'settings' => [
'handler' => 'default:poster_entity',
'handler_settings' => [],
],
]);
$field_config->save();
$created_fields[] = 'field_template_id config';
}
// Log results
if (!empty($created_fields)) {
\Drupal::logger('dynamic_image_generator')->info('Created missing fields: @fields', [
'@fields' => implode(', ', $created_fields),
]);
\Drupal::messenger()->addMessage(t('Created missing fields: @fields', [
'@fields' => implode(', ', $created_fields),
]));
} else {
\Drupal::logger('dynamic_image_generator')->info('All required fields already exist');
\Drupal::messenger()->addMessage(t('All required fields verified to exist.'));
}
}
/**
* Create the Generated Dynamic Images view for existing installations.
*/
function dynamic_image_generator_update_8001() {
// Clear caches first
drupal_flush_all_caches();
// Create the view
dynamic_image_generator_create_generated_images_view();
return t('Generated Dynamic Images view has been created.');
}
/**
* Implements hook_uninstall().
*/
function dynamic_image_generator_uninstall() {
// Remove all generated dynamic image media entities first
dynamic_image_generator_cleanup_generated_media();
// Remove views
dynamic_image_generator_remove_views();
// Clean up the media type and its fields
dynamic_image_generator_cleanup_media_type();
// Clean up configuration
dynamic_image_generator_cleanup_configuration();
// Display success message with correct module name
\Drupal::messenger()->addMessage(t('Dynamic Image Generator module uninstalled successfully. Generated files have been preserved for safety.'));
}
/**
* Remove all generated dynamic image media entities.
*/
function dynamic_image_generator_cleanup_generated_media() {
try {
$entity_type_manager = \Drupal::entityTypeManager();
$media_storage = $entity_type_manager->getStorage('media');
// Find all dynamic image media entities
$query = $media_storage->getQuery()
->condition('bundle', 'dynamic_image')
->accessCheck(FALSE);
$media_ids = $query->execute();
if (!empty($media_ids)) {
$media_entities = $media_storage->loadMultiple($media_ids);
$media_storage->delete($media_entities);
\Drupal::logger('dynamic_image_generator')->info('Deleted @count dynamic image media entities during uninstall', [
'@count' => count($media_entities),
]);
}
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Error cleaning up dynamic image media entities: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Remove views created by the module.
*/
function dynamic_image_generator_remove_views() {
try {
$views_to_remove = [
'generated_dynamic_images',
'generated_posters', // Remove old view if it exists
'dynamic_images', // Remove this conflicting view
];
foreach ($views_to_remove as $view_id) {
$view = View::load($view_id);
if ($view) {
$view->delete();
\Drupal::logger('dynamic_image_generator')->info('Deleted view: @view_id', [
'@view_id' => $view_id,
]);
}
}
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Error removing views: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Clean up the dynamic image media type and its fields.
*/
function dynamic_image_generator_cleanup_media_type() {
try {
// Remove field configs first
$field_configs = [
'field_dynamic_image',
'field_template_id',
'field_source_entity',
];
foreach ($field_configs as $field_name) {
$field_config = FieldConfig::loadByName('media', 'dynamic_image', $field_name);
if ($field_config) {
$field_config->delete();
}
}
// Remove field storage configs
foreach ($field_configs as $field_name) {
$field_storage = FieldStorageConfig::loadByName('media', $field_name);
if ($field_storage) {
$field_storage->delete();
}
}
// Remove the media type
$media_type = MediaType::load('dynamic_image');
if ($media_type) {
$media_type->delete();
}
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Error cleaning up media type: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Clean up module configuration.
*/
function dynamic_image_generator_cleanup_configuration() {
try {
$config_factory = \Drupal::configFactory();
$configs_to_delete = [
'dynamic_image_generator.settings',
'media.type.dynamic_image',
'field.storage.media.field_dynamic_image',
'field.storage.media.field_template_id',
'field.storage.media.field_source_entity',
'field.field.media.dynamic_image.field_dynamic_image',
'field.field.media.dynamic_image.field_template_id',
'field.field.media.dynamic_image.field_source_entity',
];
foreach ($configs_to_delete as $config_name) {
$config = $config_factory->getEditable($config_name);
if (!$config->isNew()) {
$config->delete();
}
}
}
catch (\Exception $e) {
\Drupal::logger('dynamic_image_generator')->error('Error cleaning up configuration: @error', [
'@error' => $e->getMessage(),
]);
}
}
/**
* Emergency field creation update - run this if fields are missing.
*/
function dynamic_image_generator_update_8004() {
// Force clear all caches
drupal_flush_all_caches();
// Check if media type exists, create if not
$media_type = \Drupal\media\Entity\MediaType::load('dynamic_image');
if (!$media_type) {
$media_type = \Drupal\media\Entity\MediaType::create([
'id' => 'dynamic_image',
'label' => 'Dynamic Image',
'description' => 'Media type for storing generated dynamic images',
'source' => 'image',
'source_configuration' => [
'source_field' => 'field_dynamic_image',
],
'field_map' => [
'name' => 'name',
],
'status' => TRUE,
]);
$media_type->save();
\Drupal::messenger()->addMessage(t('Created dynamic_image media type.'));
}
// Force create all fields
dynamic_image_generator_verify_and_create_missing_fields();
// Clear caches again
drupal_flush_all_caches();
return t('Emergency field creation completed.');
}
/**
* Fix view creation issues - update hook.
*/
function dynamic_image_generator_update_8005() {
// Clear all caches first
drupal_flush_all_caches();
// Delete existing view if it exists
$view = \Drupal\views\Entity\View::load('generated_dynamic_images');
if ($view) {
$view->delete();
\Drupal::logger('dynamic_image_generator')->info('Deleted existing problematic view');
}
// Recreate the view with proper configuration
dynamic_image_generator_create_generated_images_view();
// Clear caches again
drupal_flush_all_caches();
return t('Fixed view creation issues.');
}