You are here

varbase_media.install in Varbase Media 8.7

Contains install and update for Varbase Media module.

File

varbase_media.install
View source
<?php

/**
 * @file
 * Contains install and update for Varbase Media module.
 */
use Symfony\Component\Yaml\Yaml;
use Drupal\Core\Config\InstallStorage;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\Config\FileStorage;
use Drupal\file\Entity\File;
use Drupal\embed\Entity\EmbedButton;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\File\Exception\FileException;
use Drupal\field\Entity\FieldConfig;
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\varbase\Entity\VarbaseEntityDefinitionUpdateManager;

/**
 * Implements hook_install().
 */
function varbase_media_install() {
  $module_name = preg_replace('/_install$/', '', __FUNCTION__);
  $module_path = Drupal::service('module_handler')
    ->getModule($module_name)
    ->getPath();

  // Processer for install: in [$module_name].info.yml file.
  // --------------------------------------------------------------------------.
  $module_info_file = $module_path . '/' . $module_name . '.info.yml';
  if (file_exists($module_info_file)) {
    $module_info_data = (array) Yaml::parse(file_get_contents($module_info_file));
    if (isset($module_info_data['install']) && is_array($module_info_data['install'])) {
      \Drupal::service('module_installer')
        ->install($module_info_data['install'], TRUE);
    }
  }

  // Install optional configs.
  $optional_install_path = $module_path . '/' . InstallStorage::CONFIG_OPTIONAL_DIRECTORY;
  if (is_dir($optional_install_path)) {
    $config_installer = \Drupal::service('config.installer');
    $config_installer
      ->installDefaultConfig('module', $module_name);

    // Create field storage configs first in active config.
    $storage_config_files = \Drupal::service('file_system')
      ->scanDirectory($optional_install_path, '/^field.storage.*\\.(yml)$/i');
    if (isset($storage_config_files) && is_array($storage_config_files)) {
      foreach ($storage_config_files as $storage_config_file) {
        $storage_config_file_content = file_get_contents(DRUPAL_ROOT . '/' . $storage_config_file->uri);
        $storage_config_file_data = (array) Yaml::parse($storage_config_file_content);
        $config_factory = \Drupal::configFactory()
          ->getEditable($storage_config_file->name);
        $config_factory
          ->setData($storage_config_file_data)
          ->save(TRUE);
      }
    }

    // Install any optional config the module provides.
    $storage = new FileStorage($optional_install_path, StorageInterface::DEFAULT_COLLECTION);
    $config_installer
      ->installOptionalConfig($storage, '');

    // Have the .settings.yml configs into the active config.
    $settings_config_files = \Drupal::service('file_system')
      ->scanDirectory($optional_install_path, '/^.*\\.(settings.yml)$/i');
    if (isset($settings_config_files) && is_array($settings_config_files)) {
      foreach ($settings_config_files as $settings_config_file) {
        $settings_config_file_content = file_get_contents(DRUPAL_ROOT . '/' . $settings_config_file->uri);
        $settings_config_file_data = (array) Yaml::parse($settings_config_file_content);
        $config_factory = \Drupal::configFactory()
          ->getEditable($settings_config_file->name);
        $config_factory
          ->setData($settings_config_file_data)
          ->save(TRUE);
      }
    }
  }

  // --------------------------------------------------------------------------.
  // Configure widgets for entity browser enhanced behaviours.
  $ebe_widgets_config_files = \Drupal::service('file_system')
    ->scanDirectory($optional_install_path, '/^entity_browser_enhanced.widgets.*\\.(yml)$/i');
  if (isset($ebe_widgets_config_files) && is_array($ebe_widgets_config_files)) {
    foreach ($ebe_widgets_config_files as $ebe_widgets_config_file) {
      $ebe_widgets_config_file_content = file_get_contents(DRUPAL_ROOT . '/' . $ebe_widgets_config_file->uri);
      $ebe_widgets_config_file_data = (array) Yaml::parse($ebe_widgets_config_file_content);
      $ebe_widgets_config_factory = \Drupal::configFactory()
        ->getEditable($ebe_widgets_config_file->name);
      $ebe_widgets_config_factory
        ->setData($ebe_widgets_config_file_data)
        ->save(TRUE);
    }
  }

  // Managed Varbase Media Library configurations.
  _varbase_media_managed_media_library_configs();

  // Load Media types icons for the media libraray table view page.
  $source = $module_path . '/images/icons';
  $destination = \Drupal::config('media.settings')
    ->get('icon_base_uri');
  \Drupal::service('file_system')
    ->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
  $files = \Drupal::service('file_system')
    ->scanDirectory($source, '/.*\\.(svg|png|jpg|jpeg|gif)$/');
  foreach ($files as $file) {
    if (!file_exists($destination . DIRECTORY_SEPARATOR . $file->filename)) {
      \Drupal::service('file_system')
        ->copy($file->uri, $destination, FileSystemInterface::EXISTS_ERROR);
    }
  }

  // Configure Entity Embed buttons.
  $embed_button_config_files = \Drupal::service('file_system')
    ->scanDirectory($optional_install_path, '/^embed.button.*\\.(yml)$/i');
  if (isset($embed_button_config_files) && is_array($embed_button_config_files)) {
    foreach ($embed_button_config_files as $embed_button_config_file) {
      $embed_button_config_file_content = file_get_contents(DRUPAL_ROOT . '/' . $embed_button_config_file->uri);
      $embed_button_config_file_data = (array) Yaml::parse($embed_button_config_file_content);
      $embed_button_config_factory = \Drupal::configFactory()
        ->getEditable($embed_button_config_file->name);
      $embed_button_config_factory
        ->setData($embed_button_config_file_data)
        ->save(TRUE);
    }
  }

  // Add Icons for Entity Embed CKEditor Media Library and Gallery.
  if (!\Drupal::isConfigSyncing()) {
    $embed_buttons = [
      // CKEditor Embed Media Library icon for the gallery embed entity button.
      'media' => [
        'source' => DRUPAL_ROOT . '/' . $module_path . '/images/ckeditor/hidpi/embed-media.png',
        'destination' => 'public://embed-media.png',
      ],
      // CKEditor Embed Gallery icon for the gallery embed entity button.
      'gallery' => [
        'source' => DRUPAL_ROOT . '/' . $module_path . '/images/ckeditor/hidpi/embed-gallery.png',
        'destination' => 'public://embed-gallery.png',
      ],
    ];
    foreach ($embed_buttons as $embed_button_id => $embed_button_info) {
      $target_destination = NULL;
      if (version_compare(Drupal::VERSION, '8.7.0', '>=')) {
        try {
          $target_destination = Drupal::service('file_system')
            ->copy($embed_button_info['source'], $embed_button_info['destination']);
        } catch (FileException $e) {
          $target_destination = FALSE;
        }
      }
      else {
        $target_destination = call_user_func('file_unmanaged_copy', $embed_button_info['source'], $embed_button_info['destination']);
      }
      if ($target_destination) {
        $target_file = File::create([
          'uri' => $target_destination,
        ]);
        $target_file
          ->save();
        EmbedButton::load($embed_button_id)
          ->set('icon', EmbedButton::convertImageToEncodedData($target_file
          ->getFileUri()))
          ->save();
      }
      else {
        return t("Unable to copy @source to the public files directory.", [
          '@source' => $embed_button_info['source'],
        ]);
      }
    }
  }
}

/**
 * Implements hook_requirements().
 */
function varbase_media_requirements($phase) {
  $requirements = [];
  if ($phase == 'install') {
    $destination = \Drupal::config('media.settings')
      ->get('icon_base_uri');
    \Drupal::service('file_system')
      ->prepareDirectory($destination, FileSystemInterface::CREATE_DIRECTORY | FileSystemInterface::MODIFY_PERMISSIONS);
    $is_writable = is_writable($destination);
    $is_directory = is_dir($destination);
    if (!$is_writable || !$is_directory) {
      if (!$is_directory) {
        $error = t('The directory %directory does not exist.', [
          '%directory' => $destination,
        ]);
      }
      else {
        $error = t('The directory %directory is not writable.', [
          '%directory' => $destination,
        ]);
      }
      $description = t('An automated attempt to create this directory failed, possibly due to a permissions problem. To proceed with the installation, either create the directory and modify its permissions manually or ensure that the installer has the permissions to create it automatically. For more information, see INSTALL.txt or the <a href=":handbook_url">online handbook</a>.', [
        ':handbook_url' => 'https://www.drupal.org/server-permissions',
      ]);
      if (!empty($error)) {
        $description = $error . ' ' . $description;
        $requirements['varbase_media']['description'] = $description;
        $requirements['varbase_media']['severity'] = REQUIREMENT_ERROR;
      }
    }
  }
  return $requirements;
}

/**
 * Managed Varbase Media Library configurations.
 *
 * Fix [Media Library] and the [Media Grid and Media Table]
 * admin pages to work with Drupal ^8.8.x and ^8.7.x .
 */
function _varbase_media_managed_media_library_configs() {
  $module_path = Drupal::service('module_handler')
    ->getModule('varbase_media')
    ->getPath();
  $managed_config_path = DRUPAL_ROOT . '/' . $module_path . '/config';
  if (version_compare(Drupal::VERSION, '8.8.0', 'lt') === TRUE) {
    $managed_config_path = $managed_config_path . '/managed/lt80800';
  }
  else {

    // Use the latest managed configs from the managed latest directory.
    $managed_config_path = $managed_config_path . '/managed/latest';
  }

  // Ovarride the media view.
  $media_config_path = $managed_config_path . '/views.view.media.yml';
  if (file_exists($media_config_path)) {
    $media_config_content = file_get_contents($media_config_path);
    $media_config_data = (array) Yaml::parse($media_config_content);
    $media_config_factory = \Drupal::configFactory()
      ->getEditable('views.view.media');
    $media_config_factory
      ->setData($media_config_data)
      ->save(TRUE);
  }

  // Ovarride the media library view.
  $media_library_config_path = $managed_config_path . '/views.view.media_library.yml';
  if (file_exists($media_library_config_path)) {
    $media_library_config_content = file_get_contents($media_library_config_path);
    $media_library_config_data = (array) Yaml::parse($media_library_config_content);
    $media_library_config_factory = \Drupal::configFactory()
      ->getEditable('views.view.media_library');
    $media_library_config_factory
      ->setData($media_library_config_data)
      ->save(TRUE);
  }
}

/**
 * Issue #3098789: Fix [Media Library] and the [Media Grid and Media Table].
 *
 * Admin pages to work with Drupal ^8.8.x and ^8.7.x .
 */
function varbase_media_update_8701() {
  _varbase_media_managed_media_library_configs();
}

/**
 * Issue #3103229: Fix icons for [Embed buttons] for the CKEditor.
 *
 * After the change of Embed API as they had droped icon_uuid and change of
 * config schema.
 */
function varbase_media_update_8702() {
  varbase_media_update_8701();
  $module_path = Drupal::service('module_handler')
    ->getModule('varbase_media')
    ->getPath();

  // Add Icons for Entity Embed CKEditor Media Library and Gallery.
  $embed_buttons = [
    // CKEditor Embed Media Library icon for the gallery embed entity button.
    'media' => [
      'source' => DRUPAL_ROOT . '/' . $module_path . '/images/ckeditor/hidpi/embed-media.png',
      'destination' => 'public://embed-media.png',
    ],
    // CKEditor Embed Gallery icon for the gallery embed entity button.
    'gallery' => [
      'source' => DRUPAL_ROOT . '/' . $module_path . '/images/ckeditor/hidpi/embed-gallery.png',
      'destination' => 'public://embed-gallery.png',
    ],
  ];
  foreach ($embed_buttons as $embed_button_id => $embed_button_info) {
    $embed_button_list = \Drupal::configFactory()
      ->listAll('embed.button.' . $embed_button_id);
    if (count($embed_button_list) > 0) {
      $target_destination = NULL;
      if (version_compare(Drupal::VERSION, '8.7.0', '>=')) {
        try {
          $target_destination = Drupal::service('file_system')
            ->copy($embed_button_info['source'], $embed_button_info['destination']);
        } catch (FileException $e) {
          $target_destination = FALSE;
        }
      }
      else {
        $target_destination = call_user_func('file_unmanaged_copy', $embed_button_info['source'], $embed_button_info['destination']);
      }
      if ($target_destination) {
        $target_file = File::create([
          'uri' => $target_destination,
        ]);
        $target_file
          ->save();
        EmbedButton::load($embed_button_id)
          ->set('icon', EmbedButton::convertImageToEncodedData($target_file
          ->getFileUri()))
          ->save();
      }
      else {
        return t("Unable to copy @source to the public files directory.", [
          '@source' => $embed_button_info['source'],
        ]);
      }
    }
  }
}

/**
 * Follow up fix Issue #3103229: Fix icons for [Embed buttons] for the CKEditor.
 *
 * After the change of Embed API as they had droped icon_uuid and change of
 * config schema in case for optional updates or buttons were deleted.
 */
function varbase_media_update_8703() {
  varbase_media_update_8702();
}

/**
 * Issue #3115391: Create new field field_provider for remote video media type.
 */
function varbase_media_update_8704() {

  // When Remote Video media type is active.
  $media_bundle_ids = \Drupal::service('entity_type.bundle.info')
    ->getBundleInfo('media');
  if (isset($media_bundle_ids) && is_array($media_bundle_ids) && count($media_bundle_ids) > 0 && isset($media_bundle_ids['remote_video'])) {

    // Configure field storage media field_provider.
    $field_storage_media_field_provider = FieldStorageConfig::loadByName('media', 'field_provider');
    if (!isset($field_storage_media_field_provider)) {
      FieldStorageConfig::create([
        'field_name' => 'field_provider',
        'entity_type' => 'media',
        'type' => 'string',
        'cardinality' => 1,
      ])
        ->save();
    }

    // Configure init field media remote_video field_provider.
    $field_field_media_remote_video_field_provider = FieldConfig::loadByName('media', 'remote_video', 'field_provider');
    if (!isset($field_field_media_remote_video_field_provider)) {
      FieldConfig::create([
        'field_name' => 'field_provider',
        'entity_type' => 'media',
        'bundle' => 'remote_video',
        'label' => t('Provider'),
      ])
        ->save();
    }
  }
}

/**
 * Follow up #3115391: Update all remote videos, set field_provider value.
 */
function varbase_media_update_8705() {

  // When the Remote Video media type is active.
  $media_bundle_ids = \Drupal::service('entity_type.bundle.info')
    ->getBundleInfo('media');
  if (isset($media_bundle_ids) && is_array($media_bundle_ids) && count($media_bundle_ids) > 0 && isset($media_bundle_ids['remote_video'])) {
    $url_resolver = \Drupal::service('media.oembed.url_resolver');
    $resource_fetcher = \Drupal::service('media.oembed.resource_fetcher');
    $entities = \Drupal::entityTypeManager()
      ->getStorage('media')
      ->loadByProperties([
      'bundle' => 'remote_video',
    ]);

    // When we do have remote video media entities.
    if (isset($entities) && is_array($entities) && count($entities) > 0) {

      // And no syncing for update process.
      if (!\Drupal::isConfigSyncing()) {

        // Fetch the provider name and cach it in the field_provider
        // Not to be changed or fetched again.
        foreach ($entities as $entity) {
          try {
            $resource_url = $url_resolver
              ->getResourceUrl($entity->field_media_oembed_video->value);
            $resource = $resource_fetcher
              ->fetchResource($resource_url);
            $provider = strtolower($resource
              ->getProvider()
              ->getName());
            if ($entity->field_provider->value != $provider) {
              $entity
                ->set('field_provider', $provider);
              $entity
                ->save();
            }
          } catch (Exception $e) {
          }
        }
      }
    }
  }
}

/**
 * Follow up #3115391: Update all remote videos, set oembed view mode type.
 */
function varbase_media_update_8706() {

  // When the Remote Video media type is active.
  $media_bundle_ids = \Drupal::service('entity_type.bundle.info')
    ->getBundleInfo('media');
  if (isset($media_bundle_ids) && is_array($media_bundle_ids) && count($media_bundle_ids) > 0 && isset($media_bundle_ids['remote_video'])) {
    $storage = \Drupal::entityTypeManager()
      ->getStorage('entity_view_display');
    $media_view_modes = \Drupal::service('entity_display.repository')
      ->getViewModes('media');
    if (isset($media_view_modes) && is_array($media_view_modes) && count($media_view_modes) > 0) {
      $media_view_modes['default'] = 'default';
      $media_view_modes = array_keys($media_view_modes);
      foreach ($media_view_modes as $key) {
        $view_display = $storage
          ->load('media.remote_video.' . $key);
        if (isset($view_display)) {
          $config = $view_display
            ->getComponent('field_media_oembed_video');
          if (isset($config['type']) && $config['type'] == 'oembed') {
            $config['type'] = 'varbase_oembed';
            $view_display
              ->setComponent('field_media_oembed_video', $config);
            $view_display
              ->save();
          }
        }
      }
    }
  }
}

/**
 * Issue #3125946: Fix missing varbase media entity presave hook.
 *
 * For remote videos after introduced issues on update with [entityqueue]
 * latest release. Please run [ drupal update:entities ] after the update of
 * entityqueue and Varbase Media.
 */
function varbase_media_update_8707() {

  // When the Remote Video media type is active.
  $media_bundle_ids = \Drupal::service('entity_type.bundle.info')
    ->getBundleInfo('media');
  if (isset($media_bundle_ids) && is_array($media_bundle_ids) && count($media_bundle_ids) > 0 && isset($media_bundle_ids['remote_video'])) {

    // Recall for the following update functions as they had changed
    // as hey introduced issues on update with [entityqueue] latest release
    // Issue #3115391: Create new field field_provider for remote video
    // media type.
    // Follow up on Update all remote videos, set field_provider value.
    // Follow up onUpdate all remote videos, set oembed view mode type.
    varbase_media_update_8704();
    varbase_media_update_8705();
    varbase_media_update_8706();
  }
}

/**
 * Helper function to rename slick_media config dependencies to slick.
 *
 * Https://git.drupalcode.org/project/slick_media/-/blob/8.x-3.x/slick_media.install.
 *
 * @param string $dependency_type
 *   The type of the dependency, such as "module" or "config".
 * @param string $dependency_id
 *   The name of the dependency to be updated.
 * @param callable $map
 *   A callback to be passed to array_map() to actually perform the config name
 *   substitution.
 */
function _varbase_media_slick_media_fix_dependencies($dependency_type, $dependency_id, callable $map) {
  $dependents = \Drupal::service('config.manager')
    ->findConfigEntityDependents($dependency_type, [
    $dependency_id,
  ]);
  $key = 'dependencies.' . $dependency_type;
  $key2 = 'dependencies.enforced.' . $dependency_type;
  foreach (array_keys($dependents) as $name) {
    $config = \Drupal::configFactory()
      ->getEditable($name);
    $dependencies = $config
      ->get($key);
    if (is_array($dependencies)) {
      $config
        ->set($key, array_map($map, $dependencies));
    }
    $dependencies2 = $config
      ->get($key2);
    if (is_array($dependencies2)) {
      $config
        ->set($key2, array_map($map, $dependencies2));
    }
    $config
      ->save();
  }
}

/**
 * Issue #3151898: Remove [Slick Media] module dependencies.
 *
 * From [Varbase Media] module and replace it with the main module Slick
 *  and uninstall.
 */
function varbase_media_update_8708() {

  // Move all module dependencies on existing config entities from
  // "slick_media" to "slick".
  _varbase_media_slick_media_fix_dependencies('module', 'slick_media', function ($module) {
    return $module === 'slick_media' ? 'slick' : $module;
  });

  // Fix the update process to uninstall.
  $query = \Drupal::database()
    ->delete('key_value')
    ->condition('collection', 'system.schema')
    ->condition('name', 'slick_media')
    ->execute();
  if (isset($query)) {

    // Entity updates to clear up any mismatched entity and/or field definitions
    // And Fix changes were detected in the entity type and field definitions.
    \Drupal::classResolver()
      ->getInstanceFromDefinition(VarbaseEntityDefinitionUpdateManager::class)
      ->applyUpdates();
  }
}

/**
 * Issue #3171237: Fix deprecated function getCurrentUserId.
 *
 * Replaced by getDefaultEntityOwner in all
 *  core.base_field_override.media.MEDIA_TYPES.uid
 */
function varbase_media_update_8709() {
  $config_factory = \Drupal::service('config.factory');
  $media_uid_configs = $config_factory
    ->listAll('core.base_field_override.media.');
  foreach ($media_uid_configs as $media_uid_config) {
    if (substr($media_uid_config, -4) === ".uid") {
      $media_uid_config_factory = $config_factory
        ->getEditable($media_uid_config);
      $default_value_callback = $media_uid_config_factory
        ->get('default_value_callback');
      if (isset($default_value_callback) && !empty($default_value_callback) && $default_value_callback === 'Drupal\\media\\Entity\\Media::getCurrentUserId') {
        $media_uid_config_factory
          ->set('default_value_callback', 'Drupal\\media\\Entity\\Media::getDefaultEntityOwner')
          ->save(TRUE);
      }
    }
  }
}

/**
 * Issue #3192175: Add WebP module ~1.0 and enable by default.
 */
function varbase_media_update_8710() {
  if (!\Drupal::moduleHandler()
    ->moduleExists('webp')) {
    \Drupal::service('module_installer')
      ->install([
      'webp',
    ], FALSE);
  }
}

Functions

Namesort descending Description
varbase_media_install Implements hook_install().
varbase_media_requirements Implements hook_requirements().
varbase_media_update_8701 Issue #3098789: Fix [Media Library] and the [Media Grid and Media Table].
varbase_media_update_8702 Issue #3103229: Fix icons for [Embed buttons] for the CKEditor.
varbase_media_update_8703 Follow up fix Issue #3103229: Fix icons for [Embed buttons] for the CKEditor.
varbase_media_update_8704 Issue #3115391: Create new field field_provider for remote video media type.
varbase_media_update_8705 Follow up #3115391: Update all remote videos, set field_provider value.
varbase_media_update_8706 Follow up #3115391: Update all remote videos, set oembed view mode type.
varbase_media_update_8707 Issue #3125946: Fix missing varbase media entity presave hook.
varbase_media_update_8708 Issue #3151898: Remove [Slick Media] module dependencies.
varbase_media_update_8709 Issue #3171237: Fix deprecated function getCurrentUserId.
varbase_media_update_8710 Issue #3192175: Add WebP module ~1.0 and enable by default.
_varbase_media_managed_media_library_configs Managed Varbase Media Library configurations.
_varbase_media_slick_media_fix_dependencies Helper function to rename slick_media config dependencies to slick.