{"id":6018,"date":"2020-08-18T16:29:22","date_gmt":"2020-08-18T14:29:22","guid":{"rendered":"https:\/\/florianbrinkmann.com\/en\/?p=6018"},"modified":"2020-08-18T16:29:25","modified_gmt":"2020-08-18T14:29:25","slug":"filtered-block-markup","status":"publish","type":"post","link":"https:\/\/florianbrinkmann.com\/en\/filtered-block-markup-6018\/","title":{"rendered":"wp_kses filters block markup for non-admin users"},"content":{"rendered":"\n<p>WordPress only allows admin users to save unfiltered HTML in the editor and removes elements for all other user roles that are not specified in a set of allowed elements and attributes. Disallowed elements and attributes, for example, are the <code>svg<\/code> element and the <code>sizes<\/code> attribute for the <code>img<\/code> element. That is a problem when markup generated by a block contains those elements or attributes and leads to interesting results.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>For example, if a block generates SVG code depending on user input, let us say a star rating for a review block, we get the following behavior: admin users can add and save the block without problems. Editors can save the block, but get an error when reloading the editor, because the block does not contain the expected markup (because the SVG stars were stripped from the markup).<\/p>\n\n\n\n<p>For me, that happened with a slider block that defines the <code>sizes<\/code> attribute for the <code>img<\/code> elements. The attribute is not part of the allowed attributes for the <code>img<\/code> element, so it is removed for all other roles than admin users.<\/p>\n\n\n\n<p>The problem can be fixed with the <code>wp_kses_allowed_html<\/code> filter, that gets an array of allowed tags and attributes, and the context, for example, <code>post<\/code> as the context of editing posts and pages. The following code snippet makes the <code>sizes<\/code> attribute an allowed attribute for the <code>img<\/code> element:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/**\n * Allow the img sizes attribute for non-admin backend users in editor.\n *\/<\/span>\nadd_filter( <span class=\"hljs-string\">'wp_kses_allowed_html'<\/span>, <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">( $allowed_tags, $context )<\/span> <\/span>{\n\t<span class=\"hljs-keyword\">if<\/span> ( $context !== <span class=\"hljs-string\">'post'<\/span> ) {\n\t\t<span class=\"hljs-keyword\">return<\/span> $allowed_tags;\n\t}\n\n\t<span class=\"hljs-comment\">\/\/ Add sizes attribute to img.<\/span>\n\t<span class=\"hljs-keyword\">if<\/span> ( <span class=\"hljs-keyword\">isset<\/span>( $allowed_tags&#91;<span class=\"hljs-string\">'img'<\/span>] ) ) {\n\t\t$allowed_tags&#91;<span class=\"hljs-string\">'img'<\/span>]&#91;<span class=\"hljs-string\">'sizes'<\/span>] = <span class=\"hljs-keyword\">true<\/span>;\n\t}\n\n\t<span class=\"hljs-keyword\">return<\/span> $allowed_tags;\n}, <span class=\"hljs-number\">10<\/span>, <span class=\"hljs-number\">2<\/span> );<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Now, also non-admin users can use the block with <code>sizes<\/code> attributes without problems.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WordPress only allows admin users to save unfiltered HTML in the editor and removes elements for all other user roles that are not specified in a set of allowed elements and attributes. Disallowed elements and attributes, for example, are the svg element and the sizes attribute for the img element. That is a problem when [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wpf_show_in_dewp_planet_feed":false,"flobn_post_versions":"","webmentions_disabled_pings":false,"webmentions_disabled":false,"lazy_load_responsive_images_disabled":false,"footnotes":""},"categories":[115],"tags":[],"class_list":["post-6018","post","type-post","status-publish","format-standard","hentry","category-wordpress-snippets"],"wp-worthy-pixel":{"ignored":false,"public":null,"server":null,"url":null},"wp-worthy-type":"normal","_links":{"self":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/6018","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/comments?post=6018"}],"version-history":[{"count":2,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/6018\/revisions"}],"predecessor-version":[{"id":6020,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/posts\/6018\/revisions\/6020"}],"wp:attachment":[{"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/media?parent=6018"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/categories?post=6018"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/florianbrinkmann.com\/en\/wp-json\/wp\/v2\/tags?post=6018"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}