Confusions about Wordpress get_the_title function - php

The function:
/**
* Retrieve post title.
*
* If the post is protected and the visitor is not an admin, then "Protected"
* will be displayed before the post title. If the post is private, then
* "Private" will be located before the post title.
*
* #since 0.71
*
* #param int $id Optional. Post ID.
* #return string
*/
function get_the_title( $id = 0 ) {
$post = &get_post($id);
$title = isset($post->post_title) ? $post->post_title : '';
$id = isset($post->ID) ? $post->ID : (int) $id;
if ( !is_admin() ) {
if ( !empty($post->post_password) ) {
$protected_title_format = apply_filters('protected_title_format', __('Protected: %s'));
$title = sprintf($protected_title_format, $title);
} else if ( isset($post->post_status) && 'private' == $post->post_status ) {
$private_title_format = apply_filters('private_title_format', __('Private: %s'));
$title = sprintf($private_title_format, $title);
}
}
return apply_filters( 'the_title', $title, $id );
}
I don't understand what the parameter __('Protected: %s') means in a particular line of code below. What kind of parameter is it?
$protected_title_format = apply_filters('protected_title_format', __('Protected: %s'));

__() is a localization function which is used to get the localized string of the English word "Protected".
%s is a replacement parameter that is used by sprintf(). Basically, it replaces that with the title of a blog post.
The entire __('Protected: %s') call is passed as a parameter to the apply_filters() function to simply format the post title. By default I don't think anything happens, but plugins may hook on the protected_title_format filter to further manipulate the format before applying the post title on it.

Related

Use object values passed into another function with apply_filter

First of all what I'm trying to do is have an html tag inserted that I can then target with css.
Here's the current html that I have to work with:
<p>
Rebecca DeAcetis
posted an update in the group
Creating a Dynasty™ November 2020
<a href="https://account.danijohnson.com/activity/p/6965/" class="view activity-time-since">.
<span class="time-since">2 days ago</span>
</a>
</p>
What I would like is to have " posted an update in the group " wrapped with <span class="activity-action"></span>
The plugin function that is creating the html is:
/**
* Format groups 'activity_update' activity actions.
*
* #since BuddyBoss 1.1.9
*
* #param string $action Static activity action.
* #param object $activity Activity data object.
* #return string
*/
function bp_groups_format_activity_action_activity_update( $action, $activity ) {
$user_link = bp_core_get_userlink( $activity->user_id );
$group = groups_get_group( $activity->item_id );
$group_link = '' . esc_html( $group->name ) . '';
$action = sprintf( __( '%1$s posted an update in the group %2$s', 'buddyboss' ), $user_link, $group_link );
/**
* Filters the groups 'activity_update' activity actions.
*
* #since BuddyBoss 1.1.9
*
* #param string $action The groups 'activity_update' activity actions.
* #param object $activity Activity data object.
*/
return apply_filters( 'bp_groups_format_activity_action_activity_update', $action, $activity );
}
I've tried adding this to my theme functions.php:
function add_span_to_timeline_action($action) {
$action = sprintf( '%1$s<span class="activtiy-action"> posted in the group %2$s</span>', $user_link, $group_link );
return $action;
}
add_filter('bp_groups_format_activity_action_activity_update','add_span_to_timeline_action');
It does update the html and add the <span> tags but the <a> elements don't work because the $user_link and $group_link variables are not defined in my function.
I can't figure out how to make the $activity object available inside my function to that I can define the link variables.
I know accomplish the css I want with javascript/jquery but I'd like not rely on that because the activity loads on the page and updates with ajax so I'd have to have a setTimeout setInterval so that the activity has loaded which would result in the page updating after it's already loaded.
The original filter passes the $activity variable, so you have access to it too:
function add_span_to_timeline_action($action, $activity) {
$user_link = bp_core_get_userlink( $activity->user_id );
$group = groups_get_group( $activity->item_id );
$group_link = '' . esc_html( $group->name ) . '';
$action = sprintf( '%1$s<span class="activity-action"> posted in the group %2$s</span>', $user_link, $group_link );
return $action;
}
add_filter('bp_groups_format_activity_action_activity_update','add_span_to_timeline_action', 10, 2);
Just make sure you update the parameter count on the add_filter (10 - priority, 2 - argument count)

How to change the title on a WordPress page?

Context: WordPress 5.4.5, Yoast 3.7.1
I'm a plugin developer who has access to the client's site. The site has Yoast 3.7.1 installed and I'm wondering if that is significant because no matter what I do I can't change the 404 page's title.
Now on other pages on StackOverflow where similar questions have been posed (here, here and here for example), those answering have asked if the header.php is correctly embedding a call to wp_title(). Here's what's in the current theme's header.php at that point:
<title><?php wp_title( '|', true, 'right' ); ?></title>
Interestingly, in my 404.php page, wp_get_document_title() tells me that the document title is Page not found - XXXX even though the wp_title call above specifies the separator as |. Yoast's rewriting of titles has been disabled so I'm not at all sure where that dash is coming from.
My plugin does a REST call and pulls in content from off-site for inclusion in the page. Part of that content is the text to be used in the title.
On previous client sites, I've been able to do the following:
add_filter('wp_title', 'change_404_title');
function change_404_title($title) {
if (is_404())
{
global $plugin_title;
if (!empty($plugin_title))
{
$title = $plugin_title;
}
}
return $title;
}
However, on this site, that's not working.
I have tried, based on the version of WordPress being used, hooking the pre_get_document_title filter, viz
add_filter('pre_get_document_title', 'change_404_title');
but again to no avail. I am currently reading up on Yoast ...
wp_title deprecated since version 4.4. So we should use the new filter pre_get_document_title. Your code looks fine but I am confused about global $plugin_title. I would rather ask you to Try this first
add_filter('pre_get_document_title', 'change_404_title');
function change_404_title($title) {
if (is_404()) {
return 'My Custom Title';
}
return $title;
}
If it doesn't work then try changing the priority to execute your function lately.
add_filter('pre_get_document_title', 'change_404_title', 50);
How document title is generated has changed since Wordpress v4.4.0. Now wp_get_document_title dictates how title is generated:
/**
* Displays title tag with content.
*
* #ignore
* #since 4.1.0
* #since 4.4.0 Improved title output replaced `wp_title()`.
* #access private
*/
function _wp_render_title_tag() {
if ( ! current_theme_supports( 'title-tag' ) ) {
return;
}
echo '<title>' . wp_get_document_title() . '</title>' . "\n";
}
Here is the code from v5.4.2. These are the filters you can use to manipulate title tag:
function wp_get_document_title() {
/**
* Filters the document title before it is generated.
*
* Passing a non-empty value will short-circuit wp_get_document_title(),
* returning that value instead.
*
* #since 4.4.0
*
* #param string $title The document title. Default empty string.
*/
$title = apply_filters( 'pre_get_document_title', '' );
if ( ! empty( $title ) ) {
return $title;
}
// --- snipped ---
/**
* Filters the separator for the document title.
*
* #since 4.4.0
*
* #param string $sep Document title separator. Default '-'.
*/
$sep = apply_filters( 'document_title_separator', '-' );
/**
* Filters the parts of the document title.
*
* #since 4.4.0
*
* #param array $title {
* The document title parts.
*
* #type string $title Title of the viewed page.
* #type string $page Optional. Page number if paginated.
* #type string $tagline Optional. Site description when on home page.
* #type string $site Optional. Site title when not on home page.
* }
*/
$title = apply_filters( 'document_title_parts', $title );
// --- snipped ---
return $title;
}
So here are two ways you can do it.
First one uses pre_get_document_title filter which short-circuits the title generation and hence more performant if you are not going make changes on current title:
function custom_document_title( $title ) {
return 'Here is the new title';
}
add_filter( 'pre_get_document_title', 'custom_document_title', 10 );
Second way uses document_title_separator and document_title_parts hooks for the title and the title seperator that are executed later in the function, after title is generated using functions like single_term_title or post_type_archive_title depending on the page, and just before the title tags is about to be outputted:
// Custom function should return a string
function custom_seperator( $sep ) {
return '>';
}
add_filter( 'document_title_separator', 'custom_seperator', 10 );
// Custom function should return an array
function custom_html_title( $title ) {
return array(
'title' => 'Custom Title',
'site' => 'Custom Site'
);
}
add_filter( 'document_title_parts', 'custom_html_title', 10 );
Add this to your functions.php
function custom_wp_title($title) {
if ( is_404() ) {
$title = 'Custom 404 Title';
}
return $title;
}
add_filter( 'wp_title', 'custom_wp_title', 10, 2 );
10 - is priority change to overwrite other plugins like SEO

How to replace meta title and meta description in wordpress?

Sorry if my question was basic or stupid but please help me to solve this issue. I'm trying to change <title> and <meta name="description" > tags dynamically in wordpress. so this is what I tried in function.php file.
function changeMeta_2(){
global $wpdb;
$cur_url = $_SERVER['REQUEST_URI'];
$basename = pathinfo($cur_url);
$ebasename = $basename['filename'];
if(is_numeric($ebasename)) {
$url = explode('/', $basename['dirname']);
$basename = explode('.', $url[count($url)-2]);
$ebasename = $basename[0];
}
$pageName = $ebasename;
$arraylist_subcat = array("car","bike","boat","xxxx","yyyy","zzz","mmmm");
$arraylist_maincat = array("aus","ind","usa","uae");
$category_id = get_term_by('slug',$pageName, 'category');
$category_parentid = get_term_by('id', $category_id->parent, 'category');
$parent_slug = $category_parentid->slug;
if ( is_page()) {
if ( in_array($pageName,$arraylist_maincat) ) {
$metaTitle = 'Browse '.$pageName.' | Some txt title | mysite.com';
$metaDescription = 'some of custome blablaaaaa text description '.$pageName.' some of custome blablaaaaa text description ';
echo '<title>'.$metaTitle.'</title>';
echo '<meta name="description" content="'.$metaDescription.'"/>';
}
}
}
add_action( 'wp_head', 'changeMeta_2' );
In the above code I'm trying to change the title tag and meta description for term id which are matching with array values (in_array condition).
Everything works fine, but problem is instead of override(replace) <title> tag is appending in head. Its not changing it appending. please someone help me to solve this issue.
How document title is generated has changed since Wordpress v4.4.0. Now wp_get_document_title dictates how title is generated:
/**
* Displays title tag with content.
*
* #ignore
* #since 4.1.0
* #since 4.4.0 Improved title output replaced `wp_title()`.
* #access private
*/
function _wp_render_title_tag() {
if ( ! current_theme_supports( 'title-tag' ) ) {
return;
}
echo '<title>' . wp_get_document_title() . '</title>' . "\n";
}
Here is the code from v5.4.2. Here are the filters you can use to manipulate title tag:
function wp_get_document_title() {
/**
* Filters the document title before it is generated.
*
* Passing a non-empty value will short-circuit wp_get_document_title(),
* returning that value instead.
*
* #since 4.4.0
*
* #param string $title The document title. Default empty string.
*/
$title = apply_filters( 'pre_get_document_title', '' );
if ( ! empty( $title ) ) {
return $title;
}
// --- snipped ---
/**
* Filters the separator for the document title.
*
* #since 4.4.0
*
* #param string $sep Document title separator. Default '-'.
*/
$sep = apply_filters( 'document_title_separator', '-' );
/**
* Filters the parts of the document title.
*
* #since 4.4.0
*
* #param array $title {
* The document title parts.
*
* #type string $title Title of the viewed page.
* #type string $page Optional. Page number if paginated.
* #type string $tagline Optional. Site description when on home page.
* #type string $site Optional. Site title when not on home page.
* }
*/
$title = apply_filters( 'document_title_parts', $title );
// --- snipped ---
return $title;
}
So here are two ways you can do it.
First one uses pre_get_document_title filter which short-circuits the title generation and hence more performant if you are not going make changes on current title:
function custom_document_title( $title ) {
return 'Here is the new title';
}
add_filter( 'pre_get_document_title', 'custom_document_title', 10 );
Second way uses document_title_separator and document_title_parts hooks for the title and the title seperator that are executed later in the function, after title is generated using functions like single_term_title or post_type_archive_title depending on the page and about to be outputted:
// Custom function should return a string
function custom_seperator( $sep ) {
return '>';
}
add_filter( 'document_title_separator', 'custom_seperator', 10 );
// Custom function should return an array
function custom_html_title( $title ) {
return array(
'title' => 'Custom Title',
'site' => 'Custom Site'
);
}
add_filter( 'document_title_parts', 'custom_html_title', 10 );
For anybody coming to this question in the future: This functionality can be accomplished using the Yoast SEO plugin.
However, if you do want to still do this yourself....
In order to modify the title, rather than the wp_head hook, you need to be using the filters that actually allow you to modify the title: wp_title
And you can / should use the wp_head in order to add the meta description (see the docs here: http://codex.wordpress.org/Meta_Tags_in_WordPress)
Also note there's easier ways to get the page title, mentioned below...
For the title, your code would look something like so:
function changeTitle($title, $sep, $seplocation){
global $wpdb;
// NOTE: This is the HARD way to get the page title, and is unreliable...
$cur_url = $_SERVER['REQUEST_URI'];
$basename = pathinfo($cur_url);
$ebasename = $basename['filename'];
if(is_numeric($ebasename)) {
$url = explode('/', $basename['dirname']);
$basename = explode('.', $url[count($url)-2]);
$ebasename = $basename[0];
}
$pageName = $ebasename;
// NOTE: Why not get pagename this way?
global $post;
$pageName = $post->post_title;
// or if you need the slug...
$pageName = $post->post_slug;
$arraylist_subcat = array("car","bike","boat","xxxx","yyyy","zzz","mmmm");
$arraylist_maincat = array("aus","ind","usa","uae");
$category_id = get_term_by('slug',$pageName, 'category');
$category_parentid = get_term_by('id', $category_id->parent, 'category');
$parent_slug = $category_parentid->slug;
if ( is_page()) {
if ( in_array($pageName,$arraylist_maincat) ) {
$title = 'Browse '.$pageName.' | Some txt title | mysite.com';
}
}
return $title;
}
add_action( 'wp_title', 'changeTitle', 10, 3 );

How to Overwrite WP core function get_comments_number comepletely

Due to some requirement I need to completely change the behavior of the get_comments_number();
A wp core function that returns the number of comments !
What I want is to change its behavior and instead of reading the comment I want it to override with the following function;
function get_review_numbers( $post_id = 0 ) {
$post = get_post( $post_id );
if ( ! $post ) {
$count = 0;
} else {
$count = get_rev_count($post->ID);
$post_id = $post->ID;
}
/**
* Filter the returned comment count for a post.
*
* #since 1.5.0
*
* #param int $count Number of comments a post has.
* #param int $post_id Post ID.
*/
return apply_filters( 'get_review_numbers', $count, $post_id );
}
Please guide me I want when ever I write some where get_comments_number it should execute the above function instead of executing its core function.
you can't overwrite functions in php. (theme devs test if function exists then create function to allow new functions to be created if run before that point)
However there is a filter in get_comments_number
return apply_filters( 'get_comments_number', $count, $post_id );
so you can filter the result with:
add_filter('get_comments_number', 'your_custom_funct');
function your_custom_funct($count){
$count++; // example you can add one to the count, etc
return $count; //return it when finished!
}

how do i get the Comment-ID with the comment_post_form

I´m searching for a way to hook into comment_post_form and update_comment_meta, if something, but i can´t figure out how to get the comment-ID.
The function is in the functions.php
function add_comment_drawing() {
$drawingsave = $_POST['drawinginput'];
if ($drawingsave == 'Das Bild wird gespeichert'){
update_comment_meta( $comment->ID, 'drawingurl', 'Brad' );
}
}
add_action('comment_post', 'add_comment_drawing');
Thanks in advance
Comment Actions:
comment_post
Runs just after a comment is saved in the database. Action function arguments: comment ID, approval status ("spam", or 0/1 for disapproved/approved).
function add_comment_drawing($comment_id){
$drawingsave = isset($_POST['drawinginput']) ? $_POST['drawinginput'] : false;
if($drawingsave == 'Das Bild wird gespeichert'){
update_comment_meta($comment_id, 'drawingurl', 'Brad' );
}
}
add_action('comment_post', 'add_comment_drawing', 10, 1);
You're missing the arguments in your function.
function add_comment_drawing( $comment_id, $approval_status ) {
$drawingsave = $_POST['drawinginput'];
if ($drawingsave == 'Das Bild wird gespeichert'){
update_comment_meta( $comment_id, 'drawingurl', 'Brad' );
}
}
add_action( 'comment_post', 'add_comment_drawing', 10, 2 );
" i can´t figure out how to get the comment-ID"
add_action: adds an action to the queue
do_action: somewhere in the code where the queued actions are executed (Find it!)
in this case: /wp-includes/comment.php line 1811.
about 10 lines above you see:
$comment_ID = wp_insert_comment($commentdata);
if ( ! $comment_ID ) {
return false;
}
So your comment_ID is what is provided BY the "add_action" (in this case by the wp_insert_comment method/function; so that you can use it in your function, not the other way around. E.g. log the comment_ID to a file or something.
"How does add_action work / parameters ? "
Open /wp-includes/plugin.php, search for "add_action" and around line 400 you see:
**
* Hooks a function on to a specific action.
*
* Actions are the hooks that the WordPress core launches at specific points
* during execution, or when specific events occur. Plugins can specify that
* one or more of its PHP functions are executed at these points, using the
* Action API.
*
* #uses add_filter() Adds an action. Parameter list and functionality are the same.
*
* #since 1.2.0
*
* #param string $tag The name of the action to which the $function_to_add is hooked.
* #param callback $function_to_add The name of the function you wish to be called.
* #param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
* #param int $accepted_args optional. The number of arguments the function accept (default 1).
*/
function add_action($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
return add_filter($tag, $function_to_add, $priority, $accepted_args);
}
"How does do _action work / parameters ? "
idem. Look in wp-includes/plugin.php and look around line 427:
/**
* Execute functions hooked on a specific action hook.
*
* This function invokes all functions attached to action hook $tag. It is
* possible to create new action hooks by simply calling this function,
* specifying the name of the new hook using the <tt>$tag</tt> parameter.
*
* You can pass extra arguments to the hooks, much like you can with
* apply_filters().
*
* #see apply_filters() This function works similar with the exception that
* nothing is returned and only the functions or methods are called.
*
* #since 1.2.0
*
* #global array $wp_filter Stores all of the filters
* #global array $wp_actions Increments the amount of times action was triggered.
*
* #param string $tag The name of the action to be executed.
* #param mixed $arg,... Optional additional arguments which are passed on to the functions hooked to the action.
* #return null Will return null if $tag does not exist in $wp_filter array
*/
function do_action($tag, $arg = '') {
global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter;
if ( ! isset($wp_actions[$tag]) )
$wp_actions[$tag] = 1;
else
++$wp_actions[$tag];
// Do 'all' actions first
if ( isset($wp_filter['all']) ) {
$wp_current_filter[] = $tag;
$all_args = func_get_args();
_wp_call_all_hook($all_args);
}
if ( !isset($wp_filter[$tag]) ) {
if ( isset($wp_filter['all']) )
array_pop($wp_current_filter);
return;
}
if ( !isset($wp_filter['all']) )
$wp_current_filter[] = $tag;
$args = array();
if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
$args[] =& $arg[0];
else
$args[] = $arg;
for ( $a = 2; $a < func_num_args(); $a++ )
$args[] = func_get_arg($a);
// Sort
if ( !isset( $merged_filters[ $tag ] ) ) {
ksort($wp_filter[$tag]);
$merged_filters[ $tag ] = true;
}
reset( $wp_filter[ $tag ] );
do {
foreach ( (array) current($wp_filter[$tag]) as $the_ )
if ( !is_null($the_['function']) )
call_user_func_array($the_['function'], array_slice($args, 0, (int) $the_['accepted_args']));
} while ( next($wp_filter[$tag]) !== false );
array_pop($wp_current_filter);
}
So the main "trick" around add_action / do_action / filter is call_user_func_array() : http://php.net/manual/en/function.call-user-func-array.php , once you understand that function, you understand what these functions in WP do.
"How does do _???? work "
So in general : just look at the source code of WordPress (that is the advantage its opensource)
another tip is to use an IDE, something like Eclipse or Netbeans: they can show you a lot of info in the IDE, and on top of that: during "runtime" you get a lot of info through the debugger.

Categories