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.');
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc