I recently have removed the excerpt function from Wordpress and made my own so I can allow some HTML to be shown in the excerpt. I made the changes in a child theme functions file.
It was working fine on the front-end but after that I had problems on the back-end of Wordpress. In /wp-admin/edit.php in an excerpt of posts I get the post excerpt with all the HTML tags so it was really hard to read the actual content of post.
To fix that I did a change in the Wordpress core file /wp-admin/includes/class-wp-posts-list-table.php.
I removed content from line 1037.
echo esc_html( get_the_excerpt() );
the function esc_html
How can I make this change permanent so that after a possible update of Wordpress, the change will not be lost?
Is this change safe? I will have a lot of users in my back-end of Wordpress.
UPDATE MY QUESTION
add_filter( 'get_the_excerpt', 'my_clean_excerpt' );
function wpse_allowedtags() {
// Add custom tags to this string
return '<style>,<br>,<em>,<i>,<ul>,<ol>,<li>,<a>,<p>,<img>,<video>,<audio>,<div>,<wbr>';
}
if ( ! function_exists( 'wpse_custom_wp_trim_excerpt' ) ) :
function wpse_custom_wp_trim_excerpt($wpse_excerpt) {
$raw_excerpt = $wpse_excerpt;
if ( '' == $wpse_excerpt ) {
$wpse_excerpt = get_the_content('');
$wpse_excerpt = strip_shortcodes( $wpse_excerpt );
$wpse_excerpt = apply_filters('the_content', $wpse_excerpt);
$wpse_excerpt = str_replace(']]>', ']]>', $wpse_excerpt);
//$wpse_excerpt = strip_tags($wpse_excerpt, wpse_allowedtags()); /*IF you need to allow just certain tags. Delete if all tags are allowed */
//Set the excerpt word count and only break after sentence is complete.
$excerpt_word_count = 75;
$excerpt_length = apply_filters('excerpt_length', $excerpt_word_count);
$tokens = array();
$excerptOutput = '';
$count = 0;
// Divide the string into tokens; HTML tags, or words, followed by any whitespace
preg_match_all('/(<[^>]+>|[^<>\s]+)\s*/u', $wpse_excerpt, $tokens);
foreach ($tokens[0] as $token) {
if ($count >= $excerpt_length && preg_match('/[\,\;\?\.\!]\s*$/uS', $token)) {
// Limit reached, continue until , ; ? . or ! occur at the end
$excerptOutput .= trim($token);
break;
}
// Add words to complete sentence
$count++;
// Append what's left of the token
$excerptOutput .= $token;
}
$wpse_excerpt = trim(force_balance_tags($excerptOutput));
$excerpt_end = ' ' . ' » ' . sprintf(__( 'Read more about: %s »', 'wpse' ), get_the_title()) . '';
$excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
//$pos = strrpos($wpse_excerpt, '</');
//if ($pos !== false)
// Inside last HTML tag
//$wpse_excerpt = substr_replace($wpse_excerpt, $excerpt_end, $pos, 0); /* Add read more next to last word */
//else
// After the content
//$wpse_excerpt .= $excerpt_more; /*Add read more in new paragraph */
// Extra filter to remove the above text from excerpt
$badwords = array(
'< !DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">',
'< ?xml encoding="utf-8" ?>',
);
foreach ( $badwords as $badword ) {
$wpse_excerpt = str_replace( $badword, '', $wpse_excerpt);
}
//End extra filrer
return $wpse_excerpt;
}
return apply_filters('wpse_custom_wp_trim_excerpt', $wpse_excerpt, $raw_excerpt);
}
endif;
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'wpse_custom_wp_trim_excerpt');
I used this function to add html tags in excerpt.
I after updated the excerpts in database. And i get the result that i wanted.
But i get this in backend.
problem backend
So a fast way to get away with the problem was to go to /wp-admin/includes/class-wp-posts-list-table.php and remove the function esc_html from this line echo esc_html( get_the_excerpt() ); where the excerpt is generated for back-end.
So my question is not about how to allow html tags in excerpt, I already did that, but how to make that change permanent.
My back-end after that change. Back-end after
That is what i want to do.
Don't ever change WP core... You'll lose the ability to update it and your system will be vulnerable.
You can create plugins to change the excerpt behavior, you can create your own functions and use it in your theme templates...
There is a lot of ways better than to t
Never change the core of the WordPress. As Artur Luiz Oliveira mentioned you will lose those changes the first time WordPress will update, and you should be aware that it will do that automatically once the version becomes very dated if you like it or not.
To do what you are looking for I would suggest you look into this question.
Might be more coding involved but this will stick and won't be affected when the WordPress version updates.
Related
As mentioned in the title. I try to change the image source to a default image, if an image's expiration date is expired.
I used ACF and added a new date field to all media files.
I then created the following function:
function check_expiration_date($post) {
$url = get_the_post_thumbnail_url($post->ID);
$thumbnail_id = get_post_thumbnail_id( $post->ID );
$today = date('d/m/Y');
$expire = get_field('expiration_date', $thumbnail_id);
if( $expire < $today && $expire!="" )
{
$url = "default.jpg";
}
return $url;
}
Now this function works for images that I add sepcifically in template files
but this will not work for images that have been added via the editor on post pages.
I tried to to use various hooks to change the html markup first before attempting to get the meta information but none of those had any effect on the outcome. Here an example:
function change_image_markup($html, $id, $caption, $title, $align, $url) {
$html5 = "<section>";
$html5 .= "<figure id='post-$id media-$id' class='align-$align'>";
$html5 .= "<img src='$url' alt='$title' />";
if ($caption) {
$html5 .= "<figcaption>$caption</figcaption>";
}
$html5 .= "</figure>";
$html5 .= "<section>";
return $html5;
}
add_filter( 'image_send_to_editor', 'change_image_markup', 10, 9 );
Is there a specific hook that can alter the html markup of images?
I am using Wordpress 5.5.1
any hint or tip is appreciated.
As the question is a month old and I did not receive any answers, I figured I would answer my own question. There is a difference in the requirements though. Instead of changing the image to a default one, I removed the image completely. Both can be achieved though.
So there was no real hook that could me out, as those hooks only call the action when actually inserting the image.
In my case everytime the post is being loaded the images had to be checked if they are expired or not.
Instead of working with hooks I created my own function and call that function inside single.php
In the single.php usually there is something like echo post->post_content;
Instead I call my function and give the post content as a value.
add_post_based_on_expiration_date($post->post_content);
And my function looks something like this:
function add_post_based_on_expiration_date($post_content){
$search_pattern = '/<figure(.*)\/figure>/'; //<figure(.*)/figure> /wp-image-(\d+)/
preg_match_all( $search_pattern, $post_content, $embedded_images );
$embedded_images_count = count( $embedded_images[0] );
$new_content = $post_content;
if ( $embedded_images_count > 0 ) {
for ( $i=0; $i < $embedded_images_count ; $i++ ) {
$dom = new DOMDocument;
#$dom->loadHTML($embedded_images[0][$i]);
$image = $dom->getElementsByTagName('img');
$imageId = str_replace("wp-image-" , "" , $image[0]->getAttribute('class'));
if(check_expiration_date_get_by_id($imageId)){
$new_content = str_replace($embedded_images[0][$i],"",$new_content);
}
};
};
echo $new_content;
}
It looks a bit messy but it does it's job. What I do is using regex to look for the image mark up <figure..... and save it in an array. Afterwards by using the DOM class I get the class, which contains the media ID. Then I call my function which is an alteration of the one above in the question. The function just returns true or false depeding on the expiration date. If it is true I remove it from the content and at the end I return it.
Therefore if an image is expired the image markup gets completely removed.
The downside of this aside from the messy code is the processing time. Since it it always called when opening a post site.
I am creating a private wordpress shortcode for an accordion, by using a simple plugin, created by myself.
The problem: Wordpress adds breaks and paragraphs to my HTML outcome, which leads to a broken design.
I can remove autobreaks, but then it also does not work for the real content, which has paragraphs. But I dont want to use p-tags in the backend.
How can I stop wordpress from doing autobreaks to my HTML, but still doing it for my wrapped content?
The solution has to work within a plugin - without affecting other plugins/functions.
I can remove any spacing between my shortcodes, so wordpress does not add any breaks. But thats very ugly to read.
This way it works:
[os_accordion][os_spoiler title="Title"]Content with some
breaks.[/os_spoiler][/os_accordion]
This way it does not:
[os_accordion]
[os_spoiler title="Title"]
Content with some
breaks.
[/os_spoiler]
[/os_accordion]
I tried to use a function for removing breaks, but it does not work.
//Helper to remove autops
function cleanup_shortcode_fix($content) {
$array = array('<p>[' => '[', ']</p>' => ']', ']<br />' => ']', ']<br>' => ']');
$content = strtr($content, $array);
return $content;
}
//Outer accordion wrapper
function function_accordion($atts, $content = null){
$html = '<div class="accordion">'.do_shortcode($content).'</div>';
return cleanup_shortcode_fix($html);
}
add_shortcode('os_accordion', 'function_accordion');
//Inner wraps
function function_spoiler($atts, $content = null){
//set default attributes and values
$values = shortcode_atts( array(
'title' => '',
), $atts );
//Output buffer
ob_start();
?>
<div class="toggle"><?php echo esc_attr($values['title']); ?></div>
<div class="content"><?php echo $content; ?></div>
<?php
return ob_get_clean(); //Close buffer and return data
}
add_shortcode('os_spoiler', 'function_spoiler');
Any ideas how I can make the last version work? I'm stuck. :/
This should do it. It's probably just putting p tags after everything.
remove_filter('the_content', 'wpautop');
I'll start by saying I'm fairly new to coding so I'm probably going about this the wrong way.
Basically I've got the below php function that changes urls to the page title of the url instead of a plain web address. So instead of www.google.com it would appear as Google.
<?php
function get_title($url){
$str = file_get_contents($url);
if(strlen($str)>0){
$str = trim(preg_replace('/\s+/', ' ', $str)); // supports line breaks inside <title>
preg_match("/\<title\>(.*)\<\/title\>/i",$str,$title); // ignore case
return $title[1];
}
}
?>
This is great but to implement this I have to use the below code.
echo get_title("http://www.google.com/");
However this just works on a predefined URL. What I have set up on my site at the moment is a shortcode in a html widget.
<a href='[rwmb_meta meta_key="link_1"]'>[rwmb_meta meta_key="link_1"]</a>
This shortcode displays a url/link that is input by the user in the backend of Wordpress and displays it on the frontend as a link. However I want to apply the get_title function to the above shortcode so instead of the web address it shows the page title.
Is this possible?
Thanks in advance.
for name of a url from a link you can use parse_url($url, PHP_URL_HOST);
easier way would be to have an array of links for example
$links[] = 'some1 url here';
$links[] = 'some2 url here';
then just loop your $links array with the function.
foreach($links as $link)get_title($link);
https://metabox.io/docs/get-meta-value/
try:
$files = rwmb_meta( 'info' ); // Since 4.8.0
$files = rwmb_meta( 'info', 'type=file' ); // Prior to 4.8.0
if ( !empty( $files ) ) {
foreach ( $files as $file ) {
echo $file['url'];
}
}
I need to replace code block fencing within post_content before save. The post content is written in markdown locally, pushed to github and then Wordpress.
I need the markdown fencing ```js <some code> ``` to be replaced with: [js] <some code> [/js] before saving to Wordpress.
See my working repl: https://repl.it/KDz2/1 My function works perfectly fine outside of Wordpress.
Wordpress is invoking the function, but for some reason the replace is failing. I know this because I can get a simple str_replace to work just fine within Wordpress.
Issue;
preg_replace is failing to return the replaced content within Wordpress filter. No errors thrown. Why is this failing?
For reference, my functions.php file includes:
add_filter( 'content_save_pre', 'markdown_code_highlight_fence');
function markdown_code_highlight_fence( $content ) {
$newContent = preg_replace('/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/m', '
[${2}]
$3
[\\\${2}]
', $content);
return $newContent;
}
Also tried this
function markdown_code_highlight_fence( $content ) {
$newContent = preg_replace_callback('/^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/m', function($match){
$lang = $match[2] == '' ? 'js' : $match[2];
return '
['.$lang.']'
.' '.
$match[3]
.' '.
'[\\'.$lang.']'; }, $content);
return $newContent;
}
Not sure why preg_replace isn't working within Wordpress. If anyone can help shed some light, please do.
In the interim, I have a working solution as follows:
add_filter( 'content_save_pre', 'markdown_code_highlight_fence_replace', 1, 1);
function markdown_code_highlight_fence_replace( $content ) {
preg_match_all('/`{3,}(\S+)?/', $content, $matches);
foreach ($matches[1] as $key=>$match) {
if($match === '') continue;
$content = preg_replace('/`{3,}/', '[/'.$match.']', $content, 2);
$content = str_replace('[/'.$match.']'.$match, '['.$match.']', $content);
}
return $content;
}
This is my first time playing with filters, so forgive me if this seems basic. I have done quiet a bit of googling and can't find anything related to my problem, from everything I have been able to find this should be working without an issue. It's my understanding that filters added manually run concurrent with any other filters wordpress is automatically running, ie: creating my own filter will run along with wordpress's default wpautop and wptexturize filters.
But for some reason my added filter is running fine, except now wpautop and wptexturize is failing to run on the_content. After removing my custom filter from functions, the default filters are triggering again. No other plugins installed that are modifying the output. Any help would be super appreciated, along with any general recommendations as to a better way to do this if you see something wrong with my statements.
function tumblr_chat_post($content) {
global $post;
$content = $post->post_content;
if ($post->post_type == 'post') {
$postcats = wp_get_object_terms($post->ID, 'category');
foreach ($postcats as $mycat) {
if ($mycat->name == "chats") {
$chatoutput = "<dl class=\"transcript\">\n";
$split = preg_split("/(\r?\n)+|(<br\s*\/?>\s*)+/", $content);
foreach($split as $haystack) {
if (strpos($haystack, ":")) {
$string = explode(":", trim($haystack), 2);
//list($who, $what) = explode(":", $haystack, 2);
$who = trim($string[0]);
$what = trim($string[1]);
$row_class = empty($row_class)? " class=\"alt\"" : "";
$chatoutput = $chatoutput . "<dt$row_class><b>$who:</b></dt> <dd><i>$what</i></dd>\n";
}
else {
// the string didn't contain a needle so we will keep it and output it later
$no_chatoutput = $no_chatoutput . $haystack . "\n";
}
}
// print our new formated chat post and push unformatted content to the end of the post.
$content = $chatoutput . "</dl>\n" . $no_chatoutput;
return $content;
}
else {
// I don't exist in the defined category, so no processing is needed
return $content;
}
}
}
else {
// I'm not a regular post, so no processing is needed.
return $content;
}
}
add_filter( "the_content", "tumblr_chat_post", 20);
You're not passing the already filtered $content into your filter function (and therefore you're losing any filtering done before you reach your function). It should be defined like so:
function tumblr_chat_post($content) {
// rest of your logic m'ere
}