diff --git a/core/modules/navigation/config/install/navigation.settings.yml b/core/modules/navigation/config/install/navigation.settings.yml index ffa4ff79c88d111c47443bc2d9866f7f551f57ea..4dd462c26f856fe00e5b8ea4798ae5c2cb98616f 100644 --- a/core/modules/navigation/config/install/navigation.settings.yml +++ b/core/modules/navigation/config/install/navigation.settings.yml @@ -1,6 +1,6 @@ logo: provider: default - managed: null + path: '' max: filesize: 1048576 height: 40 diff --git a/core/modules/navigation/config/schema/navigation.schema.yml b/core/modules/navigation/config/schema/navigation.schema.yml index 0d898740431d2c8c3773b7ecffdc24da068ac391..fabf40b964f107f4808502508da4f218ef9aea03 100644 --- a/core/modules/navigation/config/schema/navigation.schema.yml +++ b/core/modules/navigation/config/schema/navigation.schema.yml @@ -18,13 +18,11 @@ navigation.settings: - default - hide - custom - managed: - type: integer - label: 'Custom logo' - nullable: true + path: + type: string + label: 'Path' constraints: - Range: - min: 0 + NotNull: [ ] max: type: mapping label: 'Logo maximum settings' diff --git a/core/modules/navigation/navigation.install b/core/modules/navigation/navigation.install index 4b39baad172aa5990ad9380aa58e56d27d94065d..72b843b23a2860f6cd0114215eb20570ee793c72 100644 --- a/core/modules/navigation/navigation.install +++ b/core/modules/navigation/navigation.install @@ -32,13 +32,34 @@ function navigation_update_11001(array &$sandbox): void { $settings->setData([ 'logo' => [ 'provider' => $settings->get('logo_provider'), - 'managed' => $settings->get('logo_managed'), + 'managed' => is_array($settings->get('logo_managed')) ? current($settings->get('logo_managed')) : $settings->get('logo_managed'), 'max' => [ 'filesize' => $settings->get('logo_max_filesize'), - 'height' => $settings->get('logo_height'), - 'width' => $settings->get('logo_width'), + 'height' => $settings->get('logo_height') ?? 40, + 'width' => $settings->get('logo_width') ?? 40, ], ], ]); $settings->save(TRUE); } + +/** + * Update for navigation logo to store the file path instead of ID. + */ +function navigation_update_11002(array &$sandbox): void { + $settings = \Drupal::configFactory()->getEditable('navigation.settings'); + $logo_path = ''; + if (!empty($settings->get('logo.managed'))) { + $logo_fid = $settings->get('logo.managed'); + $file = \Drupal::entityTypeManager()->getStorage('file')->load($logo_fid); + if (isset($file)) { + $logo_path = $file->getFileUri(); + // Delete file usage reference because they are not being used anymore. + \Drupal::service('file.usage')->delete($file, 'navigation'); + } + } + + $settings->set('logo.path', $logo_path); + $settings->clear('logo.managed'); + $settings->save(); +} diff --git a/core/modules/navigation/navigation.post_update.php b/core/modules/navigation/navigation.post_update.php index 90e63c6afb2e8089f98c09c3c928fbbff0b6827a..5c3a0dbf650af98c313ae788381976c5cd11a190 100644 --- a/core/modules/navigation/navigation.post_update.php +++ b/core/modules/navigation/navigation.post_update.php @@ -31,11 +31,5 @@ function navigation_post_update_update_permissions(array &$sandbox) { * Defines the values for the default logo dimensions. */ function navigation_post_update_set_logo_dimensions_default(array &$sandbox) { - $settings = \Drupal::configFactory()->getEditable('navigation.settings'); - $settings->set('logo_height', 40) - ->set('logo_width', 40); - if (is_array($settings->get('logo_managed'))) { - $settings->set('logo_managed', current($settings->get('logo_managed'))); - } - $settings->save(); + // Empty post_update hook. } diff --git a/core/modules/navigation/src/Form/SettingsForm.php b/core/modules/navigation/src/Form/SettingsForm.php index 4f0cda9273aabd0e3b5675a880a9a75c19fe7bfe..7d8ec3c1d21788f2718ec50a454b5570d571725d 100644 --- a/core/modules/navigation/src/Form/SettingsForm.php +++ b/core/modules/navigation/src/Form/SettingsForm.php @@ -7,15 +7,16 @@ use Drupal\Component\Utility\Environment; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\TypedConfigManagerInterface; -use Drupal\Core\Entity\EntityTypeManagerInterface; +use Drupal\Core\File\Exception\FileException; use Drupal\Core\File\FileSystemInterface; -use Drupal\Core\File\FileUrlGeneratorInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Image\ImageFactory; use Drupal\Core\Render\RendererInterface; +use Drupal\Core\StreamWrapper\PublicStream; +use Drupal\Core\StreamWrapper\StreamWrapperManager; +use Drupal\Core\Theme\ThemeManagerInterface; use Drupal\file\Entity\File; -use Drupal\file\FileUsage\FileUsageInterface; use Drupal\navigation\NavigationRenderer; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -35,26 +36,20 @@ final class SettingsForm extends ConfigFormBase { * The typed config manager. * @param \Drupal\Core\File\FileSystemInterface $fileSystem * The file system. - * @param \Drupal\Core\File\FileUrlGeneratorInterface $fileUrlGenerator - * The file URL generator. - * @param \Drupal\file\FileUsage\FileUsageInterface $fileUsage - * The File Usage service. * @param \Drupal\Core\Render\RendererInterface $renderer * The renderer service. - * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager - * The entity type manager. * @param \Drupal\Core\Image\ImageFactory $imageFactory * The image factory. + * @param \Drupal\Core\Theme\ThemeManagerInterface $themeManager + * The theme manager. */ public function __construct( ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config_manager, protected FileSystemInterface $fileSystem, - protected FileUrlGeneratorInterface $fileUrlGenerator, - protected FileUsageInterface $fileUsage, protected RendererInterface $renderer, - protected EntityTypeManagerInterface $entityTypeManager, protected ImageFactory $imageFactory, + protected ThemeManagerInterface $themeManager, ) { parent::__construct($config_factory, $typed_config_manager); } @@ -67,11 +62,9 @@ public static function create(ContainerInterface $container) { $container->get('config.factory'), $container->get('config.typed'), $container->get('file_system'), - $container->get('file_url_generator'), - $container->get('file.usage'), $container->get('renderer'), - $container->get('entity_type.manager'), - $container->get('image.factory') + $container->get('image.factory'), + $container->get('theme.manager') ); } @@ -110,7 +103,8 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ], '#config_target' => 'navigation.settings:logo.provider', ]; - $form['logo']['image'] = [ + + $form['logo']['custom'] = [ '#type' => 'container', '#states' => [ 'visible' => [ @@ -118,8 +112,34 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ], ], ]; + + // If path is a public:// URI, display the path relative to the files + // directory; stream wrappers are not end-user friendly. + $original_path = $config->get('logo.path') ?? ''; + $friendly_path = NULL; + $default_path = $original_path; + $default = 'logo.png'; + + if (StreamWrapperManager::getScheme($original_path) === 'public') { + $friendly_path = StreamWrapperManager::getTarget($original_path); + $default_path = $friendly_path; + } + + // Prepare local file path for description. + if ($original_path && isset($friendly_path)) { + $local_file = strtr($original_path, ['public:/' => PublicStream::basePath()]); + } + else { + $local_file = $this->themeManager->getActiveTheme()->getPath() . '/' . $default; + } + + $description = $this->t('Examples: <code>@implicit-public-file</code> (for a file in the public filesystem), <code>@explicit-file</code>, or <code>@local-file</code>.', [ + '@implicit-public-file' => $friendly_path ?? $default, + '@explicit-file' => StreamWrapperManager::getScheme($original_path) !== FALSE ? $original_path : 'public://' . $default, + '@local-file' => $local_file, + ]); + $allowed = 'png jpg jpeg'; - $current_logo_managed_fid = $config->get('logo.managed') ? [$config->get('logo.managed')] : NULL; $max_navigation_allowed = $config->get('logo.max.filesize'); $max_system_allowed = Environment::getUploadMaxSize(); $max_allowed = $max_navigation_allowed < $max_system_allowed ? $max_navigation_allowed : $max_system_allowed; @@ -129,19 +149,27 @@ public function buildForm(array $form, FormStateInterface $form_state): array { ]; $file_upload_help = [ '#theme' => 'file_upload_help', - '#description' => $this->t('Recommended image dimension 40 x 40 pixels.'), + '#description' => $this->t("If you don't have direct file access to the server, use this field to upload your logo. Recommended image dimension %width x %height pixels.", [ + '%width' => $config->get('logo.max.width'), + '%height' => $config->get('logo.max.height'), + ]), '#upload_validators' => $upload_validators, '#cardinality' => 1, ]; - $form['logo']['image']['logo_managed'] = [ - '#type' => 'managed_file', - '#title' => t('Choose custom logo'), - '#upload_validators' => $upload_validators, - '#upload_location' => 'public://navigation-logo', + $form['logo']['custom']['logo_path'] = [ + '#type' => 'textfield', + '#title' => $this->t('Path to custom logo'), + '#default_value' => $default_path, + '#description' => $description, + '#config_target' => 'navigation.settings:logo.path', + ]; + $form['logo']['custom']['logo_upload'] = [ + '#type' => 'file', + '#title' => $this->t('Upload logo image'), '#description' => $this->renderer->renderInIsolation($file_upload_help), - '#default_value' => $current_logo_managed_fid, - '#multiple' => FALSE, + '#upload_validators' => $upload_validators, ]; + return parent::buildForm($form, $form_state); } @@ -149,90 +177,83 @@ public function buildForm(array $form, FormStateInterface $form_state): array { * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state): void { - $logo_managed = $form_state->getValue('logo_managed'); - if ($form_state->getValue('logo_provider') === NavigationRenderer::LOGO_PROVIDER_CUSTOM && empty($logo_managed)) { - $form_state->setErrorByName('logo_managed', 'An image file is required with the current logo handling option.'); + // If the upload element is not empty, try to adjust the image dimensions + // if needed. + if ($form_state->getValue('logo_path')) { + $path = $this->validateLogoPath($form_state->getValue('logo_path')); + if (!$path) { + $form_state->setErrorByName('logo_path', $this->t('The custom logo path is invalid.')); + } + } + + if ($form_state->getValue('logo_provider') !== NavigationRenderer::LOGO_PROVIDER_CUSTOM) { + $form_state->setValue('logo_upload', ''); + $form_state->setValue('logo_path', ''); } + else { + $file = _file_save_upload_from_form($form['logo']['custom']['logo_upload'], $form_state, 0); + if ($file) { + $logo_dimensions = $this->adjustLogoDimensions($file); + if (!$logo_dimensions) { + $config = $this->config('navigation.settings'); + $width = $config->get('logo.width'); + $height = $config->get('logo.height'); + $form_state->setErrorByName('logo_upload', $this->t('Image dimensions are bigger than the expected %widthx%height pixels and cannot be used as the navigation logo.', + [ + '%width' => $width, + '%height' => $height, + ])); + } + // Put the temporary file in form_values so we can save it on submit. + $form_state->setValue('logo_upload', $file); + $form_state->setValue('logo_path', $file->getFileUri()); + $form_state->setValue('logo_dimensions', $logo_dimensions); + } - // If the upload element is not empty and the image is new, try to adjust - // the image dimensions. - $this->validateLogoManaged($form, $form_state); + if (empty($form_state->getValue('logo_path'))) { + $form_state->setErrorByName('logo_path', 'An image file is required with the current logo handling option.'); + } + } + parent::validateForm($form, $form_state); } /** * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { - $config = $this->config('navigation.settings'); - - // Get the previous config settings. - $previous_logo_provider = $config->get('logo.provider'); - $previous_logo_fid = $config->get('logo.managed'); + // If the user uploaded a new logo, save it to a permanent location + // and use it in place of the default navigation-provided file. + $default_scheme = $this->config('system.file')->get('default_scheme'); + $values = $form_state->getValues(); + try { + if (!empty($values['logo_upload'])) { + $filename = $this->fileSystem->copy($values['logo_upload']->getFileUri(), $default_scheme . '://'); + $values['logo_path'] = $filename; + if ($values['logo_dimensions']['resize']) { + $config = $this->config('navigation.settings'); + $this->messenger()->addStatus($this->t('The image was resized to fit within the navigation logo expected dimensions of %widthx%height pixels. The new dimensions of the resized image are %new_widthx%new_height pixels.', + [ + '%width' => $config->get('logo.max.width'), + '%height' => $config->get('logo.max.height'), + '%new_width' => $values['logo_dimensions']['width'], + '%new_height' => $values['logo_dimensions']['height'], + ])); + } - // Get new values from the form. - $new_logo_provider = $form_state->getValue('logo_provider'); - $logo = $form_state->getValue('logo_managed'); - $new_logo_fid = !empty($logo) ? reset($logo) : NULL; - - // Pre-load files if any for FileUsageInterface. - $previous_logo_managed = $previous_logo_fid ? File::load($previous_logo_fid) : NULL; - $new_logo_managed = $new_logo_fid ? File::load($new_logo_fid) : NULL; - - // Decrement if previous logo_provider was 'custom' and has changed to a - // different fid and there's a change in the logo fid. - if ($previous_logo_provider === NavigationRenderer::LOGO_PROVIDER_CUSTOM - && ($new_logo_provider !== NavigationRenderer::LOGO_PROVIDER_CUSTOM || $previous_logo_fid !== $new_logo_fid) - && $previous_logo_managed - ) { - $this->fileUsage->delete($previous_logo_managed, 'navigation', 'logo', 1); - } - - // Increment usage if different from the previous one. - if ($new_logo_managed && $new_logo_fid !== $previous_logo_fid) { - $new_logo_managed->setPermanent(); - $new_logo_managed->save(); - $this->fileUsage->add($new_logo_managed, 'navigation', 'logo', 1); + } } - - $config - ->set('logo.managed', $new_logo_fid) - ->save(); - parent::submitForm($form, $form_state); - } - - /** - * Validate the Logo Managed image element. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - protected function validateLogoManaged(array $form, FormStateInterface $form_state): void { - $logo_managed = $form_state->getValue('logo_managed'); - $config = $this->config('navigation.settings'); - if (empty($logo_managed)) { + catch (FileException) { + $this->messenger()->addError($this->t('The file %file could not be copied to the permanent destination. Contact the site administrator if the problem persists.', ['%file' => $values['logo_upload']->getFilename()])); return; } - $width = $config->get('logo.max.width'); - $height = $config->get('logo.max.height'); - - // Skip if the fid has not been modified. - $fid = reset($logo_managed); - if ($fid == $config->get('logo.managed')) { - return; + // If the user entered a path relative to the system files directory for + // the logo, store a public:// URI so the theme system can handle it. + if (!empty($values['logo_path'])) { + $form_state->setValue('logo_path', $this->validateLogoPath($values['logo_path'])); } - $file = $this->entityTypeManager->getStorage('file') - ->load($fid); - if ($fid && !$this->adjustLogoDimensions($file)) { - $form_state->setErrorByName('logo_managed', $this->t('Image dimensions are bigger than the expected %widthx%height pixels and cannot be used as the navigation logo.', - [ - '%width' => $width, - '%height' => $height, - ])); - } + parent::submitForm($form, $form_state); } /** @@ -241,36 +262,70 @@ protected function validateLogoManaged(array $form, FormStateInterface $form_sta * @param \Drupal\file\Entity\File $file * The file entity that contains the image. * - * @return bool - * TRUE if the logo image dimensions are properly adjusted. FALSE otherwise. + * @return array|null + * Array containing the logo dimensions properly adjusted. NULL if fails. */ - protected function adjustLogoDimensions(File $file): bool { + protected function adjustLogoDimensions(File $file): ?array { $config = $this->config('navigation.settings'); $image = $this->imageFactory->get($file->getFileUri()); if (!$image->isValid()) { - return FALSE; + return NULL; } $width = $config->get('logo.max.width'); $height = $config->get('logo.max.height'); if ($image->getWidth() <= $width && $image->getHeight() <= $height) { - return TRUE; + return [ + 'width' => $width, + 'height' => $width, + 'resize' => FALSE, + ]; } if ($image->scale($width, $height) && $image->save()) { - $this->messenger()->addStatus($this->t('The image was resized to fit within the navigation logo expected dimensions of %widthx%height pixels. The new dimensions of the resized image are %new_widthx%new_height pixels.', - [ - '%width' => $width, - '%height' => $height, - '%new_width' => $image->getWidth(), - '%new_height' => $image->getHeight(), - ])); - - return TRUE; + return [ + 'width' => $image->getWidth(), + 'height' => $image->getHeight(), + 'resize' => TRUE, + ]; } - return FALSE; + return NULL; + } + + /** + * Helper function for the navigation settings form. + * + * Attempts to validate normal system paths, paths relative to the public + * files directory, or stream wrapper URIs. If the given path is any of the + * above, returns a valid path or URI that the theme system can display. + * + * @param string $path + * A path relative to the Drupal root or to the public files directory, or + * a stream wrapper URI. + * + * @return string|null + * A valid path that can be displayed through the theme system, or NULL if + * the path could not be validated. + */ + protected function validateLogoPath(string $path): ?string { + // Absolute local file paths are invalid. + if ($this->fileSystem->realpath($path) == $path) { + return NULL; + } + // A path relative to the Drupal root or a fully qualified URI is valid. + if (is_file($path)) { + return $path; + } + // Prepend 'public://' for relative file paths within public filesystem. + if (StreamWrapperManager::getScheme($path) === FALSE) { + $path = 'public://' . $path; + } + if (is_file($path)) { + return $path; + } + return NULL; } } diff --git a/core/modules/navigation/src/NavigationRenderer.php b/core/modules/navigation/src/NavigationRenderer.php index 8613174787b52bb2a558ee8f812d848031632c33..4aa5bece02dec85f835464dd8cd7e0396cade1cc 100644 --- a/core/modules/navigation/src/NavigationRenderer.php +++ b/core/modules/navigation/src/NavigationRenderer.php @@ -18,8 +18,6 @@ use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; use Drupal\Core\Routing\RouteMatchInterface; -use Drupal\file\Entity\File; -use Drupal\file\FileInterface; use Drupal\layout_builder\SectionStorage\SectionStorageManagerInterface; use Symfony\Component\HttpFoundation\RequestStack; @@ -144,12 +142,11 @@ public function buildNavigation(array &$page_top): void { $page_top['navigation'] = $build; if ($logo_provider === self::LOGO_PROVIDER_CUSTOM) { - $logo_managed = File::load($logo_settings->get('logo.managed')); - if ($logo_managed instanceof FileInterface) { - $logo_managed_uri = $logo_managed->getFileUri(); - $logo_managed_url = $this->fileUrlGenerator->generateAbsoluteString($logo_managed_uri); + $logo_path = $logo_settings->get('logo.path'); + if (!empty($logo_path) && is_file($logo_path)) { + $logo_managed_url = $this->fileUrlGenerator->generateAbsoluteString($logo_path); + $image = $this->imageFactory->get($logo_path); $page_top['navigation'][0]['settings']['logo_path'] = $logo_managed_url; - $image = $this->imageFactory->get($logo_managed_uri); if ($image->isValid()) { $page_top['navigation'][0]['settings']['logo_width'] = $image->getWidth(); $page_top['navigation'][0]['settings']['logo_height'] = $image->getHeight(); diff --git a/core/modules/navigation/tests/assets/image_test_files/test-logo.png b/core/modules/navigation/tests/assets/image_test_files/test-logo.png deleted file mode 100644 index 853fde8e32e4af45036bc19826bf49674d56e3de..0000000000000000000000000000000000000000 --- a/core/modules/navigation/tests/assets/image_test_files/test-logo.png +++ /dev/null @@ -1,44 +0,0 @@ -‰PNG - -��� IHDR���(���(���Œþ¸m��µiTXtXML:com.adobe.xmp�����<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?> -<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 5.5.0"> - <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> - <rdf:Description rdf:about="" - xmlns:exif="http://ns.adobe.com/exif/1.0/" - xmlns:tiff="http://ns.adobe.com/tiff/1.0/" - xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/" - xmlns:xmp="http://ns.adobe.com/xap/1.0/" - xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/" - xmlns:stEvt="http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" - exif:PixelXDimension="40" - exif:PixelYDimension="40" - exif:ColorSpace="1" - tiff:ImageWidth="40" - tiff:ImageLength="40" - tiff:ResolutionUnit="2" - tiff:XResolution="72/1" - tiff:YResolution="72/1" - photoshop:ColorMode="3" - photoshop:ICCProfile="sRGB IEC61966-2.1" - xmp:ModifyDate="2024-05-27T13:36:14-04:00" - xmp:MetadataDate="2024-05-27T13:36:14-04:00"> - <xmpMM:History> - <rdf:Seq> - <rdf:li - stEvt:action="produced" - stEvt:softwareAgent="Affinity Publisher 2 2.4.2" - stEvt:when="2024-05-27T13:36:14-04:00"/> - </rdf:Seq> - </xmpMM:History> - </rdf:Description> - </rdf:RDF> -</x:xmpmeta> -<?xpacket end="r"?>ÖÂù��iCCPsRGB IEC61966-2.1��(‘u‘Ï+DQÇ?fL#Fˆ…b1iX ùQb£Œ4”¤1Ê`3ó¼™QóÆë½'ÉVÙNQbãׂ¿€²VŠHÉzÖĆé9Ϩ™dÎíÜó¹ß{ÏéÞsÁÍ(šYÝZÖ2"á>¶à÷æñÐFÅS™™¢¢}<PåÄ»n§VåsÿZݲj*PU#<¢è†%<!<µnéï -·(éø²ð¹pÐ -ß;z¢Èy‡SEþr؈FÆÀÕ(ìO•q¢Œ•´¡ ËË h™5å÷>ÎK|jvnVb‡x;&„ð3É8cÒǰ̃tÓO¬¨ßû“?ͪä*2ël`°BŠ4AQפº*1)º*#ÆÓÿ¿}5“ýÅê¾x^lû¼;PÈÙöç±mNÀýWÙRþ꽋ž+iChØ‚‹ë’–؃Ëmh}ÒãFüGr‹»’Ix=ƒú4ßBíb±g¿ûœ>BtS¾êö KÎ7,}® hhLv��� pHYs�����šœ��^IDATX…Í™[LUÇgX(!¥”^@ÛFc* Ø%*Ul -jÁ¤U£¡%ôÁxK³V+Þ"DטÔFKÚÄãC Û´‰1¶’>Ð4^¨1VSdEbHZ.+(m.—=>œag·)»;,ü“ÉžóoÎùí™ó}3sF0ƒìµ>P -›�;°z&ß(ät hu§6y«“˜.øÚ€Š¥t JwjíF? ½Ö�>bËæ—¨ëNm -ÀÐø&ðéBPh pÀg`Ì qY3ƒ¼ÀºSkF@üBì×ÜíÔi¨h]lp 2H©f,‘¦©ÃBÙ5Tž³DO@y¾U½°É†E—71^* ¡ñ¢ä愽R¨aÑâÕm‚ŒÈH…WÉÿ‘jµ%+¦jT<lÖwAåf+z†¨wÙaßöÐs”vZ°x¢ÜºÞ)3á\Íðn¶¿[&غ!š¢�ÌÉ‚Ožh_}39+9xFòóßFçBùädÅ03 êvãU½ó_8zVàóÁûßHÚ{T[b<ÔUÖ,‹`jÙ#XžlÚ֥ò¥f}lö—tªúò;àh¥ 5)€ŽÁúªÜÑö@‚MÍhRÀCÚÐ8ê%WGU}ý -x½$üô`f”wŠñI¨ùV²ß%¹<�¹w¡ñq¦ÿåAx㸙´wäCVÚ<î)Äg|Ñ$éºWGa_½dà<t|´Ë€¶npWå8 *7‡7‹aæÝ¥~'¦à䯦½wH�lÏ…êÁ§[%>Cl\ßÜ…À¿ö. ¨hÖÞGàÑûà¿ëêx¶^.6!=ÃðÇ%U^—ÞÏœ]Ó’ñ§•ÁÓ^œ ¯mŒxÁá’8\’/¼ø<ÿ é7½6l°2e�‡FàÆMUÎÍRfg‚óÁ¤ªOH:=Ðé·NH&¦àÀ“‚'6ªsV¥ªß±qè¿>€RÂ_}ªœ”�ï•>¯PÉÚÕ-]¦¯Þ¥î,BÀ‡;ŽAº1kžàåa €»×,—@FŠÿþ‚ñm0l*rñG¶»'œÃl¸ ¿åÝlú¯…úö_ƒQo°mr -~ý3–v]/Ï°t ”ä…ú–橶@}õƒZ§óP.vÛª¶òò[þZe”»Žýîh ìµ¾ðæõÀPý”¡Óêô�î]lojƒƒg$ã‘öá{Iq¶Šæ´ä™Û‡GXS[$½ÐgCí*•Erö97üØ!¹{%ÜŸÙ™´÷JܽðO¿ -Œ(¤ÛPûsLùð'èSa¯–Û©UCí,VéЈºÌ‹M-@ãbÞ~+К[0¶]k–)HèNÍ Á‰ú0ð6Š~¡äªºiÃl›èÇ°p[nŽjöꉨ€ÏvÌÏk,êÃü¡3Ëgˆÿj’Q óÞo����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/navigation/tests/src/Functional/NavigationLogoTest.php b/core/modules/navigation/tests/src/Functional/NavigationLogoTest.php index f0f65cf471d1bfead241e5c58fb5008ce338b5f2..377134f07b6ab70819fa01c1ca9664ebd591283c 100644 --- a/core/modules/navigation/tests/src/Functional/NavigationLogoTest.php +++ b/core/modules/navigation/tests/src/Functional/NavigationLogoTest.php @@ -4,9 +4,9 @@ namespace Drupal\Tests\navigation\Functional; -use Drupal\Core\Entity\EntityStorageException; use Drupal\file\Entity\File; use Drupal\Tests\BrowserTestBase; +use Drupal\Tests\TestFileCreationTrait; /** * Tests for \Drupal\navigation\Form\SettingsForm. @@ -15,6 +15,8 @@ */ class NavigationLogoTest extends BrowserTestBase { + use TestFileCreationTrait; + /** * The file system service. * @@ -22,13 +24,6 @@ class NavigationLogoTest extends BrowserTestBase { */ protected $fileSystem; - /** - * The config factory. - * - * @var \Drupal\Core\Config\ConfigFactoryInterface - */ - protected $configFactory; - /** * A user with administrative permissions. * @@ -54,9 +49,8 @@ class NavigationLogoTest extends BrowserTestBase { protected function setUp(): void { parent::setUp(); - // Inject the file_system and config.factory services. + // Inject the file_system service. $this->fileSystem = $this->container->get('file_system'); - $this->configFactory = $this->container->get('config.factory'); // Create and log in an administrative user. $this->adminUser = $this->drupalCreateUser([ @@ -70,6 +64,7 @@ protected function setUp(): void { * Tests Navigation logo configuration base options. */ public function testSettingsLogoOptionsForm(): void { + $test_files = $this->getTestFiles('image'); // Navigate to the settings form. $this->drupalGet('/admin/config/user-interface/navigation/settings'); $this->assertSession()->statusCodeEquals(200); @@ -87,51 +82,44 @@ public function testSettingsLogoOptionsForm(): void { $this->assertSession()->elementNotExists('css', 'a.admin-toolbar__logo'); // Option 3: Set the logo provider to custom and upload a logo. - $logo_file = $this->createFile(); + $file = reset($test_files); + $logo_file = File::create((array) $file + ['status' => 1]); + $logo_file->save(); $this->assertNotEmpty($logo_file, 'File entity is not empty.'); - // Preset the configuration to verify a custom image is being seen. - $config = $this->configFactory->getEditable('navigation.settings'); - $config->set('logo.provider', 'custom'); - $config->set('logo.managed', $logo_file->id()); - $config->save(); + $edit = [ + 'logo_provider' => 'custom', + 'logo_path' => $logo_file->getFileUri(), + ]; + $this->submitForm($edit, t('Save configuration')); // Refresh the page to verify custom logo is placed. $this->drupalGet('/admin/config/user-interface/navigation/settings'); $this->assertSession()->elementExists('css', 'a.admin-toolbar__logo > img'); $this->assertSession()->elementAttributeContains('css', 'a.admin-toolbar__logo > img', 'src', $logo_file->getFilename()); - } - /** - * Helper function to create a file entity. - * - * @return \Drupal\file\FileInterface - * The file entity. - * - * @throws \Drupal\Core\Entity\EntityStorageException - */ - protected function createFile() { - // Define the file URI and path. - $file_name = 'test-logo.png'; - $temp_dir = $this->fileSystem->getTempDirectory(); - $file_uri = 'public://' . $file_name; - $logo_path = __DIR__ . '/../../assets/image_test_files/' . $file_name; - $file_contents = file_get_contents($logo_path); - file_put_contents($temp_dir . '/' . $file_name, $file_contents); - - // Create a file entity for testing. - $file = File::create([ - 'uri' => $file_uri, - ]); - - try { - $file->setPermanent(); - $file->save(); - } - catch (EntityStorageException $e) { - $this->fail(sprintf('Failed to create file entity: %s', $e->getMessage())); - } + // Option 4: Set the custom logo to an image in the source code. + $edit = [ + 'logo_provider' => 'custom', + 'logo_path' => 'core/misc/logo/drupal-logo.svg', + ]; + $this->submitForm($edit, t('Save configuration')); + // Refresh the page to verify custom logo is placed. + $this->drupalGet('/admin/config/user-interface/navigation/settings'); + $this->assertSession()->elementExists('css', 'a.admin-toolbar__logo > img'); + $this->assertSession()->elementAttributeContains('css', 'a.admin-toolbar__logo > img', 'src', 'drupal-logo.svg'); - return $file; + // Option 5: Upload custom logo. + $file = end($test_files); + $edit = [ + 'logo_provider' => 'custom', + 'files[logo_upload]' => $this->fileSystem->realpath($file->uri), + ]; + $this->submitForm($edit, t('Save configuration')); + $this->assertSession()->statusMessageContains('The image was resized to fit within the navigation logo expected dimensions of 40x40 pixels. The new dimensions of the resized image are 40x27 pixels.'); + // Refresh the page to verify custom logo is placed. + $this->drupalGet('/admin/config/user-interface/navigation/settings'); + $this->assertSession()->elementExists('css', 'a.admin-toolbar__logo > img'); + $this->assertSession()->elementAttributeContains('css', 'a.admin-toolbar__logo > img', 'src', $file->name); } } diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationSettingsFormTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/NavigationSettingsFormTest.php deleted file mode 100644 index 746ec4a4be7d4919b695d7a519c11eac28b60741..0000000000000000000000000000000000000000 --- a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationSettingsFormTest.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -declare(strict_types=1); - -namespace Drupal\Tests\navigation\FunctionalJavascript; - -use Drupal\file\Entity\File; -use Drupal\FunctionalJavascriptTests\WebDriverTestBase; -use Drupal\Tests\TestFileCreationTrait; - -/** - * Tests that theme form settings works correctly. - * - * @group navigation - */ -class NavigationSettingsFormTest extends WebDriverTestBase { - - use TestFileCreationTrait; - - /** - * {@inheritdoc} - */ - protected static $modules = ['navigation']; - - /** - * {@inheritdoc} - */ - protected $defaultTheme = 'stark'; - - /** - * {@inheritdoc} - */ - protected function setUp(): void { - parent::setUp(); - - $admin = $this->drupalCreateUser(['administer site configuration']); - $this->drupalLogin($admin); - - // Set expected logo dimensions smaller than core provided test images. - \Drupal::configFactory()->getEditable('navigation.settings') - ->set('logo.max.height', 10) - ->set('logo.max.width', 10) - ->save(); - } - - /** - * Tests that submission handler works correctly. - */ - public function testFormSettingsSubmissionHandler() { - $page = $this->getSession()->getPage(); - $assert_session = $this->assertSession(); - - $this->drupalGet("/admin/config/user-interface/navigation/settings"); - - // Add a new managed file. - $file = current($this->getTestFiles('image')); - $image_file_path = \Drupal::service('file_system')->realpath($file->uri); - $page->attachFileToField('files[logo_managed]', $image_file_path); - $assert_session->waitForButton('logo_managed_remove_button'); - - // Assert the new file is uploaded as temporary. This file should not be - // saved as permanent if settings are not submitted. - $image_field = $this->assertSession()->hiddenFieldExists('logo_managed[fids]'); - $file = File::load($image_field->getValue()); - $this->assertFalse($file->isPermanent()); - - $page->pressButton('Save configuration'); - \Drupal::entityTypeManager()->getStorage('file')->resetCache(); - - $this->drupalGet("/admin/config/user-interface/navigation/settings"); - - // Assert the uploaded file is saved as permanent. - $image_field = $this->assertSession()->hiddenFieldExists('logo_managed[fids]'); - $file = File::load($image_field->getValue()); - $this->assertTrue($file->isPermanent()); - - // Ensure that the image has been resized to fit in the expected container. - $image = \Drupal::service('image.factory')->get($file->getFileUri()); - $this->assertLessThanOrEqual(10, $image->getHeight()); - $this->assertLessThanOrEqual(10, $image->getWidth()); - } - -}