Wrap element with in any number of elements with PHP

I am working on a WordPress child theme where I do not have access to any markup other than the header.php. (I have access to child functions.php and the style.css)

The site has a body and a div#wrapper, but I would really like there to be 1 or 2 divs between those because I don’t want to use body to create a column and currently, the only way to wrangle the whacky markup would be with the body. I would like to get a div that actually wraps the page contents in this case.

<html>
  <body>
   <section class="NEW-WRAPPING-ELEMENT">
     <div id='wrapper'>
       ...
     </div>
     <div id="footer'></div>
     <div id="other'></div>
   </section>
  </body>
</html>

This markup probably worked just fine in most cases with a classic 960px absolutely positioned layout, but it’s hard to work with when you want a malleable responsive layout.

I can use JavaScript and wrap them on page load, but it seems like it would be better to build it on the server – since I’m using PHP anyway. ALSO, you can see the flash of styling when the .master wrapper kicks in. No good!

I am removing p tags from images and wrapping things like inline images with a figure with preg_wrap. Can I / should I – use a similar technique to ‘wrap’ my everything in the body with another div? I do not know regex at all. I hacked this together but no go so far. Thoughts???

function wrap_wrapper( $content ) {
    // A regular expression of what to look for.
    $pattern = '/<body>(.*?)<\/body>/i';
    // What to replace it with. $1 refers to the content in the first 'capture group', in parentheses above
    $replacement="<section class="new-master">$1</section>";
    return preg_replace( $pattern, $replacement, $content );
}
add_filter( 'the_content', 'wrap_wrapper' );

Here is a CodePen with full markup example of what I have to work with:

2 Answers
2

Can I use a similar technique to ‘wrap’ my everything in the body with another div?

Absolutely. Almost everything is possible. But you’re going to have to do something a little hackish.

The the_content filter doesn’t actually filter the content of the entire page. That particular filter is used throughout WordPress to filter a variety of different contents.

Unfortunately, there isn’t a good way to filter the entire page.

One way to accomplish this would be to use ob_start() and ob_get_clean() attached to appropriate hooks. We need to hook into before anything is output to the page and start an output buffer. Then we need to hook in at the last possible moment and get the buffer.

Then we can do something with the content. Your regex was close, but not quite right.

In your functions.php, add the following:

//* Hook into WordPress immediately before it starts output
add_action( 'wp_head', 'wpse_wp', -1 );
function wpse_wp() {

  //* Start out buffering
  ob_start();

  //* Add action to get the buffer on shutdown
  add_action( 'shutdown', 'wpse_shutdown', -1 );
}

function wpse_shutdown() {

  //* Get the output buffer
  $content = ob_get_clean();

  //* Do something useful with the buffer

  //* Use preg_replace to add a <section> wrapper inside the <body> tag
  $pattern = "/<body(.*?)>(.*?)<\/body>/is";
  $replacement="<body$1><section class="new-master">$2</section></body>";

  //* Print the content to the screen
  print( preg_replace( $pattern, $replacement, $content ) );
}

Should I use a similar technique to ‘wrap’ my everything in the body with another div?

It depends. A better, faster way to accomplish this would be to edit the template files. Since you state that you don’t have access to the template files, then I believe that something like this would be your only option.

Leave a Comment