Didn't realize there was already an issue for this.
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.
loze → changed the visibility of the branch 3178212-check-rebuild-access to hidden.
+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.
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.
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)
this is fixed in 💬 You have requested a non-existent service "entity.manager" Fixed
Apologies for all the chatter here, but I think I got all the formatting issues resolved. The pipeline checks pass now.
Apologies for all the chatter here, but I think I got all the formatting issues resolved. The pipeline checks pass now.
#25 was no longer applying with the latest 2.1.x updates. This MR40 is the patch from #25 with the merge errors resolved.
This latest MR 36 should get this working with the latest updates to 2.1.x
Ignore MR19
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.
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.
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.
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?
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.
great work!
My last branch got screwed up this MR35 should work with 2.1.x. Ignore the previous one.
loze → changed the visibility of the branch 3163074-support-html-list to hidden.
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.
Also, what if a node it cloned completely? Editing a block on one would affect the other.
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_'
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)
loze → changed the visibility of the branch 1.1.x to hidden.
loze → created an issue.
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
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.
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.
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.
This should also render the block using the front end theme templates. Right now it doesn't that yet.
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.
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
loze → changed the visibility of the branch 3449711-libraries-attached-to to active.
loze → changed the visibility of the branch 3449711-libraries-attached-to to hidden.
sorry wrong patch, this is the right one.
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.
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.
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);
Confirmed. We have been using #14 for some time now with no errors.
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
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
+1 for #19 thanks
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'?
it appears the form is being built with an empty vote entity of bundle type 'vote' instead of loading the current users vote.
Yes this appears to be fixed now. Thanks!
loze → created an issue.
Heres a patch
Yea, I think the message is good.
Thanks!
the regex in #16 still failed in some cases. Try this one, It seems to work.
'#(<p>|\n|^)?(https?://[^\s<]+)(</p>|\n|$)?#'
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.
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