library_manager-8.x-1.0/library_manager.module
library_manager.module
<?php /** * @file * Primary module hooks for Library manager module. */ use Drupal\Core\File\FileSystemInterface; use Drupal\Core\Plugin\ContextAwarePluginInterface; use Drupal\Component\Plugin\Exception\ContextException; use Drupal\file\Entity\File; /** * Implements hook_library_info_build(). */ function library_manager_library_info_build() { $libraries = library_manager_build_libraries()['libraries']; // Add Library manager library. $libraries['library_manager'] = []; $libraries['library_manager']['js']['js/library-manager.js'] = []; $libraries['library_manager']['dependencies'][] = 'core/jquery'; $libraries['library_manager']['dependencies'][] = 'core/once'; $libraries['library_manager']['dependencies'][] = 'core/drupal.debounce'; return $libraries; } /** * Implements hook_library_info_alter(). */ function library_manager_library_info_alter(&$libraries, $extension) { $overrides = library_manager_build_libraries()['overrides']; foreach ($libraries as $library => $library_info) { $library_id = $extension . '/' . $library; if (isset($overrides[$library_id])) { $libraries[$library] = $overrides[$library_id]; } } } /** * Saves library file to a given location. * * @return bool * TRUE if the was successfully created and is writable or FALSE on error. */ function library_manager_save_file($file_path, $data) { $file_system = \Drupal::service('file_system'); $directory = $file_system->dirname($file_path); if (\Drupal::service('file_system')->prepareDirectory($directory, FileSystemInterface::CREATE_DIRECTORY)) { if (\Drupal::service('file_system')->saveData($data, $file_path, FileSystemInterface::EXISTS_REPLACE)) { return TRUE; } } $message = t('Could not create file %file', ['%file' => $file_path]); \Drupal::messenger()->addError($message); \Drupal::logger('library_manager')->error($message); return FALSE; } /** * Build libraries form corresponding definitions. */ function library_manager_build_libraries() { global $base_path; if (!$data = &drupal_static(__FUNCTION__)) { $data = [ 'libraries' => [], 'overrides' => [], ]; $libraries_path = \Drupal::config('library_manager.settings')->get('libraries_path'); /** @var Drupal\library_manager\LibraryDefinitionInterface[] $definitions */ $definitions = \Drupal::service('entity_type.manager') ->getStorage('library_definition') ->loadByProperties(['status' => TRUE]); foreach ($definitions as $definition) { $library_path = $libraries_path . '/' . $definition->id(); if (file_exists($library_path)) { // The files can be removed in other thread when tests are running. try { @\Drupal::service('file_system')->deleteRecursive($library_path); } catch (\Exception $e) { // There was a transient error. } } $library_info = []; $library_info['remote'] = $definition->get('remote'); $library_info['version'] = $definition->get('version'); $library_info['license'] = $definition->get('license'); $library_info['definition'] = $definition->id(); // Process JS. $library_info['js'] = []; foreach ($definition->get('js') as $file) { $options = [ 'minified' => $file['minified'], 'preprocess' => $file['preprocess'], ]; // Weight is optional property for JS files. if (isset($file['weight'])) { $options['weight'] = $file['weight']; } // Set header. $library_info['header'] = isset($file['header']) && !empty($file['header']) ? TRUE : FALSE; // Add custom attributes if they exist. if (isset($file['attributes']) && is_array($file['attributes'])) { foreach ($file['attributes'] as $attribute_name => $attribute_value) { $options['attributes'][$attribute_name] = $attribute_value; } } // Set the nomodule attribute to TRUE if it is set. if (!empty($options['attributes']['nomodule'])) { $options['attributes']['nomodule'] = TRUE; } if ($file['external']) { $options['type'] = 'external'; $library_info['js'][$file['url']] = $options; } elseif (isset($file['code_type']) && $file['code_type'] == 'file_upload') { if (!empty($file['file_upload'])) { $uploaded_file_id = $file['file_upload']; /** @var \Drupal\file\Entity\File $uploaded_file */ $uploaded_file = File::load($uploaded_file_id); if (!empty($uploaded_file)) { $uploaded_file_uri = $uploaded_file->getFileUri(); $uploaded_file_path = \Drupal::service('file_url_generator')->generateString($uploaded_file_uri); $uploaded_file_path = '/' . substr($uploaded_file_path, strlen($base_path)); $library_info['js'][$uploaded_file_path] = $options; } } } else { $file_path = $libraries_path . '/' . $definition->id() . '/' . $file['file_name']; $library_info['js']['/' . $file_path] = $options; library_manager_save_file($file_path, $file['code']); } } // Process CSS. $library_info['css'] = []; foreach ($definition->get('css') as $file) { $options = [ 'minified' => $file['minified'], 'preprocess' => $file['preprocess'], 'weight' => $file['weight'], ]; if ($file['external']) { $options['type'] = 'external'; $library_info['css'][$file['group']][$file['url']] = $options; } elseif (isset($file['code_type']) && $file['code_type'] == 'file_upload') { if (!empty($file['file_upload'])) { $uploaded_file_id = $file['file_upload']; /** @var \Drupal\file\Entity\File $uploaded_file */ $uploaded_file = File::load($uploaded_file_id); if (!empty($uploaded_file)) { $uploaded_file_uri = $uploaded_file->getFileUri(); $uploaded_file_path = \Drupal::service('file_url_generator')->generateString($uploaded_file_uri); $uploaded_file_path = '/' . substr($uploaded_file_path, strlen($base_path)); $library_info['css'][$file['group']][$uploaded_file_path] = $options; } } } else { $file_path = $libraries_path . '/' . $definition->id() . '/' . $file['file_name']; $library_info['css'][$file['group']]['/' . $file_path] = $options; library_manager_save_file($file_path, $file['code']); } } // Process dependencies. $library_info['dependencies'] = []; foreach ($definition->get('library_dependencies') as $dependency) { $library_info['dependencies'][] = $dependency; } if ($target = $definition->get('target')) { if ($definition->get('override_by_visibility')) { $data['libraries'][$definition->id()] = $library_info; } else { $data['overrides'][$target] = $library_info; } } else { $data['libraries'][$definition->id()] = $library_info; } } } return $data; } /** * Implements hook_page_attachments(). */ function library_manager_page_attachments(array &$attachments) { /** @var Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage */ $storage = \Drupal::service('entity_type.manager')->getStorage('library_definition'); $library_definition_new_query = Drupal::entityQuery('library_definition') ->condition('status', TRUE) ->condition('target', NULL, 'IS NULL') ->condition('load', TRUE) ->accessCheck(FALSE) ->execute(); $library_definitions_new = $storage->loadMultiple($library_definition_new_query); $library_definitions_override_by_visibility_query = Drupal::entityQuery('library_definition') ->condition('status', TRUE) ->condition('target', NULL, 'IS NOT NULL') ->condition('override_by_visibility', TRUE) ->accessCheck(FALSE) ->execute(); $library_definitions_override_by_visibility = $storage->loadMultiple($library_definitions_override_by_visibility_query); /** @var Drupal\library_manager\LibraryDefinitionInterface[] $definitions */ $definitions = $library_definitions_new + $library_definitions_override_by_visibility; $context_repository = \Drupal::service('context.repository'); $context_handler = \Drupal::service('context.handler'); foreach ($definitions as $definition) { foreach ($definition->getVisibilityConditions() as $condition) { $attach = TRUE; $missing_context = FALSE; if ($condition instanceof ContextAwarePluginInterface) { try { $contexts = $context_repository->getRuntimeContexts(array_values($condition->getContextMapping())); $context_handler->applyContextMapping($condition, $contexts); } catch (ContextException $exception) { $missing_context = TRUE; } } if ($missing_context || !$condition->execute()) { $attach = FALSE; break; } } if ($attach) { $attachments['#attached']['library'][] = 'library_manager/' . $definition->id(); } } } /** * Implements hook_page_attachments_alter(). */ function library_manager_page_attachments_alter(array &$attachments) { /** @var Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage */ $storage = \Drupal::service('entity_type.manager')->getStorage('library_definition'); /** @var Drupal\library_manager\LibraryDefinitionInterface[] $definitions */ $definitions = $storage->loadByProperties(['status' => TRUE, 'override_by_visibility' => TRUE]); $context_repository = \Drupal::service('context.repository'); $context_handler = \Drupal::service('context.handler'); foreach ($definitions as $definition) { if ($target = $definition->get('target')) { foreach ($definition->getVisibilityConditions() as $condition) { $attach = TRUE; $missing_context = FALSE; if ($condition instanceof ContextAwarePluginInterface) { try { $contexts = $context_repository->getRuntimeContexts(array_values($condition->getContextMapping())); $context_handler->applyContextMapping($condition, $contexts); } catch (ContextException $exception) { $missing_context = TRUE; } } if ($missing_context || !$condition->execute()) { $attach = FALSE; break; } } if ($attach) { // Remove the library if it exists in the attachments. if (isset($attachments['#attached']['library']) && ($key = array_search($target, $attachments['#attached']['library'])) !== FALSE) { unset($attachments['#attached']['library'][$key]); } } } } } /** * Implements hook_codemirror_editor_assets_alter(). */ function library_manager_codemirror_editor_assets_alter(array &$assets) { $assets['js'][] = 'mode/javascript/javascript.min.js'; $assets['js'][] = 'mode/css/css.min.js'; $assets['js'][] = 'mode/yaml/yaml.min.js'; } /** * Implements hook_css_alter(). */ function library_manager_css_alter(array &$css, \Drupal\Core\Asset\AttachedAssetsInterface $assets) { $libraries = $assets->getLibraries(); foreach (library_manager_library_info_build() as $lib_id => $library) { if (in_array("library_manager/$lib_id", $libraries) && !empty($library['css'])) { foreach ($library['css'] as $group_key => $group) { foreach (array_keys($group) as $file) { $key = trim($file, '/ '); if (array_key_exists($key, $css)) { // Detailed Reference: \Drupal\Core\Asset\LibraryDiscoveryParser. $css[$key]['group'] = $group_key == 'theme' ? CSS_AGGREGATE_THEME : CSS_AGGREGATE_DEFAULT; } } } } } }