Insert div between specific elements - php

I have previously built some html pages where several paragraphs are inside div and now i want to move it in WordPress to understand theming and the structure of the CMS but i have some issues to understand. For example, in the loop i can't just add the opening div at the starting point and the closing div at the end (obviously) because in the middle there are different elements wrapped in other div. For example, I wanted to take the last paragraph, create a wrapping div around it with a custom class and my solution was this. I am sure it is a totally messed up solution. What am I doing wrong?
// First function
function addDivLastP1( $content ) {
$pattern = '/[\s\S]*\K(<p>)/i';
// Here i adding the opening tag div. I close it later in another function
$replacement = '<div class="my_class">$1';
$content = preg_replace( $pattern, $replacement, $content );
return $content;
}
add_filter( 'the_content', 'addDivLastP1' );
// Second function
function addDivLastP2( $content ) {
$pattern = '/[\s\S]*\K(<\/p>)/i';
// Closing div previously open
$replacement = '</div>';
$content = preg_replace( $pattern, $replacement, $content );
return $content;
}
add_filter( 'the_content', 'addDivLastP2' );

It is not a good idea to parse HTML (or any XML) by regexp.
In your case much better use DOMDocument:
function addDivLastP( $content ) {
$doc = new DOMDocument();
if(!$doc->loadHTML($content)) {
// cannot parse HTML content
return $content;
}
for($i = $doc->childNodes->count()-1; $i >= 0; $i--) {
$child = $doc->childNodes[$i];
if ($child->nodeName === 'p') { // got last paragraph inside root node
$div = $doc->createElement('div');
// replace paragraph by new empty div
$doc->replaceChild($div, $child);
// insert paragraph inside div
$div->appendChild($child);
return $doc->saveHTML();
}
}
return $content;
}

Related

Get DIV content by specific string

I like the solution from Get DIV content from external Website, but I need to find the value from a DIV class which contains a specific string, like in my case btx764839 (for example). The name of the div class is not that string alone but <div class="dark btx764839">76</div> for example.
I need the script to search for the DIV that contains btx764839 and then refer to that specific one. I've been trying many different things with strpos();, without success. Below the script I found on the other post (without my adjustments). I would appreciate some help. Thank you very much!
$url = 'url';
$content = file_get_contents($url);
$first_step = explode( '<div class="dark btx764839">' , $content );
$second_step = explode("</div>" , $first_step[1] );
echo $second_step[0];
This is my latest attempt:
$url = 'url';
$content = file_get_contents($url);
foreach($content as $div) {
// Loop through the DIVs looking for one withan id of "content"
// Then echo out its contents (pardon the pun)
// get class attribute of a div, it's a string
$class = $div->getAttribute('class');
// find substring 'btx764839' in $class
if (strpos($class, 'btx764839') !== false) {
echo $div->nodeValue;
}
}
Code taken from provided example:
foreach($divs as $div) {
// Loop through the DIVs looking for one withan id of "content"
// Then echo out its contents (pardon the pun)
// get class attribute of a div, it's a string
$class = $div->getAttribute('class');
// find substring 'btx764839' in $class
if (strpos($class, 'btx764839') !== false) {
echo $div->nodeValue;
}
}

PHP separate paragraph

I am writing a code for wordpress to separate paragraph using PHP. The objective is to split the content of the post into an array and echo them accordingly.
Here are my code
<?php
$content = "<p>123</p> <p>456</p> <p>789</p>"
$p = explode("</p>", $content);
$i=0;
//echo first 2 elements
foreach ($p as $para) {
echo $para;
array_shift($p); //remove the first element
$i++; //increase the element count by 1
if ($i == 2){ break;} //if element has reach 2 meaning second paragraph, stop loop.
}
echo "<br>Break here<br>";
//echo the rest of the element
foreach ($p as $para) {
echo $para;
}
?>
Replace this
$content = "<p>123</p> <p>456</p> <p>789</p>"
With the following
$content = apply_filters( 'the_content', get_the_content() );
$content = str_replace( ']]>', ']]>', $content );
to retrieve the content of the post with paragraph tag.
I am able to achieve my result but I am just worry of the consequences such as system overload.
If i understand correctly, what you're trying to accomplish, is adding a couple of <br> tags after the first two paragraphs?
If so, this can be done alot simpler using the preg_replace method:
$content = "<p>123</p> <p>456</p> <p>789</p>";
echo preg_replace('/<\/p>/', '</p><br><br>', $content, 2);

PHP Preg Replace - Match String with Space - Wordpress

I'm trying to scan my wordpress content for:
<p><span class="embed-youtube">some iframed video</span></p>
and then change it into:
<p class="img_wrap"><span class="embed-youtube">some iframed video</span></p>
using the following code in my function.php file in my theme:
$classes = 'class="img_wrap"';
$youtube_match = preg_match('/(<p.*?)(.*?><span class="embed-youtube")/', $content, $youtube_array);
if(!empty($youtube_match))
{
$content = preg_replace('/(<p.*?)(.*?><span class=\"embed-youtube\")/', '$1 ' . $classes . '$2', $content);
}
but for some reason I am not getting a match on my regex nor is the replace working. I don't understand why there isn't a match because the span with class embed-youtube exists.
UPDATE - HERE IS THE FULL FUNCTION
function give_attachments_class($content){
$classes = 'class="img_wrap"';
$img_match = preg_match("/(<p.*?)(.*?><img)/", $content, $img_array);
$youtube_match = preg_match('/(<p.*?)(.*?><span class="embed-youtube")/', $content, $youtube_array);
// $doc = new DOMDocument;
// #$doc->loadHTML($content); // load the HTML data
// $xpath = new DOMXPath($doc);
// $nodes = $xpath->query('//p/span[#class="embed-youtube"]');
// foreach ($nodes as $node) {
// $node->parentNode->setAttribute('class', 'img_wrap');
// }
// $content = $doc->saveHTML();
if(!empty($img_match))
{
$content = preg_replace('/(<p.*?)(.*?><img)/', '$1 ' . $classes . '$2', $content);
}
else if(!empty($youtube_match))
{
$content = preg_replace('/(<p.*?)(.*?><span class=\"embed-youtube\")/', '$1 ' . $classes . '$2', $content);
}
$content = preg_replace("/<img(.*?)src=('|\")(.*?).(bmp|gif|jpeg|jpg|png)(|\")(.*?)>/", '<img$1 data-original=$3.$4 $6>' , $content);
return $content;
}
add_filter('the_content','give_attachments_class');
Instead of using regex, make effective use of DOM and XPath to do this for you.
$doc = new DOMDocument;
#$doc->loadHTML($html); // load the HTML data
$xpath = new DOMXPath($doc);
$nodes = $xpath->query('//p/span[#class="embed-youtube"]');
foreach ($nodes as $node) {
$node->parentNode->setAttribute('class', 'img_wrap');
}
echo $doc->saveHTML();
Here is a quick and dirty REGEX I did for you. It finds the entire string starting with p tag, ending p tag, span also included etc. I also wrote it to include single or double quotes for you since you never know and also to include spaces in various places. Let me know how it works out for you, thanks.
(<p )+(class=)['"]+img_wrap+['"](><span)+[ ]+(class=)+['"]embed-youtube+['"]>[A-Za-z0-9='" ]+(</span></p>)
I have tested it on your code and a few other variations and it works for me.

Remove entire div tag contents turn into a function

What I'm seeking to do is find an elegant solution to remove the contents of everything between a certain class = i.e. you want to remove all the HTML in the sometestclass class using php.
The function below works somewhat - not that well - it removes some parts of the page I don't want removed.
Below is a function based on an original post (below):
$html = "<p>Hello World</p>
<div class='sometestclass'>
<img src='foo.png'/>
<div>Bar</div>
</div>";
$clean = removeDiv ($html,'sometestclass');
echo $clean;
function removeDiv ($html,$removeClass){
$dom = new DOMDocument;
$dom->loadHTML( $html );
$xpath = new DOMXPath( $dom );
$removeString = ".//div[#class='$removeClass']";
$pDivs = $xpath->query($removeString);
foreach ( $pDivs as $div ) {
$div->parentNode->removeChild( $div );
}
$output = preg_replace( "/.*<body>(.*)<\/body>.*/s", "$1", $dom->saveHTML() );
return $output;
}
does anyone have any suggestions to improve the results of this?
the original post is here
You are not quoting the class name:
$removeString = ".//div[#class=$removeClass]";
should be:
$removeString = ".//div[#class='$removeClass']";

Convert clickable anchor tags to plain text in html document

I am trying to match <a> tags within my content and replace them with the link text followed by the url in square brackets for a print-version.
The following example works if there is only the "href". If the <a> contains another attribute, it matches too much and doesn't return the desired result.
How can I match the URL and the link text and that's it?
Here is my code:
<?php
$content = 'This is a text link';
$result = preg_replace('/<a href="(http:\/\/[A-Za-z0-9\\.:\/]{1,})">([\\s\\S]*?)<\/a>/',
'<strong>\\2</strong> [\\1]', $content);
echo $result;
?>
Desired result:
<strong>This is a text link </strong> [http://www.website.com]
You should be using DOM to parse HTML, not regular expressions...
Edit: Updated code to do simple regex parsing on the href attribute value.
Edit #2: Made the loop regressive so it can handle multiple replacements.
$content = '
<p>This is a text link</p>
bah
I wont change
';
$dom = new DOMDocument();
$dom->loadHTML($content);
$anchors = $dom->getElementsByTagName('a');
$len = $anchors->length;
if ( $len > 0 ) {
$i = $len-1;
while ( $i > -1 ) {
$anchor = $anchors->item( $i );
if ( $anchor->hasAttribute('href') ) {
$href = $anchor->getAttribute('href');
$regex = '/^http/';
if ( !preg_match ( $regex, $href ) ) {
$i--;
continue;
}
$text = $anchor->nodeValue;
$textNode = $dom->createTextNode( $text );
$strong = $dom->createElement('strong');
$strong->appendChild( $textNode );
$anchor->parentNode->replaceChild( $strong, $anchor );
}
$i--;
}
}
echo $dom->saveHTML();
?>
You can make the match ungreedy using ?.
You should also take into account there may be attributes before the href attribute.
$result = preg_replace('/<a [^>]*?href="(http:\/\/[A-Za-z0-9\\.:\/]+?)">([\\s\\S]*?)<\/a>/',
'<strong>\\2</strong> [\\1]', $content);

Categories