Showing posts with label WordPress PHP. Show all posts
Showing posts with label WordPress PHP. Show all posts

Thursday, 11 July 2024

Formatting the Date & Time Format in PHP Error Log

The default log output looks like:
[11-Jul-2024 04:19:33 UTC] The logged Info after the date
The following code will change it to your local time which makes sence if all your messages come from a single timezone:
$TZ = date_default_timezone_get();  //returns 'UTC'
            date_default_timezone_set('Australia/Melbourne');
$TZ = date_default_timezone_get();  //returns 'Australia/Melbourne'
The log will now show the correct local date time (I'd prefer am/pm but whatever):
[11-Jul-2024 14:19:33 Australia/Melbourne] The logged Info after the date
The above doesn't change the format, just the timezone it displays in, however you can override the default logging to define the date as you wish as as shown here

Monday, 4 September 2023

GMAIL Removing CSS STYLE (and referencing classes)

I'm sending emails using PHP in WordPress, there seem to be many issues with email clients in general (as a quick google will confirm).

In  GMAIL in 2023, if it doesn't like anything at all it will drop the complete "style" block (all CSS).  It will also update the email's HTML to remove any references to the dropped styles.

To check your email's HTML in general, click the Gmail messages "..." menu and choose "Show Original".  That will open up a new window, you can copy/paste the HTML you sent and run it through online HTML and/or CSS validators to check for obvious issues.

You can use Chrome's debug tools (<F12>) to find the source code and use <Ctrl><F> to search for something you expect to find in the CSS contents), if you don't find it, then you know it has been removed.

In my case, I'd fixed any issues reported but it still happened.  I went to the old standby binary tree debugging, where you keep removing code until it starts working, then keep inserting/deleting bits until you identify the style the line(s) causing the issue.

In my case, it would appear that it didn't like the incorrect important tag "!Important" (that the validators didn't pick up), fixing it solved the issue (it should have been "!important").

<style>.OrderInvoice table, .OrderInvoice th, .OrderInvoice td
{
    border: 2px solid black;
    padding: 5px;
    border-width: thin;
    border-collapse: collapse !Important;
}</style>

Friday, 30 June 2023

Prevent PHP Deprecated Messages in Wordpress PHP error logs

WordPress ignores the PHP error level so to set your own you need to use a must-use plugin, these reside in a "mu-plugins" directory next to the "plugins" one.  

A must-use plugin does not need activating and can be seen in WordPress in the "Plugins" section under a tab called "Must-Use".

To use the following code put in into a PHP file, add "<?php" to the start and use FTP or CPANEL to upload the file into the WordPress "mu-plugins" directory.


/*
 *  Plugin Name: Prevent PHP Deprecated Messages in PHP ERROR Logs
 *  Description: Wordpress stuffs up the PHP error level with it's own "error_reporting" levels so you can't rely on setting it in the "wp-config.php" configuration file for PHP!  This Must Use plugin removes almost all of the unwanted messages that can otherwise flood the error log.  It sets: error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED)
 *  Version: 2023.06.30
 *  Author: Dennis Bareis
 */


    error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);  //Doesn't work in wp-config.php

Tuesday, 6 June 2023

WordPress and "Confirm use of weak password"

 I don't want people to use weak passwords on my WordPress site, I looked for PHP code to disable the "Confirm use of weak password" row and checkbox but couldn't find anything that worked.  

My environment is WordPress 6.2.2 with a child OceanWP theme.

It seemed easiest to simply use CSS to disable it.  Obviously the CSS needs to be enqueued with PHP (for admin):


add_action( 'admin_head', 'BungalookAdministrationHeaderAssets');

 The CSS itself follows (include it in the enqueued CSS file):


.pw-weak { display: none !important; }

To improve the password requirements you can have a look at "Enforce Strong Passwords Without a Plugin - WordPress Tutorial", this is good but perhaps a bit confusing as you must first pass WordPress's "weak" check before the password can be submitted for further validation by the extra code.

Any error message is displayed at the top of the window (which may not be visible) and WordPress doesn't always scroll there...

I have modified the code a bit to display more informative error messages such as this one:


The complete modified PHP code follows:


/**
 * Enforce strong passwords (ESP) for all website users.
 *
 * https://wp-tutorials.tech/optimise-wordpress/enforce-strong-passwords-without-a-plugin/
 *
 * To disable enforcing strong passwords:
 *   define('ESP_IS_ENABLED', false);
 */

defined('WPINC') || die();

/**
 * Initialise constants and handlers.
 */
//===========================================================================
function esp_init()
//===========================================================================
{
   if (defined('ESP_IS_ENABLED') && (ESP_IS_ENABLED === false)) {
      // Disabled by configuration.
   } else {
      add_action('user_profile_update_errors',  'esp_user_profile_update_errors', 0, 3);
      add_action('resetpass_form',              'esp_resetpass_form', 10);
      add_action('validate_password_reset',     'esp_validate_password_reset', 10, 2);
   }
}
add_action('init', 'esp_init');



//===========================================================================
function esp_user_profile_update_errors($errors, $update, $user_data)
//===========================================================================
{
   return esp_validate_password_reset($errors, $user_data);
}

//===========================================================================
function esp_resetpass_form($user_data)
//===========================================================================
{
   return esp_validate_password_reset(false, $user_data);
}

//===========================================================================
/**
 * Sanitise the input parameters and then check the password strength.
 */
function esp_validate_password_reset($errors, $user_data)
//===========================================================================
{
   $is_password_ok = false;

   $user_name = null;
   if (isset($_POST['user_login'])) {
      $user_name = sanitize_text_field($_POST['user_login']);
   } elseif (isset($user_data->user_login)) {
      $user_name = $user_data->user_login;
   } else {
      // No user specified.
   }

   $password = null;
   if (isset($_POST['pass1']) && !empty(trim($_POST['pass1']))) {
      $password = sanitize_text_field(trim($_POST['pass1']));
   }

   $error_message = null;
   if (is_null($password)) {
      // Don't do anything if there isn't a password to check.
   } elseif (is_wp_error($errors) && $errors->get_error_data('pass')) {
      // We've already got a password-related error.
   } elseif (empty($user_name)) {
      $error_message = __('User name cannot be empty.');
   } else
   {
      $error_message = esp_is_password_ok($password, $user_name);
   }

   if (!empty($error_message))
   {
      //--- Display error message -------------------------------------------
      $error_message = 'ERROR: ' . $error_message;
      if (!is_a($errors, 'WP_Error')) {
         $errors = new WP_Error('pass', $error_message);
      } else {
         $errors->add('pass', $error_message);
      }
   }

   return $errors;
}

//===========================================================================
/**
 * Given a password, return "" if it's OK, otherwise return Reason it isn't.
 */
function esp_is_password_ok($password, $user_name)
//===========================================================================
{
    //--- Get userid & Password ---------------------------------------------
    $password = sanitize_text_field($password);
    $user_name = sanitize_text_field($user_name);

    //--- Run some checks ---------------------------------------------------
    $is_number_found    = preg_match('/[0-9]/',          $password);
    $is_lowercase_found = preg_match('/[a-z]/',          $password);
    $is_uppercase_found = preg_match('/[A-Z]/',          $password);
    $is_symbol_found    = preg_match('/[^a-zA-Z0-9]/',   $password);

    //--- Passed the above checks? ------------------------------------------
    $MinLen = 8;
    $R = "bug: oops";
    if       (strlen($password) < $MinLen) {
       $R =  __("The password is too short.");
    } elseif (strtolower($user_name) == strtolower($password)) {
       $R =  __("The User name and password can't be the same!");
    } elseif (!$is_number_found) {
       $R =  __("The password must contain a digit.");
    } elseif (!$is_lowercase_found) {
       $R =  __("The password must contain a lower case character.");
    } elseif (!$is_uppercase_found) {
       $R =  __("The password must contain an upper case character.");
    } elseif (!$is_symbol_found) {
       $R =  __("The password must contain a symbol (such as '@' or '#' etc).");
    } else {
       $R = '';  //Password good
    }
    if  ($R != '')
        $R = $R .  __("  The requirements for an acceptable password are that they must be at least ") . $MinLen .  __(" characters long and contain at least one each of [1] digits, [2] symbols, [3] lower case and [4] upper case");
    return $R;
}




Thursday, 25 May 2023

Enable WordPress to Search Custom Fields (PODS etc) and Display Automatically Generated Excerpt

 By default, WordPress doesn't allow searching on dynamically generated pages, but if a search matches the title then it will not display any content in the search results!  There are many plugins that can improve this but so can a little bit of PHP code.

The following code allows standard WordPress to search within the extended fields (which is stored as meta data):

 

//=======================================================

function AddCustomFieldsToSearchText($query)

//      https://wordpress.org/support/topic/default-wordpress-search-does-not-work/

//      This allows Wordpress Search to search pods fields as well as it's normal content.

//=======================================================

{

    //--- Abort if we shouldn't perform the following code ------------------

    //if (! is_main_query() )           //Function is_main_query was called <strong>incorrectly</strong>. In <code>pre_get_posts</code>, use the <code>WP_Query->is_main_query()</code> method, not the <code>is_main_query()</code> function. See https://developer.wordpress.org/reference/functions/is_main_query/. Please see <a href="https://wordpress.org/support/article/debugging-in-wordpress/">Debugging in WordPress</a> for more information. (This message was added in version 3.7.0.) in /home/wcipporg/public_html/wp-includes/functions.php on line 5865

    //   return;

    if (! $query->is_main_query())

        return;

    if (! is_search() )

        return;



    add_filter( 'posts_join',

                function( $join )

                {

                    global $wpdb;

                    return $join .' LEFT JOIN ' . $wpdb->postmeta . ' ON '. $wpdb->posts . '.ID = ' . $wpdb->postmeta . '.post_id ';

                }

              );


    add_filter( 'posts_where',

                function ( $where )

                {

                    global $wpdb;


                    $or = array(

                                    "(".$wpdb->posts.".post_title LIKE $1)",

                                    "(".$wpdb->postmeta.".meta_value LIKE $1)",

                               );


                    if ( is_main_query() && is_search() )

                    {

                        $where = preg_replace(

                                                "/\(\s*".$wpdb->posts.".post_title\s+LIKE\s*(\'[^\']+\')\s*\)/",

                                                implode( ' OR ', $or ),

                                                $where

                                             );

                    }

                    return $where;

                }

              );


    add_filter( 'posts_distinct',

                function ()

                {

                    global $wpdb;

                    return "DISTINCT";

                }

              );

}

add_action( 'pre_get_posts', 'AddCustomFieldsToSearchText', 9 );

Now, for the excerpt,  you need to make sure it is enabled/supported (PODS Advanced).  That adds the field allowing you to manually enter it, but we will automatically add it after the POD (page) is saved.

In the following code, I use a PODS-specific hook but with a little variation to the code, you could also use the WordPress "save_post" hook:


//==============================================

function PLANT_post_save_function($pieces, $is_new_item, $PlantId)

// https://stackoverflow.com/questions/38049208/set-wordpress-excerpt-and-post-thumbnail-based-on-custom-field

//==============================================

{

    //$post_excerpt   = get_the_excerpt( $PlantId );               //Get Excerpt


    //--- Work out the New Excerpt ------------------------------------------

    $PrevBotanicalNames = $pieces['fields']['plant_previous_botanical_names']['value'];

    $CnArray            = $pieces['fields']['plant_common_names']['value'];

    $Size               = trim( $pieces['fields']['plant_size']['value'] );

    $Flowers            = trim( $pieces['fields']['plant_flowers']['value'] );

    $GeneralComments    = trim( $pieces['fields']['plant_general_comments']['value'] );

    $AKA                = PlantAKA($PrevBotanicalNames, $CnArray);

    $NE = "Australian native plant";

    if  ($AKA != '')

        $NE = 'An ' . $NE . ', also known as: <b>' . $AKA . '</b>';

    if  ($Size != '')

        $NE = $NE . '<br><b>SIZE:</b> ' . $Size;

    if  ($Flowers != '')

        $NE = $NE . '<br><b>FLOWERS:</b> ' . $Flowers;

    if  ($Flowers != '')

        $NE = $NE . '<br><b>COMMENTS:</b> ' . $GeneralComments;


    //--- Set up the array to save the Excerpt ------------------------------

    $post_array = array(

                            'ID'            => $PlantId,

                            'post_excerpt'  => $NE,

                       );



    //--- Saving ------------------------------------------------------------

    remove_action('pods_api_post_save_pod_item_plant', 'PLANT_post_save_function');

                    wp_update_post( $post_array );

    add_action('pods_api_post_save_pod_item_plant', 'PLANT_post_save_function', 10, 3);

}

add_action('pods_api_post_save_pod_item_plant', 'PLANT_post_save_function', 10, 3);