Add wp_header depending on wp_content in Wordpress Plugin - wordpress

I am developing a Wordpress plugin to run a certain javascript function based on some parameters.
The first step is to include the javascript file from my server. Easy:
add_action('wp_head', 'my_plugin_head');
function my_plugin_head(){
echo '<script type="text/javascript" src="http://www.my-server.net/js/w.js" ></script>';
}
The second step is to change certain text in the WordPress body to the javascript function...something like:
add_filter('the_content', 'plugin_text_replace');
function plugin_text_replace($text){
$text=preg_replace('blah', 'blah');
return $text;
//I Am still researching how to setup the preg_replace.
//It will look for something like plugin_call[1, 40, 60]
//And Change it To jsFunction(1, 40, 60);
//Bonus for anyone who can help me with that :)
}
In any case, I realized that I want the my-server.net javascript included ONLY if needed (or in other words, only if the preg_replace found a match). This is problematic to me because I can't find anyway to add a script to the <head> tag without using an action on wp_head, which does not have any reference to the body of the text.
How can I add a header ONLY if a certain preg_match is found?

To add javascript the best way is using wp_enqueue_script(), like this:
function my_scripts_method() {
wp_enqueue_script('my_java_function');
}
// For use on the Front end (ie. Theme)
add_action('wp_enqueue_scripts', 'my_scripts_method');
Inserting code into the <body> can be achieved like this:
function wp_body() {
do_action( 'wp_body' );
}
add_action( 'wp_body', 'my_body_function' ) ; //
// In "header.php" place something like this after <body>:
if ( function_exists('wp_body')) wp_body(); ?>

Related

Replace Wordpress URL domain in HTML output (for SEO optimisation) [duplicate]

WordPress has great filter support for getting at all sorts of specific bits of content and modifying it before output. Like the_content filter, which lets you access the markup for a post before it's output to the screen.
I'm trying to find a catch-all filter that gives me one last crack at modifying the final markup in its entirety before output.
I've browsed the list of filters a number of times, but nothing jumps out at me:
https://codex.wordpress.org/Plugin_API/Filter_Reference
Anyone know of one?
WordPress doesn't have a "final output" filter, but you can hack together one. The below example resides within a "Must Use" plugin I've created for a project.
Note: I haven't tested with any plugins that might make use of the "shutdown" action.
The plugin works by iterating through all the open buffer levels, closing them and capturing their output. It then fires off the "final_output" filter, echoing the filtered content.
Sadly, WordPress performs almost the exact same process (closing the open buffers), but doesn't actually capture the buffer for filtering (just flushes it), so additional "shutdown" actions won't have access to it. Because of this, the below action is prioritized above WordPress's.
wp-content/mu-plugins/buffer.php
<?php
/**
* Output Buffering
*
* Buffers the entire WP process, capturing the final output for manipulation.
*/
ob_start();
add_action('shutdown', function() {
$final = '';
// We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
// that buffer's output into the final output.
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
$final .= ob_get_clean();
}
// Apply any filters to the final output
echo apply_filters('final_output', $final);
}, 0);
An example of hooking into the final_output filter:
<?php
add_filter('final_output', function($output) {
return str_replace('foo', 'bar', $output);
});
Edit:
This code uses anonymous functions, which are only supported in PHP 5.3 or newer. If you're running a website using PHP 5.2 or older, you're doing yourself a disservice. PHP 5.2 was released in 2006, and even though Wordpress (edit: in WP version < 5.2) STILL supports it, you should not use it.
The question is may be old, but I have found a better way to do it:
function callback($buffer) {
// modify buffer here, and then return the updated code
return $buffer;
}
function buffer_start() { ob_start("callback"); }
function buffer_end() { ob_end_flush(); }
add_action('wp_head', 'buffer_start');
add_action('wp_footer', 'buffer_end');
Explanation
This plugin code registers two actions – buffer_start and buffer_end.
buffer_start is executed at the end of the header section of the html. The parameter, the callback function, is called at the end of the output buffering. This occurs at the footer of the page, when the second registered action, buffer_end, executes.
The callback function is where you add your code to change the value of the output (the $buffer variable). Then you simply return the modified code and the page will be displayed.
Notes
Be sure to use unique function names for buffer_start, buffer_end, and callback, so they do not conflict with other functions you may have in plugins.
AFAIK, there is no hook for this, since the themes uses HTML which won't be processed by WordPress.
You could, however, use output buffering to catch the final HTML:
<?php
// example from php.net
function callback($buffer) {
// replace all the apples with oranges
return (str_replace("apples", "oranges", $buffer));
}
ob_start("callback");
?>
<html><body>
<p>It's like comparing apples to oranges.</p>
</body></html>
<?php ob_end_flush(); ?>
/* output:
<html><body>
<p>It's like comparing oranges to oranges.</p>
</body></html>
*/
#jacer, if you use the following hooks, the header.php also gets included.
function callback($buffer) {
$buffer = str_replace('replacing','width',$buffer);
return $buffer;
}
function buffer_start() { ob_start("callback"); }
function buffer_end() { ob_end_flush(); }
add_action('after_setup_theme', 'buffer_start');
add_action('shutdown', 'buffer_end');
I was using the top solution of this post (by kfriend) for a while. It uses an mu-plugin to buffer the whole output.
But this solution breaks the caching of wp-super-cache and no supercache-files are generated when i upload the mu-plugin.
So: If you are using wp-super-cache, you can use the filter of this plugin like this:
add_filter('wp_cache_ob_callback_filter', function($buffer) {
$buffer = str_replace('foo', 'bar', $buffer);
return $buffer;
});
Modified https://stackoverflow.com/users/419673/kfriend answer.
All code will be on functions.php. You can do whatever you want with the html on the "final_output" filter.
On your theme's 'functions.php'
//we use 'init' action to use ob_start()
add_action( 'init', 'process_post' );
function process_post() {
ob_start();
}
add_action('shutdown', function() {
$final = '';
// We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
// that buffer's output into the final output.
$levels = ob_get_level();
for ($i = 0; $i < $levels; $i++) {
$final .= ob_get_clean();
}
// Apply any filters to the final output
echo apply_filters('final_output', $final);
}, 0);
add_filter('final_output', function($output) {
//this is where changes should be made
return str_replace('foo', 'bar', $output);
});
You might try looking in the wp-includes/formatting.php file. For example, the wpautop function.
If you are looking for doing something with the entire page, look at the Super Cache plugin. That writes the final web page to a file for caching. Seeing how that plug-in works may give you some ideas.
Indeed there was a discusussion recently on the WP-Hackers mailing list about the topic of full page modification and it seems the consensus was that output buffering with ob_start() etc was the only real solution. There was also some discussion about the upsides and downsides of it: http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#
To summarize: It works and is the best solution when necessary (like in the WP-Supercache plugin) but slows down overall speeds because your content isn't allowed to be sent to the browser as its ready, but instead has to wait for the full document to be rendered (for ob_end() ) before it can be processed by you and sent to the browser.
To simplify previous answers, just use this in functions.php:
ob_start();
add_action('shutdown', function () {
$html = ob_get_clean();
// ... modify $html here
echo $html;
}, 0);
I've been testing the answers here now for a while, and since the cache breaking thing is still an issue, I came up with a slightly different solution. In my tests no page cache broke. This solution has been implemented into my WordPress plugin OMGF (which has 50k+ users right now) and no issues with page cache breaking has been reported.
First, we start an output buffer on template redirect:
add_action('template_redirect', 'maybe_buffer_output', 3);
function maybe_buffer_output()
{
/**
* You can run all sorts of checks here, (e.g. if (is_admin()) if you don't want the buffer to start in certain situations.
*/
ob_start('return_buffer');
}
Then, we apply our own filter to the HTML.
function return_buffer($html)
{
if (!$html) {
return $html;
}
return apply_filters('buffer_output', $html);
}
And then we can hook into the output by adding a filter:
add_filter('buffer_output', 'parse_output');
function parse_output($html)
{
// Do what you want. Just don't forget to return the $html.
return $html;
}
Hope it helps anyone.
I have run into problems with this code, as I end up with what seems to be the original source for the page so that some plugins has no effect on the page. I am trying to solve this now - I haven't found much info regarding best practises for collecting the output from WordPress.
Update and solution:
The code from KFRIEND didnt work for me as this captures unprocessed source from WordPress, not the same output that ends up in the browser in fact. My solution is probably not elegant using a globals variable to buffer up the contents - but at least I know get the same collected HTML as is delivered to the browser. Could be that different setups of plugins creates problems but thanks to code example by Jacer Omri above I ended up with this.
This code is in my case located typically in functions.php in theme folder.
$GLOBALS['oldschool_buffer_variable'] = '';
function sc_callback($data){
$GLOBALS['final_html'] .= $data;
return $data;
}
function sc_buffer_start(){
ob_start('sc_callback');
}
function sc_buffer_end(){
// Nothing makes a difference in my setup here, ob_get_flush() ob_end_clean() or whatever
// function I try - nothing happens they all result in empty string. Strange since the
// different functions supposedly have very different behaviours. Im guessing there are
// buffering all over the place from different plugins and such - which makes it so
// unpredictable. But that's why we can do it old school :D
ob_end_flush();
// Your final HTML is here, Yeeha!
$output = $GLOBALS['oldschool_buffer_variable'];
}
add_action('wp_loaded', 'sc_buffer_start');
add_action('shutdown', 'sc_buffer_end');
If you want to modify the output, you can use template_include:
add_filter( 'template_include', static function ( $template ) {
if ( basename( $template ) === 'foo-template.php' ) {
echo str_replace( 'foo', 'bar', file_get_contents( $template ) );
}
return null;
} );
If instead you want to override the output completely, you can use the action template_redirect.
add_action( 'template_redirect', static function () {
wp_head();
echo 'My output.';
wp_footer();
exit;
} );

Wordpress shortcode is being inserted before content

I know we have have to return the shortcode but I'm trying to use custom templates and the shortcode is being inserted before the content in the wysiwyg editor when its actually at the end of the content:
Here is my shortcode:
add_shortcode('test_temp', 'temp_handler');
function temp_handler($atts) {
ob_start();
load_template(TEMPLATES_PATH . templates/test.php');
return ob_get_contents();
}
here is what test.php looks like:
<div class="testDiv">Here is my test template</div>
What else can I do so the short code is not inserted before the content?
Try this:
add_shortcode('test_temp', 'temp_handler');
function temp_handler($atts) {
ob_start();
load_template(TEMPLATES_PATH . templates/test.php');
$ret = ob_get_contents();
ob_end_clean();
return $ret;
}
Your idea to use output buffering to load template files is a good idea and a common practice for Wordpress shortcodes. However, it looks odd to me that you don't end the output buffering anywhere in your provided code, ob_end_clean(), which leads me to believe that your output buffering is just not setup perfectly.
Generally speaking, Wordpress will run your function and replace your shortcode tag with the output. If the output of your function is instead showing up somewhere else on the page (particularly if it is showing up above the area where it should be) then your function must be outputting content as Wordpress is running it (in your case, it must not be output buffering as expected).
Note: The load_template function uses require_once by default, which means you'll only be able to use your shortcode once on the page. Instead, I recommend using: load_template(TEMPLATES_PATH . templates/test.php', false);

How I can add my JQuery script into single wordpress page?

I want to add my JQuery script into single Wordpress page, but I dont know how. Example of script I'd like to inject:
<script type="text/javascript">
$(document).ready(function() {
$("html, body").animate({ scrollTop: $(window).height() }, 600);
return false;
});
</script>
This code works fine when injected in plain HTML, but how can I do the same for Wordpress?
Personally I feel the best way for adding a JavaScript to a particular page/post is to use ShortCode
Add this:
function add_my_script() {
return "<script>
//your jQuery here
</script>";
}
add_shortcode( 'myCustomShortCode', 'add_my_script' );
to your function.php file. Your function.php file is location at /wp-content/themes/<name of theme>/
NOTE: Use ' instead of " in your <script> to continue inside the return statement.
Now simply add the shortcode [myCustomShortCode] in your page.
you have a couple of options, the function you created above will add it to all pages (you were registering the script but not actually calling it, thats why its not working. see correction below).
If you want you can simply place the wp_enqueue_script() function below in your template (without add action and the custom() function
or directly write it into the template file (lots of arguments about whether this is acceptable coding practice, but it works)
or require_once / include_once the file in the correct sequence (you are using document.ready so you can do this anywhere below the header (if you already have jquery loaded in the header, if in the footer, must be below the footer) same rules apply for directly writing into the file.
function custom() {
wp_enqueue_script('jquery');
wp_enqueue_script('add-custom-js' , get_template_directory_uri() . '/js/custom.js' , array('jquery'),'',true );
}
add_action('wp_enqueue_scripts' . 'custom' );
also WP uses non conflict jquery so you need to use jQuery instead of the the shorthand vers $. there are a few alternative ways to use the shorthand if you google it.
just edit a page in wordpress, select text view (not formatted text) and paste your script wherever you like.

Make Wordpress Pages's Titles readonly

I'm looking for a WP function that add the Read-only parameter to all Pages's Titles's input, that will make the Page's title unalterable.
Thanks a lot in advance.
This can be accomplished with some simple JavaScript/jQuery. Create a file called admin_title_disable.js, and queue it up within functions.php. For example:
functions.php:
wp_register_script('admin_title_disable', '/path/to/admin_title_disable.js');
function disableAdminTitle () {
wp_enqueue_script('admin_title_disable');
}
add_action('admin_enqueue_scripts', 'disableAdminTitle');
Now, in your js file:
jQuery(document).ready(function ($) {
$('#title').attr('disabled','disabled');
});
This will set both post and page title input fields with a disabled attribute. Hope this helps!
If you want to restrict this script to a particular admin page, wrap the add_action hook in a conditional that compares $_GET['page']. You can also take advantage of the $hook parameter that is available when using admin_enqueue_scripts to check for the page. See here.
Update::
WordPress makes it a little tricky to tell between post and page edit screens, but there is a hidden input that you can take advantage of. :) Here's an updated version of the jQuery that will only run on page edit screens:
jQuery(document).ready(function ($) {
//find the hidden post type input, and grab the value
if($('#post_type').val() === 'page'){
$('#title').attr('disabled','disabled');
}
});
No need to make a seperate js file. Adding this to your function.php will do the same that Matthew showed.
function admin_footer_hook(){
?>
<script type="text/javascript">
if(jQuery('#post_type').val() === 'post'){
jQuery('#title').prop('disabled', true);
}
</script>
<?php
}
add_action( 'admin_footer-post.php', 'admin_footer_hook' );
This Solution Will disable clicking on the post title and editing it using CSS. CSS targets post type "page" only. It has been tested on Gutenberg visual editor. Users Can still edit title from "Quick Edit".
Add this code to your functions.php file.
function disable_title_edit() {
if(!current_user_can('administrator')){
if( !current_user_can('administrator')){ ////Only allow Admin
echo '<style>.post-type-page .edit-post-visual-editor__post-title-wrapper{
pointer-events: none;
}</style>'; } }
}
add_action('admin_head', 'disable_title_edit', 100);

How can I use add_filter for a specific page template?

In Wordpress I have a page template called designers.php.
When loading, it reads the slug to get a uniqe ID, then calls the DB to retrieve designer information.
I want to use this information to alter the page title, using the designer name in the title tag.
I've tried using the add_filter in my designers.php file, but it's not working:
add_filter('wp_title', 'set_page_title');
function set_page_title($title) {
global $brand;
return 'Designer '.$brand['name'].' - '.get_bloginfo('name');
}
I'm, guessing the add_filter must either be located inside a plugin or in functions.php file.
How can I achieve what I'm trying to do?
UPDATE
The function is never fired as long as I use wp_title. If I change it to init (for testing), the function is fired.
So why does the add_filternor work for wp_title?
You are almost right. The filter must reside in function.php, and is called to modify the title. You can add the filter conditionally. Use this function is_page_template() to determine if wordpress is rendering your template
Try to modify your function like this:
add_filter('wp_title', 'set_page_title');
function set_page_title($title) {
global $brand;
if (is_page_template('designer.php'))
return 'Designer '.$brand['name'].' - '.get_bloginfo('name');
else
return $title;
}
First of all add_filter must either be located inside a plugin or in functions.php file.
Then, maybe you have to set the priority for the filter :
add_filter('wp_title', 'set_page_title',1);
function set_page_title() {
global $brand;
return 'Designer '.$brand['name'].' - '.get_bloginfo('name');
}
And check the <title> meta in your header.php theme.
<title><?php wp_title(); ?></title>

Resources