Created on 27 May 2025, 4 months ago

Problem/Motivation

When upgrading from 2.x -> 3.x extra settings (title_format, title_fallback) are added but we do not update existing content, leading to broken embeds that just output the raw text.

Steps to reproduce

  1. Install ckeditor5 and video_embed_field 2.x
  2. Set ckeditor5 as the text editor for an available format at /admin/config/content/formats
  3. Add the "Video Embed" button to the toolbar
  4. Create a new piece of content using the video embed tool
  5. Upgrade video_embed_field to 3.x
  6. Clear cache
  7. View content, note raw output

Proposed resolution

Provide an upgrade path that checks for text, text_long, or text_with_summary field configuration on nodes, paragraphs, and block_content. Then, check those fields in the database for video_embed_wysiwyg usage and add the missing configuration to the settings.

🐛 Bug report
Status

Needs review

Version

3.0

Component

Video Embed WYSWIYG

Created by

🇨🇦Canada cchiste

Live updates comments and jobs are added and updated live.
  • Upgrade path

    It affects the ability to upgrade Drupal sites to a new major version. Preferred over version-specific tags such as D7 upgrade path.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @cchiste
  • Merge request !84Resolve #3526845 "Upgrade path" → (Merged) created by cchiste
  • Pipeline finished with Success
    4 months ago
    Total: 173s
    #507787
  • Pipeline finished with Success
    4 months ago
    Total: 223s
    #507795
  • Pipeline finished with Success
    4 months ago
    Total: 190s
    #507798
  • Pipeline finished with Success
    4 months ago
    Total: 171s
    #507802
  • I've made another update.
    - a bit cleaner,
    - very fast,
    - covers all multiline text fields and db revisions
    - does one database table per pass (not tested on that)
    - converts settings to json instead of manipulating strings
    Shouldn't do any harm, at least.

    <?php
    
    /**
     * @file
     * Install file for Video Embed WYSIWYG.
     */
    const VIDEO_EMBED_WYSIWYG_UPDATE_REGEX = '\{"preview_thumbnail"[^}]*"video_url"[^}]*"settings":\{[^}]*\}[^}]*\}';
    
    /**
     * Add title_format setting to video embed settings.
     */
    function video_embed_wysiwyg_update_10001(&$sandbox) {
      $database = Drupal::database();
      if (!isset($sandbox['embed_node_tables'])) {
        foreach (\Drupal::service('entity_field.manager')->getFieldMap() as $entity_type => $fields) {
          foreach ($fields as $field_name => $field_info) {
            if ($field_info['type'] == 'text_long' or $field_info['type'] == 'text_with_summary') {
              $sandbox['embed_node_tables'][$entity_type.'__'.$field_name] = 0;
              $sandbox['embed_node_tables'][$entity_type.'_revision__'.$field_name] = 0;
              $sandbox['finished'] = 0;
            }
          }
        }
      }
      $table_name = key($sandbox['embed_node_tables']);
      // Do one table each pass.
      video_embed_wysiwyg_update_text($table_name, $sandbox['embed_node_tables']);
    }
    
    /**
     * Updates up to 999 fields. Very fast.
     *
     * @param string $table_name
     * @param int $last_updated_id
     *   updated by reference
     */
    function video_embed_wysiwyg_update_text($table_name, array &$tables) {
      $last_updated_id = &$tables[$table_name];
      $col = substr($table_name, strpos($table_name, '__') + 2) . '_value';
      $cols = ['entity_id', $col];
      if (str_contains($table_name, '_revision__')) {
        $cols[] = 'vid';
      }
      $field_values = $database->select($table_name, 't')
        ->fields('t', )
        ->where($col . ' REGEXP :pattern', [':pattern' => VIDEO_EMBED_WYSIWYG_UPDATE_REGEX])
        ->condition('t.entity_id', $last_updated_id, '>')
        ->orderby('entity_id', 'DESC')
        ->execute()->fetchAllAssoc('entity_id');
    
      $count = 0;
      while ($res = array_pop($field_values)) {
        $count++;
        $id = $res->entity_id;
        $orig_text = $res->{$col};
        $replace_text = $orig_text;
        if (preg_match_all('/'.$regex_pattern.'/', $orig_text, $matches)) {
          foreach ($matches[0] as $match) {
            $embed_data = json_decode($match, TRUE);
            $embed_data['settings'] += ['title_fallback' => TRUE, 'title_format' => '@provider | @title'];
            $replace_text = str_replace($match, json_encode($embed_data, JSON_UNESCAPED_SLASHES), $replace_text);
          }
        }
        if ($replace_text and strlen($replace_text) > strlen($orig_text)) {
          $q= $database->update($table_name)
            ->fields([$col => $replace_text]);
          if (str_contains($table_name, '_revision__')) {
            $q->condition('vid', $last_updated_id = $res->vid);
          }
          else {
            $q->condition('entity_id', $last_updated_id = $res->entity_id);
          }
          $q->execute();
        }
        $tables[$table_name] = $last_updated_id;
        if ($count > 999) break;
      }
      if (empty($field_values)) {
        unset($tables[$table_name]);
        $sandbox['finished'] = empty($tables);
      }
    }
    
  • 🇫🇷France mably

    Shouldn't the rendering code also be fixed to avoid rendering raw content? 🤔

  • can you say a bit more about that?

  • 🇫🇷France mably

    Can't we just use some default value when the new configuration is missing?

  • 🇨🇦Canada cchiste

    @matslats Thank you for the improvement suggestions! I tried running this locally and noticed a couple of issues.

    • No `\` on Drupal for initial assignment of `$database` to `Drupal::database()
    • `$database` is not defined in `video_embed_wysiwyg_update_text`

    @mably I might be misunderstanding, but I believe we are providing the default value (as far as Video Embed Field goes) in the following. Let me know if I am off base though.
    ```
    // Check if title_format already exists.
    if (!preg_match('/"title_format"/', $settings)) {
    // Add title_format setting.
    $title_format = '"title_format":"@provider | @title"';
    $title_fallback = '"title_fallback":true';

    // If settings is empty, just add the title_format.
    if (trim($settings) === '') {
    $updated_settings = $title_format . ',' . $title_fallback;
    }
    else {
    // Add title_format at the end.
    $updated_settings = $settings . ',' . $title_format . ',' . $title_fallback;
    }

    \Drupal::logger('video_embed_wysiwyg')->notice('Added title_format and title_fallback to settings: @old -> @new', [
    '@old' => $settings,
    '@new' => $updated_settings,
    ]);

    return '"settings":{' . $updated_settings . '}';
    }
    ```

  • @mably That approach also seems valid, and would require less upgrade code, but its also cleaner in the long term to update the old data so that all the data managed by the module is consistent. So its up to the maintenance team to decide.

  • 🇳🇿New Zealand Gold 20 minutes in the future

    I've just hit this and only incidentally found this issue. I'm going to dive into testing it, but thought I'd update the Title to something that would have jumped out to me as relating to my issue.

  • 🇳🇿New Zealand Gold 20 minutes in the future

    MR!84 is looking good to me.

    While the reworking at #3 may be less code, !84 is very readable, doesn't introduce extra constants or functions outside of the update hook. It is also working in it's current state. If this code was going to be used repeatedly the proposed optimisation would be worth exploring, but with it being a one-shot update, I don't see the need.

    MR!84, as it stands now, gets my RTBC.

  • 🇫🇷France mably

    Ok, let's merge this and see how it goes.

  • Status changed to Fixed about 2 months ago
  • Automatically closed - issue fixed for 2 weeks with no activity.

  • 🇬🇧United Kingdom jwmorris

    This patch doesn't seem to work with translations. We installed and ran the DB updates, and whilst it did correctly restore all the videos, it converted all fields with videos into the site's default language despite those fields being translated before running the DB update.

  • 🇬🇧United Kingdom jwmorris

    Here's an updated version of the MR84 patch - specifically, an extra condition at line 141 of .install to take into account the langcode.

  • 🇫🇷France mably

    @jwmorris previous patch has already been merged.

    Could you provide an MR against the 3.x branch with your fix please?

  • 🇫🇷France mably

    @jwmorris I just created MR 86 to include the diff from your patch.

    Can you confirm that it fixes the problem ?

    • mably committed c08e56b1 on 3.x
      Issue #3526845 by cchiste, mably, jwmorris: Upgrade Path to resolve raw...
  • Now that this issue is closed, please review the contribution record.

    As a contributor, attribute any organization helped you, or if you volunteered your own time.

    Maintainers, please credit people who helped resolve this issue.

Production build 0.71.5 2024