Account created on 17 February 2007, over 17 years ago
#

Merge Requests

More

Recent comments

🇺🇸United States loze

Didn't realize there was already an issue for this.

🇺🇸United States loze

loze created an issue.

🇺🇸United States loze

Thanks, The update hook worked for me.
My commit gets the changed timestamp to update when the entity is saved. It appears to be working as expected in my local environment.

🇺🇸United States loze

loze changed the visibility of the branch 3178212-check-rebuild-access to hidden.

🇺🇸United States loze

loze made their first commit to this issue’s fork.

🇺🇸United States loze

+1 for adding this.

The MR does add the field successfully, however I think we need to add a few things.

1. Add an update hook that copies all of the existing message entities created timestamps to the new changed field. Currently they are all null.
2. Editing a message entity on the entity edit page message/%/edit does not update the changed date.

🇺🇸United States loze

Not exactly sure why, but apparently inside the .each() functions $(this) was undefined. so instead I changed it to use the element parameter in the each function. This MR seems to resolve the issue for me.

🇺🇸United States loze

Thanks Grevil, I tried your MR and get the following error now

The website encountered an unexpected error. Try again later.

TypeError: strlen(): Argument #1 ($string) must be of type string, array given in strlen() (line 395 of core/lib/Drupal/Component/Utility/Unicode.php).
Drupal\Component\Utility\Unicode::validateUtf8(Array) (Line: 65)
Drupal\Component\Utility\Xss::filter(Array) (Line: 52)
facebook_pixel_page_attachments(Array) (Line: 311)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}(Object, 'facebook_pixel') (Line: 388)
Drupal\Core\Extension\ModuleHandler->invokeAllWith('page_attachments', Object) (Line: 308)
Drupal\Core\Render\MainContent\HtmlRenderer->invokePageAttachmentHooks(Array) (Line: 285)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 627)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 284)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 128)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 186)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 28)
Drupal\Core\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 32)
Drupal\big_pipe\StackMiddleware\ContentLength->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 193)
Drupal\cleantalk\EventSubscriber\BootSubscriber->handle(Object, 1, 1) (Line: 53)
Asm89\Stack\Cors->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 36)
Drupal\Core\StackMiddleware\AjaxPageState->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
🇺🇸United States loze

Apologies for all the chatter here, but I think I got all the formatting issues resolved. The pipeline checks pass now.

🇺🇸United States loze

Apologies for all the chatter here, but I think I got all the formatting issues resolved. The pipeline checks pass now.

🇺🇸United States loze

loze changed the visibility of the branch 2.1.x to hidden.

🇺🇸United States loze

#25 was no longer applying with the latest 2.1.x updates. This MR40 is the patch from #25 with the merge errors resolved.

🇺🇸United States loze

This latest MR 36 should get this working with the latest updates to 2.1.x
Ignore MR19

🇺🇸United States loze

Thanks for the insight @marcofernandes.
I think this is pretty solid now. Still not addressing revisions, though.
But it appears to be working pretty good. The latest changes requires running another updb because I made some edits to the usage table.

🇺🇸United States loze

Ok, so I think I got this pretty much there and was able to work out some of my questions.

This latest MR does the following

  • Adds a update hook to create a table to track block usage
  • Adds a update hook to batch process all existing Gutenberg nodes and create usage records for any blocks being used.
  • Changes my original route for cloning a node, to one that checks the usage and clones it if it needs to, returning the block Id
  • Cleans up the javascript filter detecting the duplicates

I still need to

  • Clean up orphaned blocks on cron
  • Address updating block ids when programmatically cloning an entire node.

Bigger picture:
What to do about node revisions, that feels like a separate undertaking full of gotchas.

It appears to be working well from my initial tests. Be sure to run updb when testing.

🇺🇸United States loze

I think a table that tracks usage makes sense. something with fields like: entity_type, entity_id, block_type, block_id, created_timestamp

With this we could do the following:

  • Change the editor/content_block/clone/[ID] path (that this MR currently adds) to editor/content_block/check_usage/[NODE_ID]/[BLOCK_ID].
    This would check against the usage table if the block is used in any other nodes and duplicate the block it if it is and return the new block id.
  • on saving of the node, we would parse the body and write all the used contentBlockIds to the table, and delete all the records for contentBlockIds on that node that arent used.
  • When a node is cloned programmatically (is new) check that any contentBlockIds arent being used in another node and clone them if they are
  • Then on cron we can delete orphaned blocks older than a certain timestamp

This would address several of the issues I raised but still not deal with revisions, which could be addressed later.

🇺🇸United States loze

This is my first stab at the initial issue.
See my comment in content-blocks.jsx, I'm not sure how to best handle this. Any thoughts?

    // @todo This doesn't feel safe. Someone can just hit the url editor/content_block/clone/[ID] and clone a block.
    //  Maybe csrf token is the way to protect against it, but I dont know how to get it in javascript.
    //  Also, as it is now, this will clone any block, even if its not a type that is used in gutenberg.
    //  Maybe we should also pass the node type, and check that this block type is enabled in gutenberg for this
    //  node type?
🇺🇸United States loze

What about node revisions? Do we want to make revisions of the content blocks as well that correspond to the node revisions?
Or at least not delete blocks that are present in a revision.

ehh, theres a lot to consider here.

Anyway, I have something somewhat working that handles the original issue, of cloning a block when it is copy/pasted/duplicated in a single node. That I will push up in a bit.

🇺🇸United States loze

My last branch got screwed up this MR35 should work with 2.1.x. Ignore the previous one.

🇺🇸United States loze

loze changed the visibility of the branch 3163074-support-html-list to hidden.

🇺🇸United States loze

Perhaps we need to track content block usage in a custom table? This way, if a contentBlockId used in a node appears in another node, a duplicate is created, and they can be edited independently.

This would also allow us to clean up orphaned blocks on cron also. Consider someone adding a block in a node, not saving the node, deleting the block, then saving the node. That block would still exist in the db.

Some effort is made to delete unused blocks on node save, where we compare the old body field to the new body field and delete any blocks that were detected there, but in this case the deleted block was never saved in the body field.

🇺🇸United States loze

Also, what if a node it cloned completely? Editing a block on one would affect the other.

🇺🇸United States loze

I think that was the way to go. I have this working on the frontend. But it still loads the local path in the editor.
I also changed the image styles 'full' key to '_original_'

🇺🇸United States loze

I think the answer is to make an imageBlockProcessor that regenerates the image url. Since it has already been viewed the first time in the editor, it presumably was pushed to s3 already, and getting the url the second time from the file entity thats stored in the block should get the s3 url.
Then replace the image url in the src with this new url.

Does this make sense? would this be the correct place to do this?

If I go back into the node and switch the style and then switch back to what it was previously, it has the s3 url. Its just not getting it when it renders on the front end, or when it renders in the editor the 2nd time (unless you do what I described)

🇺🇸United States loze

My MR does the following:

  • adds the permission 'create and edit custom gutenberg content blocks' for all content block types in the editor so it does not need ot rely on the layout_builder permission
  • Shows a warning message to the user if they do not have permission
  • removes the submit button on the form if they do not have permission
  • Gets rid of the error messages if they submit the node with no contentBlockId
🇺🇸United States loze

Digging into this, I see that we are checking for 'create and edit custom blocks' as a permission to show the form.
This permission is provided by layout_builder which may not necessarily be installed (In my case is wasn't).

This module should either provided its own permission 'gutenberg create and edit custom block_content' ?
or possibly check the $block->access('update') on the individual block.

🇺🇸United States loze

We are also going to run into an issue when a block is copy/pasted or added manually in the code editor. Im not sure the best approach here.

Maybe we can show a warning if a content block has the same ID as another on the same page, with a button to create a duplicate, wich would clone the block entity and rebuild the preview.

🇺🇸United States loze

I can take a stab at doing this, but I'm unsure how to hook into Gutenberg's duplicate functionality. (act when a block is duplicated) If someone can point me in the right direction, I can work on this.

🇺🇸United States loze

This should also render the block using the front end theme templates. Right now it doesn't that yet.

🇺🇸United States loze

This also does not add any sort of required indicator. I needed something quick that prevented people from trying to save nodes with no titles.

🇺🇸United States loze

loze made their first commit to this issue’s fork.

🇺🇸United States loze

I dug around a little in this and realized that the libraries wernt being included because renderContentBlock() was returning a plain json response with the rendered html only and no libraries.

I switched this to return an ajaxResponse and populate the block in the editor with drupals ajax commands since that has the benifit of including any attached libraries in the render array

It probably needs some cleaning up, but it seems to be working from my initial testing

🇺🇸United States loze

loze changed the visibility of the branch 3449711-libraries-attached-to to active.

🇺🇸United States loze

loze changed the visibility of the branch 3449711-libraries-attached-to to hidden.

🇺🇸United States loze

Thanks for adding this. There is another instances where this is occurring and Im getting the same error. I think it also needs to go into blocksController.php.

These two patches cleared it up for me.

🇺🇸United States loze

I'm still seeing this on my end.

Im using Drupal: 10.2.6, Php 8.2.0
With the latest dev 3.x version of guttenberg

The error happens on the 2 different block types I was testing on, both the default "basic block" type and a custom block type that's just an entityreference and title.

both block types only have the default view mode, the default view mode is selected in the gutenberg edit widget when adding the block.

The block is created in guttenberg w/o any errors, but I get the errors when viewing it on the front end.

It's a fairly straitforward set up. My Blocks work fine when I place them normally.

Digging in little further I see that in contentBockProcessor.php the only key in the #configuration section of the block render array is 'provider'
block_content_theme_suggestions_block_alter() expects the 'view_mode' key to be present (even if its empty)

It does feel like there should be other config variables here too though, for instance the block title, no?

Nonetheless, this patch adds the view mode and makes hte error go away.

🇺🇸United States loze

Thanks.

I was able to do this following the register-filters.jsx example in the gutenberg_starter theme, which seems to do the trick.

((Drupal, wp) => {
  const {t} = Drupal;
  const {hooks, blockEditor} = wp;
  const {addFilter} = hooks;
  const {BlockControls} = blockEditor;


  /**
   * This filter will alter image block by removing its styles.
   */
  addFilter(
    'blocks.registerBlockType',
    'MYTHEME/remove-image-block-styles',
    (settings, name) => {

      if (name === "core/image") {
        return {
          ...settings,
          styles: []
        };
      }
      else {
        return settings;
      }
    },
  );
})(Drupal, wp);
🇺🇸United States loze

Confirmed. We have been using #14 for some time now with no errors.

🇺🇸United States loze

It appears I was missing my sitemapxml.settings config from a previous import and saving the form did not create it. I fixed it by importing sitemapxml.settings.yml from a backup and it started working again

🇺🇸United States loze

Here is my config

_config_id: node.type.test
uuid: d0b797fb-8d88-4d1a-8f4b-47a26f109d1c
langcode: en
status: true
dependencies:
  module:
    - menu_ui
    - node_form_overrides
third_party_settings:
  menu_ui:
    available_menus:
      - main
    parent: 'main:'
  node_form_overrides:
    insert_button: Save
    update_button: Update
    insert_title: 'Add new [node:content-type:name]'
    update_title: 'Edit this [node:content-type:name]'
    delete_form_title: 'Are you sure you want to delete this [node:content-type:name]?'
    delete_form_description: 'This action cannot be undone.'
name: Test
type: test
description: ''
help: ''
new_revision: true
preview_mode: 1
display_submitted: true

_config_id: core.entity_form_display.node.test.default
uuid: bab49af5-943a-4742-a90a-f1474a1f5709
langcode: en
status: true
dependencies:
  config:
    - field.field.node.test.field_images2
    - node.type.test
  module:
    - content_moderation
    - extra_field_description
    - file_uploader_uppy
    - hide_revision_field
    - path
    - publication_date
    - text
id: node.test.default
targetEntityType: node
bundle: test
mode: default
content:
  created:
    type: datetime_timestamp
    weight: 10
    region: content
    settings: {  }
    third_party_settings: {  }
  field_images2:
    type: file_uploader_uppy
    weight: 122
    region: content
    settings:
      options:
        instance:
          autoProceed: false
        plugin:
          showProgressDetails: false
          hideCancelButton: false
          hideProgressAfterFinish: false
          singleFileFullScreen: true
          disableStatusBar: false
          disableInformer: false
          disableThumbnailGenerator: false
          waitForThumbnailsBeforeUpload: false
          thumbnailWidth: 200
          enableImageEditor: false
          autoOpenFileEditor: false
          imageEditor:
            actions: {  }
          thumbnailHeight: 200
          theme: light
        uploader:
          method: xhr
      progress_indicator: throbber
    third_party_settings:
      extra_field_description:
        extra_description: ''
  moderation_state:
    type: moderation_state_default
    weight: 100
    region: content
    settings: {  }
    third_party_settings: {  }
  path:
    type: path
    weight: 30
    region: content
    settings: {  }
    third_party_settings: {  }
  promote:
    type: boolean_checkbox
    weight: 15
    region: content
    settings:
      display_label: true
    third_party_settings: {  }
  published_at:
    type: publication_date_timestamp
    weight: 10
    region: content
    settings: {  }
    third_party_settings: {  }
  revision_log:
    type: hide_revision_field_log_widget
    weight: 80
    region: content
    settings:
      rows: 5
      placeholder: ''
      show: true
      default: ''
      permission_based: false
      allow_user_settings: true
      hide_revision: false
    third_party_settings: {  }
  status:
    type: boolean_checkbox
    weight: 120
    region: content
    settings:
      display_label: true
    third_party_settings: {  }
  sticky:
    type: boolean_checkbox
    weight: 16
    region: content
    settings:
      display_label: true
    third_party_settings: {  }
  title:
    type: string_textfield
    weight: -5
    region: content
    settings:
      size: 60
      placeholder: ''
    third_party_settings: {  }
  uid:
    type: entity_reference_autocomplete
    weight: 5
    region: content
    settings:
      match_operator: CONTAINS
      match_limit: 10
      size: 60
      placeholder: ''
    third_party_settings: {  }
  url_redirects:
    weight: 50
    region: content
    settings: {  }
    third_party_settings: {  }
hidden: {  }

_config_id: field.storage.node.field_images2
uuid: e69f741f-fd96-466c-a962-a4d0ce11d38e
langcode: en
status: true
dependencies:
  module:
    - field_permissions
    - file
    - image
    - node
third_party_settings:
  field_permissions:
    permission_type: public
id: node.field_images2
field_name: field_images2
entity_type: node
type: image
settings:
  target_type: file
  display_field: false
  display_default: false
  uri_scheme: public
  default_image:
    uuid: ''
    alt: ''
    title: ''
    width: null
    height: null
module: image
locked: false
cardinality: -1
translatable: true
indexes: {  }
persist_with_no_fields: false
custom_storage: false

_config_id: field.field.node.test.field_images2
uuid: f152d738-0f04-41bb-a823-15e5c0284314
langcode: en
status: true
dependencies:
  config:
    - field.storage.node.field_images2
    - node.type.test
  module:
    - image
id: node.test.field_images2
field_name: field_images2
entity_type: node
bundle: test
label: Images2
description: ''
required: false
translatable: false
default_value: {  }
default_value_callback: ''
settings:
  handler: 'default:file'
  handler_settings: {  }
  file_directory: '[date:custom:Y]-[date:custom:m]'
  file_extensions: 'png gif jpg jpeg webp'
  max_filesize: ''
  max_resolution: ''
  min_resolution: ''
  alt_field: true
  alt_field_required: false
  title_field: true
  title_field_required: false
  default_image:
    uuid: ''
    alt: ''
    title: ''
    width: null
    height: null
field_type: image

🇺🇸United States loze

I'm not sure if this is the optimal way to do this, but the patch here does fix the issue for me.

Alternatively, maybe this should happen in viewElements of the field formatter, instead of always creating a vote entity of type 'vote'?

🇺🇸United States loze

it appears the form is being built with an empty vote entity of bundle type 'vote' instead of loading the current users vote.

🇺🇸United States loze

Yes this appears to be fixed now. Thanks!

🇺🇸United States loze

loze changed the visibility of the branch 3443015-call-to-a to hidden.

🇺🇸United States loze

the regex in #16 still failed in some cases. Try this one, It seems to work.
'#(<p>|\n|^)?(https?://[^\s<]+)(</p>|\n|$)?#'

🇺🇸United States loze

I think is regex should work
'#(<p>|\n|^)(https?://\S+)(</p>|\n|$)#'

This works with ckeditor and without in my testing when urls are on their own line.
It also works for Peter Törnstrand's use case when it is the only text in the textarea.

🇺🇸United States loze

After further testing testing these latests commit, the regex still fails in a few places

in particular the url inside the tag gets converted to a video in the following example.
<a href="https://www.youtube.com/watch?v=CsGQOPLGImA">https://www.youtube.com/watch?v=CsGQOPLGImA</a>

Also some urls that do not have an enabled provider are mangled. for example:
the website <a href="https://drupal.org"><em>Drupal</em></a>
displays broken html, see screenshot

Production build 0.69.0 2024