diff --git a/core/modules/file/css/file.formatter.generic.css b/core/modules/file/css/file.formatter.generic.css new file mode 100644 index 0000000..73498e3 --- /dev/null +++ b/core/modules/file/css/file.formatter.generic.css @@ -0,0 +1,64 @@ +/** + * @file + * Default style for file module + */ + +/** + * File icons + */ +.file { + padding-left: 20px; /* LTR */ + display: inline-block; + min-height: 16px; + background-repeat: no-repeat; + background-position: left center; /* LTR */ +} + +[dir="rtl"] .file { + padding-left: inherit; + padding-right: 20px; + background-position: right center; +} + +.file.package-x-generic { + background-image: url(../icons/package-x-generic.png); +} +.file.office-spreadsheet { + background-image: url(../icons/x-office-spreadsheet.png); +} +.file.office-document { + background-image: url(../icons/x-office-document.png); +} +.file.office-presentation { + background-image: url(../icons/x-office-presentation.png); +} +.file.text-x-script { + background-image: url(../icons/text-x-script.png); +} +.file.text-html { + background-image: url(../icons/text-html.png); +} +.file.text-plain { + background-image: url(../icons/text-plain.png); +} +.file.application-pdf { + background-image: url(../icons/application-pdf.png); +} +.file.application-octet-stream { + background-image: url(../icons/application-octet-stream.png); +} +.file.application-x-executable { + background-image: url(../icons/application-x-executable.png); +} +.file.audio { + background-image: url(../icons/audio-x-generic.png); +} +.file.video { + background-image: url(../icons/video-x-generic.png); +} +.file.text { + background-image: url(../icons/text-x-generic.png); +} +.file.image { + background-image: url(../icons/image-x-generic.png); +} diff --git a/core/modules/file/file.libraries.yml b/core/modules/file/file.libraries.yml index ccc0c3b..4652958 100644 --- a/core/modules/file/file.libraries.yml +++ b/core/modules/file/file.libraries.yml @@ -5,8 +5,16 @@ drupal.file: css: theme: css/file.admin.css: {} + component: + css/file.formatter.generic.css: {} dependencies: - core/jquery - core/jquery.once - core/drupal - core/drupalSettings + +drupal.file.formatter.generic: + version: VERSION + css: + theme: + css/file.formatter.generic.css: {} diff --git a/core/modules/file/file.module b/core/modules/file/file.module index e17ab46..3bcd9af 100644 --- a/core/modules/file/file.module +++ b/core/modules/file/file.module @@ -576,7 +576,7 @@ function file_theme() { return array( // From file.module. 'file_link' => array( - 'variables' => array('file' => NULL, 'icon_directory' => NULL, 'description' => NULL, 'attributes' => array()), + 'variables' => array('file' => NULL, 'description' => NULL, 'attributes' => array()), 'template' => 'file-link', ), 'file_managed_file' => array( @@ -1542,43 +1542,15 @@ function file_managed_file_pre_render($element) { */ function template_preprocess_file_link(&$variables) { $file = $variables['file']; - $options = array( - 'attributes' => $variables['attributes'], - ); - $icon_directory = $variables['icon_directory']; + $options = array(); - $url = file_create_url($file->getFileUri()); $file_entity = ($file instanceof File) ? $file : file_load($file->fid); + $url = file_create_url($file_entity->getFileUri()); - // Human-readable names, for use as text-alternatives to icons. - $mime_name = array( - 'application/msword' => t('Microsoft Office document icon'), - 'application/vnd.ms-excel' => t('Office spreadsheet icon'), - 'application/vnd.ms-powerpoint' => t('Office presentation icon'), - 'application/pdf' => t('PDF icon'), - 'video/quicktime' => t('Movie icon'), - 'audio/mpeg' => t('Audio icon'), - 'audio/wav' => t('Audio icon'), - 'image/jpeg' => t('Image icon'), - 'image/png' => t('Image icon'), - 'image/gif' => t('Image icon'), - 'application/zip' => t('Package icon'), - 'text/html' => t('HTML icon'), - 'text/plain' => t('Plain text icon'), - 'application/octet-stream' => t('Binary Data'), - ); - - $variables['icon'] = array( - '#theme' => 'image__file_icon', - '#uri' => file_icon_url($file_entity, $icon_directory), - '#alt' => (!empty($mime_name[$file->getMimeType()])) ? $mime_name[$file->getMimeType()] : t('File'), - '#title' => String::checkPlain($file_entity->getFilename()), - '#attributes' => array('class' => array('file-icon')), - ); - + $mime_type = $file->getMimeType(); // Set options as per anchor format described at // http://microformats.org/wiki/file-format-examples - $options['attributes']['type'] = $file->getMimeType() . '; length=' . $file->getSize(); + $options['attributes']['type'] = $mime_type . '; length=' . $file->getSize(); // Use the description as the link text if available. if (empty($variables['description'])) { @@ -1589,93 +1561,58 @@ function template_preprocess_file_link(&$variables) { $options['attributes']['title'] = String::checkPlain($file_entity->getFilename()); } - $variables['link'] = l($link_text, $url, $options); - $variables['attributes'] = array('class' => array('file')); -} + // Classes to add to the file field for icons. + $classes = array( + 'file', + strtr($mime_type, array('/' => '-')), + file_icon_class($mime_type), + ); -/** - * Creates a URL to the icon for a file entity. - * - * @param \Drupal\file\FileInterface $file - * A file entity. - * @param $icon_directory - * (optional) A path to a directory of icons to be used for files. Defaults to - * the value of the "icon.directory" variable. - * - * @return - * A URL string to the icon, or FALSE if an appropriate icon cannot be found. - */ -function file_icon_url(FileInterface $file, $icon_directory = NULL) { - if ($icon_path = file_icon_path($file, $icon_directory)) { - return base_path() . $icon_path; - } - return FALSE; + // Set file classes to the options array. + $variables['attributes'] = new Attribute($variables['attributes']); + $variables['attributes']->addClass($classes); + + $variables['link'] = l($link_text, $url, $options); } /** - * Creates a path to the icon for a file entity. + * Gets a class for the icon for a MIME type. * - * @param \Drupal\file\FileInterface $file - * A file entity. - * @param $icon_directory - * (optional) A path to a directory of icons to be used for files. Defaults to - * the value of the "icon.directory" variable. + * @param string $mime_type + * A MIME type. * - * @return - * A string to the icon as a local path, or FALSE if an appropriate icon could - * not be found. + * @return string + * A class associated to the file. */ -function file_icon_path(FileInterface $file, $icon_directory = NULL) { - // Use the default set of icons if none specified. - if (!isset($icon_directory)) { - $icon_directory = \Drupal::config('file.settings')->get('icon.directory'); - } - - // If there's an icon matching the exact mimetype, go for it. - $dashed_mime = strtr($file->getMimeType(), array('/' => '-')); - $icon_path = $icon_directory . '/' . $dashed_mime . '.png'; - if (file_exists($icon_path)) { - return $icon_path; - } - - // For a few mimetypes, we can "manually" map to a generic icon. - $generic_mime = (string) file_icon_map($file); - $icon_path = $icon_directory . '/' . $generic_mime . '.png'; - if ($generic_mime && file_exists($icon_path)) { - return $icon_path; +function file_icon_class($mime_type) { + // Search for a group with the files MIME type. + $generic_mime = (string) file_icon_map($mime_type); + if (!empty($generic_mime)) { + return $generic_mime; } // Use generic icons for each category that provides such icons. foreach (array('audio', 'image', 'text', 'video') as $category) { - if (strpos($file->getMimeType(), $category . '/') === 0) { - $icon_path = $icon_directory . '/' . $category . '-x-generic.png'; - if (file_exists($icon_path)) { - return $icon_path; - } + if (strpos($mime_type, $category) === 0) { + return $category; } } - // Try application-octet-stream as last fallback. - $icon_path = $icon_directory . '/application-octet-stream.png'; - if (file_exists($icon_path)) { - return $icon_path; - } - - // No icon can be found. - return FALSE; + // If there's no generic icon for the type the general class. + return 'file-general'; } /** * Determines the generic icon MIME package based on a file's MIME type. * - * @param \Drupal\file\FileInterface $file - * A file entity. + * @param string $mime_type + * A MIME type. * * @return * The generic icon MIME package expected for this file. */ -function file_icon_map(FileInterface $file) { - switch ($file->getMimeType()) { +function file_icon_map($mime_type) { + switch ($mime_type) { // Word document types. case 'application/msword': case 'application/vnd.ms-word.document.macroEnabled.12': @@ -1693,7 +1630,7 @@ function file_icon_map(FileInterface $file) { case 'application/x-applix-word': case 'application/x-kword': case 'application/x-kword-crypt': - return 'x-office-document'; + return 'office-document'; // Spreadsheet document types. case 'application/vnd.ms-excel': @@ -1709,7 +1646,7 @@ function file_icon_map(FileInterface $file) { case 'application/x-gnumeric': case 'application/x-kspread': case 'application/x-kspread-crypt': - return 'x-office-spreadsheet'; + return 'office-spreadsheet'; // Presentation document types. case 'application/vnd.ms-powerpoint': @@ -1721,7 +1658,7 @@ function file_icon_map(FileInterface $file) { case 'application/vnd.sun.xml.impress': case 'application/vnd.sun.xml.impress.template': case 'application/x-kpresenter': - return 'x-office-presentation'; + return 'office-presentation'; // Compressed archive types. case 'application/zip': diff --git a/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php b/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php index 5d137e0..e37633b 100644 --- a/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php +++ b/core/modules/file/src/Plugin/Field/FieldFormatter/GenericFileFormatter.php @@ -46,6 +46,12 @@ public function viewElements(FieldItemListInterface $items) { } } + if (!empty($elements)) { + $elements['#attached'] = array( + 'library' => array('file/drupal.file.formatter.generic'), + ); + } + return $elements; } diff --git a/core/modules/file/templates/file-link.html.twig b/core/modules/file/templates/file-link.html.twig index fbbf08b..44cbd7f 100644 --- a/core/modules/file/templates/file-link.html.twig +++ b/core/modules/file/templates/file-link.html.twig @@ -6,11 +6,10 @@ * Available variables: * - attributes: The HTML attributes for the containing element. * - link: A link to the file. - * - icon: The icon image representing the file type. * * @see template_preprocess_file_link() * * @ingroup themeable */ #} -{{ icon }} {{ link }} +{{ link }} diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index be1d027..9dc7d5a 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -359,7 +359,7 @@ function shortcut_preprocess_page(&$variables) { else { $query['id'] = $shortcut_id; $link_text = shortcut_set_switch_access() ? t('Remove from %shortcut_set shortcuts', array('%shortcut_set' => $shortcut_set->label())) : t('Remove from shortcuts'); - $route_name = 'entity.shortcut.delete_form'; + $route_name = 'entity.shortcut.link_delete_inline'; $route_parameters = array('shortcut' => $shortcut_id); } diff --git a/core/modules/shortcut/shortcut.routing.yml b/core/modules/shortcut/shortcut.routing.yml index 90752cd..6a892bd 100644 --- a/core/modules/shortcut/shortcut.routing.yml +++ b/core/modules/shortcut/shortcut.routing.yml @@ -62,6 +62,14 @@ entity.shortcut.canonical: requirements: _entity_access: 'shortcut.update' +entity.shortcut.link_delete_inline: + path: '/admin/config/user-interface/shortcut/link/{shortcut}/delete-inline' + defaults: + _controller: 'Drupal\shortcut\Controller\ShortcutController::deleteShortcutLinkInline' + requirements: + _entity_access: 'shortcut.delete' + _csrf_token: 'TRUE' + entity.shortcut.delete_form: path: '/admin/config/user-interface/shortcut/link/{shortcut}/delete' defaults: diff --git a/core/modules/shortcut/src/Controller/ShortcutController.php b/core/modules/shortcut/src/Controller/ShortcutController.php index 943caa0..85371de 100644 --- a/core/modules/shortcut/src/Controller/ShortcutController.php +++ b/core/modules/shortcut/src/Controller/ShortcutController.php @@ -9,6 +9,8 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\shortcut\ShortcutSetInterface; +use Drupal\shortcut\ShortcutInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides route responses for taxonomy.module. @@ -30,4 +32,28 @@ public function addForm(ShortcutSetInterface $shortcut_set) { return $this->entityFormBuilder()->getForm($shortcut, 'add'); } + /** + * Deletes the selected shortcut. + * + * @param \Drupal\shortcut\ShortcutInterface $shortcut + * The shortcut to delete. + * + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect to the previous location or the front page when destination + * is not set. + */ + public function deleteShortcutLinkInline(ShortcutInterface $shortcut) { + $label = $shortcut->label(); + + try { + $shortcut->delete(); + drupal_set_message($this->t('The shortcut %title has been deleted.', array('%title' => $label))); + } + catch (\Exception $e) { + drupal_set_message($this->t('Unable to delete the shortcut for %title.', array('%title' => $label))); + } + + return $this->redirect(''); + } + } diff --git a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php index 85c7253..2b4c731 100644 --- a/core/modules/shortcut/src/Tests/ShortcutLinksTest.php +++ b/core/modules/shortcut/src/Tests/ShortcutLinksTest.php @@ -118,7 +118,6 @@ public function testShortcutQuickLink() { // Test the "Remove from shortcuts" link. $this->clickLink('Cron'); $this->clickLink('Remove from Default shortcuts'); - $this->drupalPostForm(NULL, array(), 'Delete'); $this->assertText('The shortcut Cron has been deleted.'); $this->assertNoLink('Cron', 'Shortcut link removed from page');