I needed to override one of the theme TwentyTwentyTwo template from a custom plugin, and I wanted to use one of Gutenberg's blocks.
I see that in the templates files blocks are used by just writing the corresponding html comment.
So I tried editing the template/single.html file in
<!-- wp:post-title /-->
<!-- wp:custom-block-i-defined /-->
<!-- fest -->
<div>Test</div>
and created a file plugin.template.html with the same content in my plugin.
When I visit a single page with the theme's template, it renders the blocks fine, but if I do so using
add_filter( 'template_include', 'override_template' );
function override_template( string $template ) {
return 'path/to/the/plugin.template.html';
}
the rendered page only contains the Fest div, but inspecting the page reveals the comments that didn't become blocks.
Am I using a wrong filter? Should I call some function to "hydrate" the blocks?
Similarly, I wanted to deliver an archive HTML template in my plugin. So I hope this helps.
The filter template_include didn't cut it and after running debug and tracing the template loading route I found a solution with the filter get_block_templates.
Here's a simplified version of the key parts of my plugin code:-
public function setup() {
add_filter( 'get_block_templates', array( $this, 'manage_block_templates' ), 10, 3 );
}
public function manage_block_templates( $query_result, $query, $template_type ) {
$theme = wp_get_theme();
$template_contents = file_get_contents( plugin_dir_path( __DIR__ ) . 'templates/archive-ale.html' );
$template_contents = str_replace( '~theme~', $theme->stylesheet, $template_contents );
$new_block = new WP_Block_Template();
$new_block->type = 'wp_template';
$new_block->theme = $theme->stylesheet;
$new_block->slug = 'archive-ale';
$new_block->id = $theme->stylesheet . '//archive-ale';
$new_block->title = 'archive-ale';
$new_block->description = '';
$new_block->source = 'custom';
$new_block->status = 'publish';
$new_block->has_theme_file = true;
$new_block->is_custom = true;
$new_block->content = $template_contents;
$query_result[] = $new_block;
return $query_result;
}
When the template was in the template folder of the child theme the render was fine, but from inside the plugin I had to force the theme name into the template. To avoid the header and footer failing to display. I was getting
Template part has been deleted or is unavailable: header
Hence the str_replace.
Using this method means I can just deploy a plugin and be totally theme agnostic, but I now can't edit the template from the site editor. The template needs to be in the theme folder to do that.
My archive-ale.html template:
<!-- wp:template-part {"slug":"header","tagName":"header","theme":"~theme~"} /-->
<!-- wp:group {"layout":{"inherit":true}} -->
<div class="wp-block-group"><!-- wp:query-title {"type":"archive","align":"wide","style":{"typography":{"fontSize":"clamp(2.75rem, 6vw, 3.25rem)"},"spacing":{"margin":{"bottom":"6rem"}}}} /-->
<!-- wp:query {"query":{"perPage":2,"pages":0,"offset":0,"postType":"post","categoryIds":[],"tagIds":[],"order":"desc","orderBy":"date","author":"","search":"","exclude":[],"sticky":"","inherit":true},"tagName":"main","align":"wide","layout":{"inherit":false}} -->
<main class="wp-block-query alignwide"><!-- wp:post-template {"align":"wide"} -->
<!-- wp:post-title {"isLink":true,"align":"wide","style":{"typography":{"fontStyle":"normal","fontWeight":"300"}},"fontSize":"var(--wp--custom--typography--font-size--huge, clamp(2.25rem, 4vw, 2.75rem))"} /-->
<!-- My block -->
<!-- wp:multiple-blocks-plugin/hero /-->
<!-- wp:columns {"align":"wide"} -->
<div class="wp-block-columns alignwide"><!-- wp:column {"width":"650px"} -->
<div class="wp-block-column" style="flex-basis:650px"><!-- wp:post-excerpt /-->
<!-- wp:post-date {"format":"F j, Y","isLink":true,"style":{"typography":{"fontStyle":"italic","fontWeight":"400"}},"fontSize":"small"} /--></div>
<!-- /wp:column -->
<!-- wp:column {"width":""} -->
<div class="wp-block-column"></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->
<!-- wp:spacer {"height":112} -->
<div style="height:112px" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
<!-- /wp:post-template -->
<!-- wp:query-pagination {"paginationArrow":"arrow","align":"wide","layout":{"type":"flex","justifyContent":"space-between"}} -->
<!-- wp:query-pagination-previous {"fontSize":"small"} /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next {"fontSize":"small"} /-->
<!-- /wp:query-pagination --></main>
<!-- /wp:query --></div>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} /-->
My solution, above, is one way to ADD an HTML template residing in the plugin folders.
To override an existing theme template use the same filter but find the template slug to override and then overwrite the content property, or remove it completely from the array and append your new one.
I'm still wondering if a template from a plugin should really be copied to the theme template folder on activation so that the user can then use the site editor to make further modifications.
Related
Thanks for taking the time to read my question.
I have a problem adding the message and message status blocks in my content region using Drupal 9. I'm using a custom theme.
The blocks are simply not displayed. They are not even added to the DOM.
Here is my block configuration : https://imgur.com/gPvEq1Q (Sorry, it's in French. The two blocks are underlined in red)
And the configuration of each block : https://imgur.com/q3cBToL and https://imgur.com/hePdhHn (again, in French, but there are no restriction on page, role or type of content - it should appear everywhere)
I found these solutions online :
1 - https://www.drupal.org/forum/support/theme-development/2016-03-08/d8-any-reason-why-blocks-arent-renderingdisplaying
I tried uninstalling my theme, clearing the cache, reinstalling my theme but it doesn't work. The blocks did not appear in the Bartik theme either.
2 - https://www.drupal.org/forum/support/post-installation/2018-09-23/new-blocks-not-displaying
I tried adding a simple test block, it appears normally.
I tried displaying a test message using $this->messenger()->addMessage("test"); in a module to be sure there was something to display but with no success.
I'm not sure if it helps but here is my page.twig template :
<header aria-label="Site header" class="header" id="header" role="banner">
<div id='header-content'>
<div id="header-left">
{{ page.branding }}
{{ page.navigation }}
</div>
<div id='header-right'>
{{ page.user_menu }}
{{ page.search }}
</div>
</div>
</header>
<section class="main" id="main">
<main aria-label="Site main content" class="content" id="content" role="main">
{{ page.content }}
</main>
</section>
<footer aria-label="Site footer" class="footer" id="footer" role="contentinfo">
<div class="footer--top">
{{ page.footer_first }}
</div>
<div class="footer--bottom">
{{ page.footer_bottom }}
</div>
</footer>
Does any of you already encountered the problem ? Is there a solution ?
Thanks again !
EDIT
Here is the output from twig debug :
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
* block--messages.html.twig
x block--system-messages-block.html.twig
* block--system.html.twig
* block.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/system/templates/block--system-messages-block.html.twig' -->
<div data-drupal-messages-fallback class="hidden"></div><span data-big-pipe-placeholder-id="callback=Drupal%5CCore%5CRender%5CElement%5CStatusMessages%3A%3ArenderMessages&args%5B0%5D&token=_HAdUpwWmet0TOTe2PSiJuMntExoshbm1kh2wQzzzAA"></span>
<!-- END OUTPUT from 'core/modules/system/templates/block--system-messages-block.html.twig' -->
This suggests that the \Drupal::messenger()->addMessage(); does not output any message.
A strange thing I noticed testing with a FormBase class is that the Drupal\Core\Form\FormStateInterface::setErrorByName() method is working fine. A message is being displayed and the twig debug output becomes
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'block' -->
<!-- FILE NAME SUGGESTIONS:
* block--cessoc-messages.html.twig
x block--system-messages-block.html.twig
* block--system.html.twig
* block.html.twig
-->
<!-- BEGIN OUTPUT from 'core/modules/system/templates/block--system-messages-block.html.twig' -->
<div data-drupal-messages-fallback class="hidden"></div>
<!-- THEME DEBUG -->
<!-- THEME HOOK: 'status_messages' -->
<!-- BEGIN OUTPUT from 'core/modules/system/templates/status-messages.html.twig' -->
<div data-drupal-messages>
<div role="contentinfo" aria-label="Message d'erreur">
<div role="alert">
<h2 class="visually-hidden">Message d'erreur</h2>
The title must be at least 5 characters long.
</div>
</div>
</div>
<!-- END OUTPUT from 'core/modules/system/templates/status-messages.html.twig' -->
<!-- END OUTPUT from 'core/modules/system/templates/block--system-messages-block.html.twig' -->
My problem is solved !
Like Kien Nguyen suggested, this was an issue caused by the BigPipe module not filling the message block with the status messages.
Apparently, this was because my theme contained a jQuery.js file which was outdated. I deleted it and everything work fine now.
I'm developping a Wordpress website, and I need to display conditionnal content in header file, just after opening body tag.
If I call exit(); just after my condition, the code is outputted correctly, so I know condition is working and I'm in the right file. Then I remove the call to exit(); and code is not outputted.
Theme is Divi / Divi-Child, I removed all plugins to be sure (renamed the plugins folder to _plugins), no cache in effect.
I looked at both functions.php and child/functions.php, I don't see any 'after content' functions that would clean/remove the code, although I suspect this is what's happening.
Even the HTML comments are striped ()
</head>
<body <?php body_class(); ?>>
<!-- Advertising -->
<?php
$bool = is_sidebar_active('wallpaper-advertising');
//var_dump($bool);
if($bool){
//exit();
?>
<script>
jQuery(document).ready(function($){
if(jQuery('#ad_habillage').length>0){
jQuery('#adbg, .wallpaper_spacer').show(0);
}else{
jQuery('body').addClass('deactivate_wallpaper');
}
});
</script>
<div id="adbg">
<?php dynamic_sidebar('wallpaper-advertising'); ?>
</div>
<div class="wallpaper_spacer" style="">
<img src="<?= THEME_PATH ?>/media/img/994x112Transparent.gif" border="0" alt="Cliquez ici" title="Cliquez ici">
</div>
<div class="big_wallpaper_wrap_bg">
<div class="big_wallpaper_wrap">
<?php } ?>
<!-- End Advertising -->
Any help is welcome.
I found out using QueryMonitor, it shows templates in use, and header.php was replaced by another file in the theme folder. I moved my code there and it's all fine.
I am trying to show .gif banner on a posts only within specific category after first paragraph in wordpress, so I my code in loop-single.php looks like:
<?php if(in_category('my_category')){ ?>
<script>
const par = document.querySelector('p');
par.insertAdjacentHTML('afterend', '<div><img src="some_gif" alt="" class=""></div>')
</script>
<?php } ?>
But it doesn't work as expected. Anyone have an idea? Or may be some other solution that not recquires installing additional plugins (not that I don't want to, most of them just slow the site down).
Thank you
edit: 'after first paragraph' added
So, I found a way, firstly I needed to check if the post is in wanted category, than create a function and call it afterwards. The code is set in single-loop.php file in my template:
<?php if(in_category('my-category')){ ?>
<script type="text/javascript">
function krasAd() {
const par = document.querySelector("p");
par.insertAdjacentHTML('afterend', '<div><img src="my-gif" alt="" class=""></div>')
};
krasAd();
</script>
<?php } ?>
There was also one way to check if you have a string in URL that only recquires JS. But it recquires you to have properly created URL structure, for example: domain.com/category/post
If I had category in my posts URL I would use code below, the code is set before closing footer tag in my single-loop.php template file:
<script type="text/javascript">
if (window.location.href.indexOf("my-string") > -1) {
const par = document.querySelector("p");
par.insertAdjacentHTML('afterend', '<div><img src="my-gif" alt="" class=""></div>')
}
</script>
I have next code inside contact form 7 editor
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
<div class="row">
<div class="col-sm-4">
[text* name class:border-field placeholder "Name"]
</div><!-- End of col -->
<div class="col-sm-4">
[email* email class:border-field placeholder "Email"]
</div><!-- End of col -->
<div class="col-sm-4">
[text subject class:border-field placeholder "Subject"]
</div><!-- End of col -->
</div><!-- ENd of row -->
</div><!-- End of col -->
</div><!-- ENd of row -->
<div class="row">
<div class="col-sm-8 col-sm-offset-2">
[textarea message class:border-field placeholder "Message"]
</div>
</div><!-- End of row -->
<div class="row text-center">
<div clas s="col-sm-12">
[submit class:btn class:btn-black-fill class:btn-small "Submit"]
</div><!-- End of col -->
</div><!-- End of row -->
The problem is that it adds random p tags almost after each element and also that first text field is for some reason little bit above other two fields when they should all be inline. And i think this is not css problem because previously i had this coded in plane HTML and all fields were inline so i think it must be something with contact form 7.
According to the Contact Form 7 Docs, you can disable "wpautop" for the plugin by placing the following constant in wp-config.php:
define( 'WPCF7_AUTOP', false );
If editing wp-config.php is not the solution for you, there's a handy filter. Put it in your functions.php:
// Remove <p> and <br/> from Contact Form 7
add_filter('wpcf7_autop_or_not', '__return_false');
I would like to say something about this, when we want reduce auto P tag form the we should go with below filter and just write blow code in function.php.
add_filter('wpcf7_autop_or_not', '__return_false');
I tried many answers but nothing worked so...
I ended up using simple CSS to specifically target empty P tags
in the form itself like this:
.wpcf7-form p:empty { display: none; }
This worked for me and, its a simple solution.
Add this in your functions.php file
function reformat_auto_p_tags($content) {
$new_content = '';
$pattern_full = '{(\[raw\].*?\[/raw\])}is';
$pattern_contents = '{\[raw\](.*?)\[/raw\]}is';
$pieces = preg_split($pattern_full, $content, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($pieces as $piece) {
if (preg_match($pattern_contents, $piece, $matches)) {
$new_content .= $matches[1];
} else {
$new_content .= wptexturize(wpautop($piece));
}
}
return $new_content;
}
remove_filter('the_content', 'wpautop');
remove_filter('the_content', 'wptexturize');
add_filter('the_content', 'reformat_auto_p_tags', 99);
add_filter('widget_text', 'reformat_auto_p_tags', 99);
Then on your post editor wrap your contact form 7 shortcode with raw shortcode
e.g.
[raw][contact-form-7 id="1" title="Contact Us"][/raw]
This works too. Tested with WordPress 5.7, PHP 7.4, Contact Form 7 v5.4.
<?php
add_filter('wpcf7_autop_or_not', false);
Potentially there are situations (old versions of WP, PHP?) where using the __return_false utility function is necessary.
I want to know how to set up a custom page template. My website is based on many different widths. example for some pages I use a div called <div class="content-wrap ninecol clearfix"> but for another page I use <div class="text-centered twelvecol clearfix">.
I need to create a template so that I can easy create new pages based on those templates.
Below is my static html code that Ive done in dreamweaver.
<div class="content-wrap ninecol clearfix"> <!--I want to make a template based on this div so I can just add new text in the future-->
<div class="content">
<h1 class="title">Om oss</h1>
<hr>
<div class="entry-content">
<h4>Vilka är Unified Sweden?</h4>
<p>Vi värnar starkt om vår unika företagskultur och ser den som vårt kraftfullaste
konkurrensmedel. Inom företaget har vi alltid arbetat hårt för att skapa den
stabila grund som vår företagskultur är byggd på. </p>
<p>All personal på Unified Sweden har många års erfarenhet av webbutveckling,
programmering, design och kundservice vilket gör oss unika då alla led inom kundbemötandet
vet exakt vad ni som företag behöver hjälp med.</p>
</div>
</div>
</div>
and this is what I came up with.
<?php
/*
Template Name: Test
*/
?>
<?php get_header(temp); ?>
<?php
// get_template_part( 'loop', 'index' );
?>
<div class="breadcrumbs">
<?php if(function_exists('bcn_display'))
{
bcn_display();
}?>
</div>
<?php if ( have_posts() ) : while ( have_posts() ) : the_post(); ?>
<?php the_content(); ?>
<?php endwhile; endif; ?>
</div><!-- content-wrap -->
</div><!-- #content -->
</div>
</div><!-- .main -->
<?php get_footer(); ?>
Thank you for any kind of help or support.
Are you saying that for each template you want a different style? If yes you need to give different name at div id and then you should edit your style.css
#namediv{ }
to setup custom page template (if i understand your question correctly)
you create your page template in the theme directory which is active
and use the header the way you did
<?php
/*
Template Name: Test
*/
?>
you replace Test by whatever you want to use for the name (this name can have space)
then in the admin, you can select the template to use for the page by going to Admin > Page Attributes > Templates
Your new custom template should appear here
edit (following op comment)
then you could check which template is being use with
is_page_template()
http://codex.wordpress.org/Function_Reference/is_page_template
from within the header.php that would then load a specific css file
side note: you might also want to check the codex page: http://codex.wordpress.org/Pages#Creating_Your_Own_Page_Templates as well as the dedicated wordpress stackexchange https://wordpress.stackexchange.com/
Template Name : Your page name
*/
you replace Test by whatever you want to use for the name (this name can have space) then in the admin, you can select the template to use for the page by going to Admin > Page Attributes > Templates Your new custom template should appear here