How can I style the WordPress failure notice page? - css

Is there a way I can style the WordPress failure notice page? Take a look at the screenshot below which shows an example of the page. This page is generated at various times and for various reasons. To generate the page, open 2 tabs in your browser and login to the same WordPress site on each tab.
1: log out of the site via the first tab you have open.
2: log out via the second tab.
You'll see the failure page.

The approach I took was to set up a custom die handler which gives you the option to style all 'die' messages.
// custom die handler
function get_custom_die_handler() {
return 'custom_die_handler';
}
// hook the function
add_filter('wp_die_handler', 'get_custom_die_handler' );
// build a custom die handler
function custom_die_handler( $message, $title = '', $args = array() ) {
// whatever you want the die handler to do
}

Navigate to the file /wp-includes/functions.php look for a function called
wp_nonce_ays
That is the function which outputs the error page. That is a core function, which is called by the action of check_admin_referer. You could try to hook into that action; the only problem is that it dies after wp_nonce_ays is called, so using add_action has no effect since it dies before it would trigger. However, luckily, check_admin_referer is a pluggable function, so you can make a function to override it. Our function will be an exact copy of check_admin_referer except one extra line of code is added to style it. Save the function, I called it styleFailPage.php, and put it in your /wp-content/plugins/ folder.
<?php /*
* Plugin Name:Failure Styler
* Description:Adds a style element right before the failure notice is called
*/
if ( ! function_exists( 'wp_logout' ) ) {
function check_admin_referer($action = -1, $query_arg = '_wpnonce') {
if ( -1 == $action )
_doing_it_wrong( __FUNCTION__, __( 'You should specify a nonce action to be verified by using the first parameter.' ), '3.2' );
$adminurl = strtolower(admin_url());
$referer = strtolower(wp_get_referer());
$result = isset($_REQUEST[$query_arg]) ? wp_verify_nonce($_REQUEST[$query_arg], $action) : false;
if ( !$result && !(-1 == $action && strpos($referer, $adminurl) === 0) ) {
//this is the line I added:
echo "<style>body {background:red !important;}</style>";
wp_nonce_ays($action);
die();
}
do_action('check_admin_referer', $action, $result);
return $result;
}
}
?>
This will make invalid HTML because you have to end up inserting the <style> info ABOVE the doctype declaration, however AFAIK this is unavoidable without explicitly editing the core wp_nonce_ays function

Related

How do I add my class the earliest possible?

I am using the following code to add my class “noTypo”:
function prefix_register_block( $blocks ) {
// 'my_block' corresponds to the block slug.
$blocks['wpgb_custom_title'] = [
'name' => __( 'WPGB Custom Title', 'text-domain' ),
'render_callback' => 'prefix_my_block_render',
];
return $blocks;
}
add_filter( 'wp_grid_builder/blocks', 'prefix_register_block', 10, 1 );
// The render callback function allows to output content in cards.
function prefix_my_block_render() {
// Get current post, term, or user object.
$post = wpgb_get_post();
// Output the post title.
echo '<span class="noTypo">' . esc_html( $post->post_title ) . '</span>';
}
But it seems that this code above is adding the class later than this code:
function add_notypo_to_title( $title ) {
return "<span class='noTypo'>$title</span>";
}
if (! is_admin() ) {
add_filter( 'the_title', 'add_notypo_to_title', 10, 1 );
}
Both codes add the class successfully, yet the plugin that should use the class for dewidowing – wpTypography -, does not see the class if it’s added with the first code, but it does see the class when it’s added with the second code.
The conclusion is that the class is not available for the plugin at the time it’s processing my content:
add_filter('wp_grid_builder/the_content', [ 'WP_Typography', 'process' ] );
My question is how do I modify the first code so that the class will be added at the earliest possible time, so that at the time wpTypography is processing the content, it would already be available?
The wpTypography plugin does not inspect the final HTML, but it looks for the class at a much earlier stage.
It seems that when I am hooking into the_title in a global function, the class is added earlier.
Is there a way to make my first function global?
Would that make it add the class earlier?
It makes sense that native WP code like the_title runs earlier than plugin code.
I tried to add global $post; into my function, but it will not make the class to be added earlier.
Can I troubleshoot this with Query Monitor to see when are these functions running? And how do I do that?
Does anyone have any other ideas?
According to the wpTypography developer:
what matters is whether the string ultimately passed to
WP_Typography::process as its first parameter contains the element
with the class
How do I verify if the string passed is the first parameter of the process?
Thanks in advance.

WooCommerce Registration Shortcode - Error messages problems

I am currently creating a widget to display the registration form on a WordPress website that uses WooCommerce. For now, I only have 3 basic fields which are email, password, repeat password. I'm looking forward to add more WooCommerce fields, but want to solve that problem before jumping to the next step.
I'm having some problems with the messages output (wrong password, account already exists, etc).
I searched on the web and there was no shortcode already built for WooCommerce registration, beside their registration page. So I went ahead and created a shortcode, with a template part.
function custom_register_shortcode( $atts, $content ){
global $woocommerce;
$form = load_template_part('framework/views/register-form');
return $form;
}
add_shortcode( 'register', 'custom_register_shortcode' );
This is a snippet I use to get the template part inside a variable, since the default function would "echo" the content instead of "returning" it.
function load_template_part($template_name, $part_name=null) {
ob_start();
get_template_part($template_name, $part_name);
$var = ob_get_contents();
ob_end_clean();
return $var;
}
So, the problem is, when I call woocommerce_show_messages or $woocommerce->show_messages(); from my template part, nothing is showing, or if it is, it shows at the top of the page.
I did try to put the calls inside my shortcode function:
function custom_register_shortcode( $atts, $content ){
global $woocommerce;
$woocommerce->show_messages();
$form = load_template_part('framework/views/register-form');
return $form;
}
add_shortcode( 'register', 'custom_register_shortcode' );
Doing so, the message output inside the <head> tag, which is not what I want.
I tried to do the same trick with ob_start(), ob_get_contents() and ob_clean() but nothing would show. The variable would be empty.
I also did try to hook the woocommerce_show_messages to an action as saw in the core:
add_action( 'woocommerce_before_shop_loop', 'woocommerce_show_messages', 10 );
For something like:
add_action( 'before_registration_form', 'woocommerce_show_messages');
And I added this in my template-part:
<?php do_action('before_registration_form'); ?>
But I still can't manage to get the error messages show inside the box. It would always be inserted in the <head>
I will share final solution when everything is done.
Thanks for your time,
Julien
I finally got this working by hooking a custom function to an action which is called in my header.php
I guess hooking functions inside template part does not work as intended.
In header.php, I got this:
do_action('theme_after_header');
And here's the hooked function. Works perfectly.
function theme_show_messages(){
woocommerce_show_messages();
}
add_action('theme_after_header', 'theme_show_messages');
However, I will look into 'unhooking' the original show message function since it might show twice. Need to test some more ;)
You can also just use the [woocommerce_messages] shortcode in your template where you want it displayed
Replying to a bit of an old question, but you can also try the following:
$message = apply_filters( 'woocommerce_my_account_message', '' );
if ( ! empty( $message ) ) {
wc_add_notice( $message );
}

Wordpress wp_schedule_event - not returning the next schedule

I am having a hard time figuring out this issue. So basically, I wrote a plugin.. the file structure is as below
-myplugin.php (init and includes myplugin-common.php )
-myplugin-admin.php (plugin menu item index and includes myplugin-part1.php and part2)
-myplugin-common.php
-myplugin-part1.php
-myplugin-part2.php
i have a function that activates the cron if it is not already enabled .. example below (this is inside the myplugin.php)
function myplugin_cron_activate() {
if ( get_option( SCHEDULE_ENABLED ) !== false ) {
if ( get_option(SCHEDULE_ENABLED) == 'true') {
if (!wp_next_scheduled('wpo_cron_event2')) {
$schedule_type = get_option(SCHEDULE_TYPE, 'weekly');
wp_schedule_event(time(), $schedule_type, 'my_cron_event2');
add_action('my_cron_event2', 'my_cron_action');
}
}
}
now *my_cron_action* is inside a common file myplugin-common.php . Which is fine and it works anyway..
The problem is, myplugin-part2.php is a settings page to enable or disable the scheduler. When I enable it .. calls the *myplugin_cron_activate()* function. But it does not activate the cron function in wordpress. But when I go to the plugin main link in admin - it gets activated.
Please note both myplugin-part1.php, myplugin-part2.php are included from inside the myplugin-admin.php. myplugin-admin.php holds 2 tabs and loads these 2 part of files accordingly.
What I still can't figure out why the scheduler is not getting activated when i submit the settings page - yes i am calling the function there on $POST. But it gets activated when I click on the main link for the admin page.. (because of this I can't show the next schedule time either)
You need to add weekly schedule
function add_weekly_cron( $schedules ) {
$schedules['weekly'] = array(
'interval' => 604800,
'display' => __('Once Weekly','beforeafter')
);
return $schedules;
}
add_filter( 'cron_schedules', 'add_weekly_cron' );
Also, I think you're triggerring wp-cron in a wrong way
add_action('my_action_hook','my_cron_function');
if( !wp_next_scheduled( 'my_cron function' ) ) {
wp_schedule_event( time(), 'weekly', 'my_action_hook' );
Use Cron View to debug WP-CRON :)

Checking If A WordPress Widget Displayed In The Current Front End

Is there a function to check if a widget is displayed in the current front end?
This is necessary for pulling some styles or scripts or doing other action to the widget.
Please see if this works by echoing the contents $GLOBALS['displayed_sidebars'] and $GLOBALS['displayed_widgets'], using print_r for example.
It must be tested after dynamic_sidebar has been executed for all sidebars that you want to include.
add_filter( 'dynamic_sidebar_params', function( $params ) {
global $displayed_sidebars, $displayed_widgets;
if( !in_array( $params[0]['id'], $displayed_sidebars ))
$displayed_sidebars[] = $params[0]['id'];
if( !in_array( $params[0]['widget_name'], $displayed_widgets ))
$displayed_widgets[] = $params[0]['widget_name'];
return $params;
});

Redirect from add_menu_page

I have added a menu using add_menu_page which all works correctly, but when clicked I want this menu page to open the post editor for a particular post id.
As a proof of concept i have tried echoing a javascript redirect out into the do function like so...
// Load up the menu page
function register_availability_custom_menu_page() {
add_menu_page('custom menu title', 'Availability', 'add_users', 'options', 'options_do_page');
}
function options_do_page() {
echo "<script type=\"text/javascript\">";
echo "window.location = '/whatever_page.php';";
echo "</script>";
}
This approach does work but I was wondering if it is the best approach, is there a better way to redirect to the page I am after?
UPDATE
I have now also tried using wp_redirect with this code...
add_action( 'admin_menu' , 'admin_menu_new_items' );
function admin_menu_new_items() {
wp_redirect( home_url() );
exit;
}
This gives me a Headers already sent error, can anyone suggest where I am going wrong?
If I'm understanding this correctly, you don't need the redirect. Instead of using a $menu_slug in the function add_menu_page, put the address of the target page, e.g.:
$the_post_title = 'The Portfolio';
add_action( 'admin_menu', 'wpse_59050_add_menu' );
function wpse_59050_add_menu()
{
global $the_post_title;
$our_page = get_page_by_title( $the_post_title );
$settings_page = add_menu_page(
'Edit '.$our_page->post_title,
'Edit '.$our_page->post_title,
'add_users',
'/post.php?post='.$our_page->ID.'&action=edit',
'',
'',
2
);
}
This function is from the following WordPress Answer: Highlighting a Menu Item by Post Name. You'll need some jQuery to do the correct highlighting of this top level menu, check both my and TheDeadMedic answers in that Q.
This other one is useful too: Add highlighting to new Admin Dashboard Menu Item.
Recently did this for pootle page builder, and this AFAIK is the best way,
/**
* Redirecting from Page Builder > Add New page
* #since 0.1.0
*/
function add_new() {
global $pagenow;
if ( 'admin.php' == $pagenow && 'page_builder_add' == filter_input( INPUT_GET, 'page' ) ) {
header( 'Location: ' . admin_url( 'whatever-page.php' ) );
die();
}
}
add_action( 'admin_init', 'add_new' );
Replace page_builder_add with your page slug and admin_url( 'whatever-page.php' ) with url you wanna redirect to.
We always use scrutinizer-ci for best code practices and maintain code score greater than 9.5/10, so all code (Including this) is secure and optimized ;)
Lemme know how it works for ya.
Cheers
I found a 2-step solution that doesn't use JS/JQ.
Step 1:
Near the top of your script, put the following PHP to display CSS that hides your first page:
add_action('admin_head', 'hide_my_first_page');
function hide_my_first_page(){
echo '<style>
a[href="admin.php?page=admin_menu_slug"] + ul > li.wp-first-item{
display: none;
}
</style>';
}
Where admin_menu_slug is the 4th argument passed to add_menu_page();.
Step 2:
Take the function of the page you want to run and pass it as the 5th argument in add_menu_page();

Resources