wordpress php content formatting - php

I added a custom php function to my wordpress template, where I want to echo the content of pages under a certain parent:
Departments
-department 1 (get the title and the content clean)
-department 2 (get the title and the content clean)
(...)
The code I have so far is not working as i want, the title is fine but I need to filter the content so I can grab only the text between the "<p>" tag. Is this possible? Thank you.
functions.php
function echo_childs_of( $postID ) {
$args = array(
'order' => 'ASC',
'post_parent' => $postID,
'post_status' => null,
'post_type' => 'any'
);
$page_childs = get_children( $args );
if ( $page_childs ) {
foreach ( $page_childs as $child ) {
$title = get_the_title( $child );
$content = get_the_content($child);
$content = strip_shortcodes( $content );
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
$content = strip_tags($content);
echo $title;
echo $content;
}
}
}
on my php page
echo_childs_of( 7 );

You could use DOM to find the p tag elements and itarate over them using a for cycle to do whatever it is that you want to do.
$content = get_the_content($child);
$doc = new DOMDocument();
#$doc->loadHTML($content);
$p_elements = $doc->getElementsByTagName('p');
foreach ($p_elements as $p) {
//Do something with the p element... Strip tags maybe?
}

Try this:
$content = get_the_content($child);
preg_match('/<p>(.*)<\/p>/', $content, $match);
$content = $match[1];

Related

WordPress replace all instances of [vc_single_image] shortcode with img src

im updating my WordPress website and removing the https://wpbakery.com/ editor and I'm wanting to remove the markup generated by the plugin.
This plugin https://codecanyon.net/item/shortcode-cleaner-clean-wordpress-content-from-broken-shortcodes/21253243 I'm using will remove all shortcodes with no problem except one. It's removing images.
On closer inspection images are posted on the backend using the below shortcode
[vc_single_image image="10879" img_size="large" add_caption="yes" alignment="center"]
And I want to update all references to use HTML instead
<img src="IMGURL">
However, I'm not sure about the right way to do it, any advice, please?
There is a regular expression replace in MySQL 8, but if you don't have that, you could do it with PHP.
$query = new WP_Query( [-- whatever posts you want--] );
while ( $query->have_posts() ) {
$query->the_post();
$content = get_the_content();
preg_match('/\[vc_single_image image="(\d+)" img_size="(\w+)"[^\]]*\]/', $content, $matches);
if( isset($matches[1]) ) {
$url = wp_get_attachment_image_url( (int) $matches[1], $matches[2] );
$img = sprintf( '<img src="%s" />', $url );
$new_content = str_replace( $matches[0], $img, $content );
wp_update_post( [ 'ID' => get_the_ID(), 'post_content' => $new_content] );
}
}
Here Is the updated answer to update all images in the post/page content. The above code finds the first image of the content and update that.
// Args for the WP_Query
$args = array(
'post_type' => 'post',
'posts_per_page' => 10,
'post__in' => array(5824),
'orderby' => 'post__in'
);
// Execute WP_Query with args
$query = new WP_Query( $args );
// Start the Loop
while ( $query->have_posts() ) {
$query->the_post();
// Get Page/Post content
$content = apply_filters('the_content', $content);
// Get the vc_single_image count from the post
$found_keyword = substr_count( $content,"vc_single_image" );
// Start loop to replace all elements from the content
for ($i=0; $i < $found_keyword; $i++) {
// Get the position of vc_single_image shortcode with Image ID and Image Size
preg_match( '/\[vc_single_image image="(\d+)" img_size="(\w+)"[^\]]*\]/', $content, $matches );
// Check shotcode are exist on loop
if( isset( $matches[1]) ){
// Get the Image ur by Image id and Size
$url = wp_get_attachment_image_url( (int) $matches[1], $matches[2] );
$img = sprintf( '<img src="%s" />', $url );
// Replce shortcode with <img> tag
$content = str_replace( $matches[0], $img, $content );
}
}
// Update post content with updated content with <img> tag
wp_update_post( [ 'ID' => get_the_ID(), 'post_content' => $content] );
}
// END the Loop

Get first image from last post in WordPress

Can't get the first picture in the last post (function - get_first_post_image). Where is the mistake? Please help me. Thank you in advance for your help.
function get_first_post_image() {
global $post, $posts;
$first_img = '';
ob_start();
ob_end_clean();
if(preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches)){
$first_img = $matches [1] [0];
return $first_img;
}
else {
$first_img = "http://yyyyyy/post-default.png";
return $first_img;
}
};
function custom_function(){
$args = array(
'numberposts' => '1',
);
$recent_posts = wp_get_recent_posts( $args );
foreach( $recent_posts as $recent ):
$post_id = $recent['ID'];
$post_url = get_permalink($recent['ID']);
$post_title = $recent['post_title'];
$post_content = $recent['post_content'];
$post_thumbnail = get_the_post_thumbnail($recent['ID']);
$imglink = get_first_post_image($recent['ID']);
endforeach;
$data = '... ' . $imglink . ' ...';
....
}
Sorry for my bad English.
I've rewritten the function to return the default image if no first image is found. Best way of parsing HTML is DOM parsing, not regex.
function get_first_post_image(string $post_content): string
{
$defaultImage = 'http://yyyyyy/post-default.png';
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML($post_content);
$img = $doc->getElementsByTagName('img');
if (!$img->length) return $defaultImage;
return $img->item(0)->getAttribute('src') ?: $defaultImage;
}
You are calling get_first_post_image() with the ID instead of the post content.
change
$imglink = get_first_post_image($recent['ID']);
to
$imglink = get_first_post_image($recent['post_content']);
I've updated the function above
Changed Signature
Removed global $post
Changed loadHtml()

Wordpress shortcode function returns only the title

my problem is that: Trying to retrieve the_content with a simple shortcode function, it retrieves only the title.
Even applying another filters the result is always the same.
The content is from a page.
The function is declared in the functions.php theme file.
Using the post (page) id.
function shtcode_Func( $atts = array() ) {
// set up default parameters
extract(shortcode_atts(array(
'id' => '5'
), $atts));
$my_postid = $atts;//This is page id or post id
$content_post = get_post($my_postid);
$content = $content_post->post_content;
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
return $content;
}
add_shortcode('shortcodePage', 'shtcode_Func');
Calling from widget with [shortcodePage id=POST_ID] (int)
Result: Prints only the title.
I tried to change the filter with 'the_post_thumbnail' and retrieved the title again.
I'm desperated :(
Thanks!!
There are several things incorrect with your shortcode function, but the main things:
You are using extract but not using anything from extract
$atts is an array, not just the id.
You are using apply_filters('the_content'). This essentially overwrites WPs built in apply_filter. You want to use add_filter, but as you can see that won't be necessary.
Here is the shortcode trimmed down with what you are trying to do:
function shtcode_Func( $atts ) {
// set up default parameters. No need to use extract here.
$a = shortcode_atts(array(
'id' => ''
), $atts);
// Use get_the_content, and pass the actual ID
$content = get_the_content('','', $a['id'] );
// This is the same
$content = str_replace(']]>', ']]>', $content);
// Return the content.
return $content;
}
add_shortcode('shortcodePage', 'shtcode_Func');
Try to use like this:
function shtcode_Func( $atts = array() ) {
// set up default parameters
extract(shortcode_atts(array(
'id' => '5'
), $atts));
$content_post = get_post( $atts['id'] );
ob_start();
$content = $content_post->post_content;
$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]>', $content );
echo $content;
$str = ob_get_contents();
ob_end_clean();
return $str;
}
add_shortcode('shortcodePage', 'shtcode_Func');

How to strip all visual composer shortcode/tags from wordpress's post_content fetched with custom query

I am working on a web-service(API) where i am fetching result WP_query() function and parse that in JSON format. which will further use in android application.
The problem is the post_content i am getting with query is composed by visual composer and the whole content is in form of such tags like
[VC_ROW][/VC_ROW][VC_COLUMN]some text[/VC_COLUMN] etc.
I want to remove/strip all these shortcode from the content and retrieve only plain text from it. Is there any visual composer function through which i can achieve this thing
<?php
require('../../../wp-load.php');
require_once(ABSPATH . 'wp-includes/functions.php');
require_once(ABSPATH . 'wp-includes/shortcodes.php');
header('Content-Type: application/json');
$post_name = $_REQUEST['page'];
if($post_name!=''){
if($post_name=='services') {
$args = array(
'post_parent' => $page['services']['id'],
'post_type' => 'page',
'post_status' => 'published'
);
$posts = get_children($args);
foreach($posts as $po){
$services_array[] = array('id'=>$po->ID,'title'=>$po->post_title,'image'=>get_post_meta($po->ID, 'webservice_page_image',true),'description'=>preg_replace("~(?:\[/?)[^/\]]+/?\]~s", '', $po->post_content));
}
$post = array(
'status'=>'ok',
'services'=>$services_array
);
echo json_encode($post);
}
}
?>
I want to remove/strip all these shortcode from the content and retrieve only plain text from it.
Solution that worked for me:
$content = strip_tags( do_shortcode( $post->post_content ) );
do_shortcode triggers all visual composer shortcodes and thus returns html+text;
strip_tags removes all html tags and returns plain text.
Here, you can try and easily add some short codes in array that you needs and also you can remove all shortcodes via below code.
$the_content = '[VC_ROW][VC_COLUMN]some text1[/VC_COLUMN] etc.[/VC_ROW][VC_COLUMN_INNTER width="1/3"][/VC_COLUMN_INNTER]';
$shortcode_tags = array('VC_COLUMN_INNTER');
$values = array_values( $shortcode_tags );
$exclude_codes = implode( '|', $values );
// strip all shortcodes but keep content
// $the_content = preg_replace("~(?:\[/?)[^/\]]+/?\]~s", '', $the_content);
// strip all shortcodes except $exclude_codes and keep all content
$the_content = preg_replace( "~(?:\[/?)(?!(?:$exclude_codes))[^/\]]+/?\]~s", '', $the_content );
echo $the_content;
you want to remain some shortcodes you can't use strip_shortcodes() for that.
Best solution, solved.
Just add the following code to file wp-includes/rest-api.php, at the bottom:
/**
* Modify REST API content for pages to force
* shortcodes to render since Visual Composer does not
* do this
*/
add_action( 'rest_api_init', function ()
{
register_rest_field(
'page',
'content',
array(
'get_callback' => 'compasshb_do_shortcodes',
'update_callback' => null,
'schema' => null,
)
);
});
function compasshb_do_shortcodes( $object, $field_name, $request )
{
WPBMap::addAllMappedShortcodes(); // This does all the work
global $post;
$post = get_post ($object['id']);
$output['rendered'] = apply_filters( 'the_content', $post->post_content );
return $output;
}
I took it somewhere and update it a bit, to work a bit better :).
in functions.php add this function:
/** Function that cuts post excerpt to the number of a word based on previously set global * variable $word_count, which is defined below */
if(!function_exists('kc_excerpt')) {
function kc_excerpt($excerpt_length = 20) {
global $word_count, $post;
$word_count = $excerpt_length;
$post_excerpt = get_the_excerpt($post) != "" ? get_the_excerpt($post) : strip_tags(do_shortcode(get_the_content($post)));
$clean_excerpt = strpos($post_excerpt, '...') ? strstr($post_excerpt, '...', true) : $post_excerpt;
/** add by PR */
$clean_excerpt = strip_shortcodes(remove_vc_from_excerpt($clean_excerpt));
/** end PR mod */
$excerpt_word_array = explode (' ',$clean_excerpt);
$excerpt_word_array = array_slice ($excerpt_word_array, 0, $word_count);
$excerpt = implode (' ', $excerpt_word_array).'...'; echo ''.$excerpt.'';
}
}
and after that you call it normally kc_excerpt(20); and it will return normal post_content/excerpt
How to remove visual composer from wp post: i.e [vc_row][vc_column width=\"2/3\"][distance][vc_single_image image=\"40530\" img_size=\"large\"][distance][distance][distance][vc_column_text]
Also WP post remvoe short codes and html tags.
while($posts->have_posts()) {
$postContent = get_the_content();
//Remove html tags. and short code
$postContent = strip_tags( do_shortcode( $postContent ) );
//Remove visual composer tags [vc_column] etc
$postContent = preg_replace( "/\[(\/*)?vc_(.*?)\]/", '', $postContent );
}
Looking source code from wordpress api, I did a function to remove some shortcode from content. So this is the result:
function removeShortcode($content, $shortcodeList){
preg_match_all('#\[([^<>&/\[\]\x00-\x20=]++)#', $content, $matches);
$tagnames = array_intersect($shortcodeList, $matches[1]);
if(empty($tagnames)){
return $content;
}
$pattern = get_shortcode_regex($tagnames);
preg_match_all("/$pattern/", $content, $matchesTags);
foreach ($matchesTags[0] as $key => $value) {
$content = str_replace($value, $matchesTags[5][$key], $content);
}
return $content;
}
example:
$content = "<p>Hi, this is a [example]<b>example</b>[/example]. [end]</p>";
$shortcodesToRemove = ["example", "end"];
echo removeShortcode($content, $shortcodesToRemove);
foreach($posts as $po){
$services_array[] = array('id'=>$po->ID,'title'=>$po->post_title, 'description'=>do_shortcode($po->post_content));
}
You should try this.

Wordpress, get a post content by its name or URL

I saw in here that I can get a post's content in WordPress using the post ID. Something like:
<?php $my_postid = 83;//This is page id or post id
$content_post = get_post($my_postid);
$content = $content_post->post_content;
$content = apply_filters('the_content', $content);
$content = str_replace(']]>', ']]>', $content);
echo $content;?>
I want the very same thing, BUT getting the post by its name.
You can do it using
$content_post = get_posts( array( 'name' => 'yourpostname' ) ); // i.e. hello-world
if( count($content_post) )
{
$content = $content_post[0]->post_content;
// do whatever you want
echo $content;
}
Update : Also you can add this function in your functions.php and can call it from anywhere
function get_post_by_name($post_name, $post_type = 'post', $output = OBJECT) {
global $wpdb;
$post = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type= %s", $post_name, $post_type ));
if ( $post ) return get_post($post, $output);
return null;
}
// call the function "get_post_by_name"
$content_post = get_post_by_name('hello-world');
if($content_post)
{
$content = $content_post->post_content;
// do whatever you want
echo $content;
}
Update : To get a post by it's title you can use
// 'Hello World!' is post title here
$content_post = get_page_by_title( 'Hello World!', OBJECT, 'post' );
or you can use your $item->item_title variable
$content_post = get_page_by_title( $item->item_title, OBJECT, 'post' );
if($content_post)
{
$content = $content_post->post_content;
// do whatever you want
echo $content;
}

Categories