From 1e63bf7192a78eba5359004774b2e59c56e0c067 Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Mon, 17 Mar 2025 08:39:32 -0500
Subject: [PATCH 1/9] Capture changes from patch #7.

---
 js/patternkit.jsoneditor.js                     |  2 +-
 .../src/MediaLibraryJSONLibraryOpener.php       | 17 +++++++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/js/patternkit.jsoneditor.js b/js/patternkit.jsoneditor.js
index b49fb07f..95e8d0e5 100644
--- a/js/patternkit.jsoneditor.js
+++ b/js/patternkit.jsoneditor.js
@@ -307,7 +307,7 @@ patternkitEditorArray(jQuery, Drupal, JSONEditor);
      }
      // Ajax command response to allow updating Editor field values.
      Drupal.AjaxCommands.prototype.patternkitEditorUpdate = function (ajax, response, status) {
-       window.patternkitEditor.getEditor(response.selector).setValue(response.value);
+       window.patternkitEditor.getEditor(response.selector)?.setValue(response.value);
      };
 
      let $target = $('#patternkit-editor-target', context);
diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 2933503d..384d249b 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -98,6 +98,23 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
       }
       else {
         $value = $this->getFileUrl($media);
+        // If we're populating the image src, also try to populate the image alt text.
+        if (str_ends_with($widget_id, '.image.src')) {
+          // Build the alt widget alt id.
+          $alt_id = str_replace('image.src', 'image.alt', $widget_id);
+          // Build the height/width widget ids.
+          $height_id = str_replace('image.src', 'image.height', $widget_id);
+          $width_id = str_replace('image.src', 'image.width', $widget_id);
+          // Grab the alt text from the media item.
+          $alt_text = $media->get('field_media_image')->first()->alt;
+          // Grab the width and height from the media item.
+          $img_width = $media->get('field_media_image')->first()->width;
+          $img_height = $media->get('field_media_image')->first()->height;
+          // Update the fields in json editor.
+          $response->addCommand(new PatternkitEditorUpdateCommand($alt_id, $alt_text));
+          $response->addCommand(new PatternkitEditorUpdateCommand($width_id, $img_width));
+          $response->addCommand(new PatternkitEditorUpdateCommand($height_id, $img_height));
+        }
       }
 
       $response->addCommand(new PatternkitEditorUpdateCommand($widget_id, $value));
-- 
GitLab


From e3a397caedf9a5ef26dd35f2a7a88968db346bb5 Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Mon, 17 Mar 2025 13:56:57 -0500
Subject: [PATCH 2/9] Generalize source file loading to not assume field name.

---
 .../src/MediaLibraryJSONLibraryOpener.php     | 123 +++++++++---------
 1 file changed, 65 insertions(+), 58 deletions(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 384d249b..edd72299 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -4,11 +4,11 @@ namespace Drupal\patternkit_media_library;
 
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Ajax\AjaxResponse;
-use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\File\FileUrlGeneratorInterface;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\file\FileInterface;
 use Drupal\media\MediaInterface;
 use Drupal\media_library\MediaLibraryOpenerInterface;
 use Drupal\media_library\MediaLibraryState;
@@ -19,46 +19,18 @@ use Drupal\patternkit\AJAX\PatternkitEditorUpdateCommand;
  */
 class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
 
-  /**
-   * The entity type manager.
-   *
-   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
-   */
-  protected EntityTypeManagerInterface $entityTypeManager;
-
-  /**
-   * The file url generator service.
-   *
-   * @var \Drupal\Core\File\FileUrlGeneratorInterface
-   */
-  protected FileUrlGeneratorInterface $fileUrlGenerator;
-
-  /**
-   * The configuration factory service.
-   *
-   * @var \Drupal\Core\Config\ConfigFactoryInterface
-   */
-  protected ConfigFactoryInterface $configFactory;
-
-  /**
-   * The loaded settings for the Pattern Media Library module.
-   *
-   * @var array
-   */
-  protected array $settings;
-
   /**
    * MediaLibraryFieldWidgetOpener constructor.
    *
-   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
    *   The entity type manager.
-   * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator
+   * @param \Drupal\Core\File\FileUrlGeneratorInterface $fileUrlGenerator
    *   The file url generator service.
    */
-  public function __construct(EntityTypeManagerInterface $entity_type_manager, FileUrlGeneratorInterface $file_url_generator) {
-    $this->entityTypeManager = $entity_type_manager;
-    $this->fileUrlGenerator = $file_url_generator;
-  }
+  public function __construct(
+    protected EntityTypeManagerInterface $entityTypeManager,
+    protected FileUrlGeneratorInterface $fileUrlGenerator,
+  ) {}
 
   /**
    * {@inheritdoc}
@@ -90,36 +62,52 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
       return $response;
     }
     try {
-      /** @var \Drupal\media\Entity\Media $media */
+      /** @var \Drupal\media\MediaInterface $media */
       $media = $this->entityTypeManager->getStorage('media')->load($mid);
+      assert($media instanceof MediaInterface);
 
       if ($use_media_token) {
-        $value = $this->getMediaToken($media);
+        $media_token = $this->getMediaToken($media);
+        $response->addCommand(new PatternkitEditorUpdateCommand($widget_id, $media_token));
       }
       else {
-        $value = $this->getFileUrl($media);
-        // If we're populating the image src, also try to populate the image alt text.
+        $image_src = $this->getFileUrl($media);
+        $response->addCommand(new PatternkitEditorUpdateCommand($widget_id, $image_src));
+
+        // If we're populating the image src, also try to populate the image
+        // alt text and dimensions. If a schema doesn't match this format for
+        // an image field, this additional processing will be ignored
+        // altogether.
         if (str_ends_with($widget_id, '.image.src')) {
-          // Build the alt widget alt id.
-          $alt_id = str_replace('image.src', 'image.alt', $widget_id);
-          // Build the height/width widget ids.
-          $height_id = str_replace('image.src', 'image.height', $widget_id);
-          $width_id = str_replace('image.src', 'image.width', $widget_id);
-          // Grab the alt text from the media item.
-          $alt_text = $media->get('field_media_image')->first()->alt;
-          // Grab the width and height from the media item.
-          $img_width = $media->get('field_media_image')->first()->width;
-          $img_height = $media->get('field_media_image')->first()->height;
-          // Update the fields in json editor.
-          $response->addCommand(new PatternkitEditorUpdateCommand($alt_id, $alt_text));
-          $response->addCommand(new PatternkitEditorUpdateCommand($width_id, $img_width));
-          $response->addCommand(new PatternkitEditorUpdateCommand($height_id, $img_height));
+          // Attempt to load the source file to identify additional available
+          // attributes.
+          $image = $this->getSourceFile($media);
+
+          // Stop here if the image was not able to be loaded.
+          if ($image !== NULL) {
+            // Remove 'src' from the end of the widget path to easily append the
+            // additional attributes.
+            $widget_base_path = substr($widget_id, 0, -3);
+
+            // Images will typically produce the following attributes: 'alt',
+            // 'height', 'target_id', 'title', and 'width'.
+            $attributes = $media->get('field_media_image')->first()->getValue();
+            foreach ($attributes as $key => $value) {
+              // Only assign attributes with non-empty values, and ignore the
+              // internal value for the target_id referencing the file entity.
+              if ($key != 'target_id' && $value) {
+                $target = $widget_base_path . $key;
+
+                // If a field is not found in the schema client-side, the
+                // command should fail silently.
+                $response->addCommand(new PatternkitEditorUpdateCommand($target, $value));
+              }
+            }
+          }
         }
       }
-
-      $response->addCommand(new PatternkitEditorUpdateCommand($widget_id, $value));
     }
-    catch (\Exception $exception) {
+    catch (\Exception) {
       return $response;
     }
 
@@ -162,8 +150,7 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
    * @throws \Drupal\Core\Entity\EntityMalformedException
    */
   protected function getFileUrl(MediaInterface $media): string {
-    $fid = $media->getSource()->getSourceFieldValue($media);
-    $file = $this->entityTypeManager->getStorage('file')->load($fid);
+    $file = $this->getSourceFile($media);
 
     if ($file->hasLinkTemplate('canonical')) {
       $url = $file->toUrl()->setAbsolute(FALSE);
@@ -178,4 +165,24 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
     return $url;
   }
 
+  /**
+   * Load the source file entity from the given media.
+   *
+   * @param \Drupal\media\MediaInterface $media
+   *   The media entity to load the source file from.
+   *
+   * @return \Drupal\file\FileInterface|null
+   *   The loaded source file entity or NULL if the file could not be loaded.
+   *
+   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
+   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
+   */
+  protected function getSourceFile(MediaInterface $media): ?FileInterface {
+    $fid = $media->getSource()->getSourceFieldValue($media);
+    $file = $this->entityTypeManager->getStorage('file')->load($fid);
+
+    assert($file === NULL || $file instanceof FileInterface);
+    return $file;
+  }
+
 }
-- 
GitLab


From 24aa5a457fd1ec0fc4f9f34d976f5476a26d017b Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Thu, 20 Mar 2025 16:56:18 -0500
Subject: [PATCH 3/9] Add null safety to file URL processing.

---
 .../src/MediaLibraryJSONLibraryOpener.php                 | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index edd72299..6e31f0a8 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -152,17 +152,17 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
   protected function getFileUrl(MediaInterface $media): string {
     $file = $this->getSourceFile($media);
 
-    if ($file->hasLinkTemplate('canonical')) {
+    if ($file?->hasLinkTemplate('canonical')) {
       $url = $file->toUrl()->setAbsolute(FALSE);
     }
-    elseif ($file->access('download')) {
+    elseif ($file?->access('download')) {
       $url = $this->fileUrlGenerator->generateString($file->getFileUri());
     }
     else {
-      $url = $file->label();
+      $url = $file?->label();
     }
 
-    return $url;
+    return (string) $url;
   }
 
   /**
-- 
GitLab


From bcb18e8b3fe32376951deb2d682101f5e6cc80ac Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Fri, 21 Mar 2025 09:15:55 -0500
Subject: [PATCH 4/9] Add debug warning for missing editor value assignments.

---
 js/patternkit.jsoneditor.js | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/js/patternkit.jsoneditor.js b/js/patternkit.jsoneditor.js
index 95e8d0e5..56645e2c 100644
--- a/js/patternkit.jsoneditor.js
+++ b/js/patternkit.jsoneditor.js
@@ -307,7 +307,15 @@ patternkitEditorArray(jQuery, Drupal, JSONEditor);
      }
      // Ajax command response to allow updating Editor field values.
      Drupal.AjaxCommands.prototype.patternkitEditorUpdate = function (ajax, response, status) {
-       window.patternkitEditor.getEditor(response.selector)?.setValue(response.value);
+       let editor = window.patternkitEditor.getEditor(response.selector);
+
+       if (editor) {
+         editor.setValue(response.value);
+       }
+       else {
+         window.console?.debug('Unable to find an editor at "%s" to assign value "%s".',
+           response.selector, response.value);
+       }
      };
 
      let $target = $('#patternkit-editor-target', context);
-- 
GitLab


From 7fd3e586cafd1027c508a83cef2721f8eb5973c3 Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Fri, 21 Mar 2025 10:09:48 -0500
Subject: [PATCH 5/9] Log media opener exceptions server-side.

---
 .../patternkit_media_library.services.yml       |  7 +++++++
 .../src/MediaLibraryJSONLibraryOpener.php       | 17 +++++++++++++++--
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/modules/patternkit_media_library/patternkit_media_library.services.yml b/modules/patternkit_media_library/patternkit_media_library.services.yml
index d2fb1886..7e1df3ee 100644
--- a/modules/patternkit_media_library/patternkit_media_library.services.yml
+++ b/modules/patternkit_media_library/patternkit_media_library.services.yml
@@ -1,4 +1,11 @@
 services:
+  _defaults:
+    autoconfigure: true
+
+  logger.channel.patternkit_media_library:
+    parent: logger.channel_base
+    arguments: [ 'patternkit_media_library' ]
+
   patternkit.opener.jsonlibrary:
     class: Drupal\patternkit_media_library\MediaLibraryJSONLibraryOpener
     arguments:
diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 6e31f0a8..75ab9f94 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -4,20 +4,28 @@ namespace Drupal\patternkit_media_library;
 
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\MessageCommand;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\File\FileUrlGeneratorInterface;
+use Drupal\Core\Form\FormAjaxException;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Template\Attribute;
+use Drupal\Core\Utility\Error;
 use Drupal\file\FileInterface;
 use Drupal\media\MediaInterface;
 use Drupal\media_library\MediaLibraryOpenerInterface;
 use Drupal\media_library\MediaLibraryState;
 use Drupal\patternkit\AJAX\PatternkitEditorUpdateCommand;
+use Psr\Log\LoggerAwareInterface;
+use Psr\Log\LoggerAwareTrait;
+use Symfony\Component\Lock\Exception\InvalidArgumentException;
 
 /**
  * The media library opener for field widgets.
  */
-class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
+class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface, LoggerAwareInterface {
+
+  use LoggerAwareTrait;
 
   /**
    * MediaLibraryFieldWidgetOpener constructor.
@@ -107,7 +115,12 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface {
         }
       }
     }
-    catch (\Exception) {
+    catch (\Exception $exception) {
+      // Log the failure server-side for review and visibility.
+      Error::logException($this->logger, $exception);
+
+      // @todo Add a client-side warning message to the form with MessageCommand
+      //   and a new message list container on the form.
       return $response;
     }
 
-- 
GitLab


From bc13228c0309be5d28b708b91b358312b4780597 Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Fri, 21 Mar 2025 13:24:54 -0500
Subject: [PATCH 6/9] Add editor notification if the media opener encounters an
 exception.

---
 .../src/MediaLibraryJSONLibraryOpener.php     | 20 ++++++++++++---
 src/Plugin/Block/PatternkitBlock.php          | 25 +++++++++++++------
 2 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 75ab9f94..433f79a6 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -4,10 +4,11 @@ namespace Drupal\patternkit_media_library;
 
 use Drupal\Core\Access\AccessResult;
 use Drupal\Core\Ajax\AjaxResponse;
+use Drupal\Core\Ajax\CloseDialogCommand;
 use Drupal\Core\Ajax\MessageCommand;
+use Drupal\Core\Ajax\ScrollTopCommand;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\File\FileUrlGeneratorInterface;
-use Drupal\Core\Form\FormAjaxException;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\Template\Attribute;
 use Drupal\Core\Utility\Error;
@@ -18,7 +19,6 @@ use Drupal\media_library\MediaLibraryState;
 use Drupal\patternkit\AJAX\PatternkitEditorUpdateCommand;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerAwareTrait;
-use Symfony\Component\Lock\Exception\InvalidArgumentException;
 
 /**
  * The media library opener for field widgets.
@@ -119,8 +119,20 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface, Logg
       // Log the failure server-side for review and visibility.
       Error::logException($this->logger, $exception);
 
-      // @todo Add a client-side warning message to the form with MessageCommand
-      //   and a new message list container on the form.
+      // Display a message client-side for context when the value fails to be
+      // populated.
+      $response->addCommand(new MessageCommand(
+        'There was a problem selecting the media asset. Save your work.',
+        '.patternkit-form-messages .messages-list',
+        ['type' => 'warning']
+      ));
+
+      // A redundant close dialog command is added by the
+      // MediaLibrarySelectForm, but we have to close the media dialog first for
+      // the scroll command to take effect.
+      $response->addCommand(new CloseDialogCommand('#drupal-modal'));
+      $response->addCommand(new ScrollTopCommand('.patternkit-form-messages'));
+
       return $response;
     }
 
diff --git a/src/Plugin/Block/PatternkitBlock.php b/src/Plugin/Block/PatternkitBlock.php
index 465ea012..088c0ac7 100644
--- a/src/Plugin/Block/PatternkitBlock.php
+++ b/src/Plugin/Block/PatternkitBlock.php
@@ -266,14 +266,25 @@ class PatternkitBlock extends BlockBase implements ContainerFactoryPluginInterfa
     // in layout builder and elsewhere.
     $configuration['reusable'] = $patternkit_block->isNew() ? $is_block_form : $patternkit_block->isReusable();
 
+    // Include a messages list wrapper to display AJAX warnings or messages.
+    // NB. The class must be added on a theme wrapper since the '#attributes'
+    // key is lost when the status_messages element renders as a placeholder.
+    $form['messages'] = [
+      '#theme' => 'status_messages',
+      '#message_list' => [],
+      '#theme_wrappers' => [
+        'container' => [
+          '#attributes' => [
+            'class' => ['patternkit-form-messages'],
+          ],
+        ],
+      ],
+    ];
+
     // Warn about accidental changes to reusable blocks.
     if (isset($configuration['reusable']) && $configuration['reusable']) {
-      $form['messages'] = [
-        '#theme' => 'status_messages',
-        '#message_list' => [
-          'warning' => [$this->t('This block is reusable! Any changes made will be applied globally.')],
-        ],
-      ];
+      $form['messages']['#message_list']['warning'][] =
+        $this->t('This block is reusable! Any changes made will be applied globally.');
     }
 
     $form['reusable'] = [
@@ -560,7 +571,7 @@ class PatternkitBlock extends BlockBase implements ContainerFactoryPluginInterfa
           ['@version' => $pattern->getVersion()]
         );
       }
-      $form['schema_desc'] = ['#markup' => $success_message];
+      $form['messages']['#message_list']['status'][] = $success_message;
     }
 
     try {
-- 
GitLab


From a5fa83d9d8cafd0a8d46be34cee88400c6b238af Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Fri, 21 Mar 2025 13:40:00 -0500
Subject: [PATCH 7/9] Handle media load failures in the opener.

---
 .../src/MediaLibraryJSONLibraryOpener.php             | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 433f79a6..4122c530 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -70,9 +70,16 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface, Logg
       return $response;
     }
     try {
-      /** @var \Drupal\media\MediaInterface $media */
+      /** @var \Drupal\media\MediaInterface|null $media */
       $media = $this->entityTypeManager->getStorage('media')->load($mid);
-      assert($media instanceof MediaInterface);
+
+      // Fail here if the Media entity couldn't be loaded.
+      if ($media === NULL) {
+        $this->logger->error('Unable to load media entity "@mid" for media opener.', [
+          '@mid' => $mid,
+        ]);
+        return $response;
+      }
 
       if ($use_media_token) {
         $media_token = $this->getMediaToken($media);
-- 
GitLab


From 6539a007f5fce8a0b56e49e84f4160f376043528 Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Fri, 21 Mar 2025 13:43:17 -0500
Subject: [PATCH 8/9] More explicitly test for a media interface on loaded
 media result.

---
 .../src/MediaLibraryJSONLibraryOpener.php                       | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index 4122c530..ea1d8c32 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -74,7 +74,7 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface, Logg
       $media = $this->entityTypeManager->getStorage('media')->load($mid);
 
       // Fail here if the Media entity couldn't be loaded.
-      if ($media === NULL) {
+      if (!($media instanceof MediaInterface)) {
         $this->logger->error('Unable to load media entity "@mid" for media opener.', [
           '@mid' => $mid,
         ]);
-- 
GitLab


From 5e5712c1b2033be5ae094c9c0f4e74bb5b8465ac Mon Sep 17 00:00:00 2001
From: Stephen Lucero <slucero@redhat.com>
Date: Wed, 26 Mar 2025 08:33:13 -0500
Subject: [PATCH 9/9] Replace remaining hardcoded image field name.

---
 .../src/MediaLibraryJSONLibraryOpener.php     | 29 +++++++++++--------
 1 file changed, 17 insertions(+), 12 deletions(-)

diff --git a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
index ea1d8c32..953717d6 100644
--- a/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
+++ b/modules/patternkit_media_library/src/MediaLibraryJSONLibraryOpener.php
@@ -104,18 +104,23 @@ class MediaLibraryJSONLibraryOpener implements MediaLibraryOpenerInterface, Logg
             // additional attributes.
             $widget_base_path = substr($widget_id, 0, -3);
 
-            // Images will typically produce the following attributes: 'alt',
-            // 'height', 'target_id', 'title', and 'width'.
-            $attributes = $media->get('field_media_image')->first()->getValue();
-            foreach ($attributes as $key => $value) {
-              // Only assign attributes with non-empty values, and ignore the
-              // internal value for the target_id referencing the file entity.
-              if ($key != 'target_id' && $value) {
-                $target = $widget_base_path . $key;
-
-                // If a field is not found in the schema client-side, the
-                // command should fail silently.
-                $response->addCommand(new PatternkitEditorUpdateCommand($target, $value));
+            $source_configuration = $media->getSource()?->getConfiguration();
+            $source_field_name = is_array($source_configuration) ? $source_configuration['source_field'] : NULL;
+
+            if ($source_field_name !== NULL) {
+              // Images will typically produce the following attributes: 'alt',
+              // 'height', 'target_id', 'title', and 'width'.
+              $attributes = $media->get($source_field_name)?->first()?->getValue() ?: [];
+              foreach ($attributes as $key => $value) {
+                // Only assign attributes with non-empty values, and ignore the
+                // internal value for the target_id referencing the file entity.
+                if ($key != 'target_id' && $value) {
+                  $target = $widget_base_path . $key;
+
+                  // If a field is not found in the schema client-side, the
+                  // command should fail silently.
+                  $response->addCommand(new PatternkitEditorUpdateCommand($target, $value));
+                }
               }
             }
           }
-- 
GitLab