WordPress custom function not passing Global Variables to other functions - php

I'm trying to pass Custom CSS in global variable to use it in another function then to pass it to wp_enqueue_scripts via wp_add_inline_style but the global variable whenever I use it as global it doesn't return anything only if i use add_action('wp_footer', 'my_function') below i'll show you my code and functions
I've tried many methods but still the same problem!
I use cru_generate_custom_style in many files to generate custom css for custom elements and based on WordPress you can’t run wp_add_inline_style anywhere else except wp_enqueue_scripts this is to eliminate errors on W3C and add inline style to wp_head
global $cru_bottom_styles;
$cru_bottom_styles = array();
function cru_generate_custom_style( $selector = '', $props = '', $media = '', $footer = true ) {
global $cru_bottom_styles;
$css = '';
// Selector Start
$css .= $selector . ' {' . PHP_EOL;
// Selector Properties
$css .= str_replace( ';', ';' . PHP_EOL, $props );
$css .= PHP_EOL . '}';
// Selector End
// Media Wrap
if ( trim( $media ) ) {
$css = "#media {$media} { {$css} }";
}
if ( ! $footer || defined( 'DOING_AJAX' ) ) {
echo "<style>{$css}</style>";
return;
}
$cru_bottom_styles[] = $css;
}
function cru_parse_header_styles() {
global $cru_bottom_styles;
print_r($cru_bottom_styles);
wp_add_inline_style( 'main', implode( PHP_EOL . PHP_EOL, $cru_bottom_styles ) );
}
add_action( 'wp_enqueue_scripts', 'cru_parse_header_styles' );

Related

Change the variable value in an other plugin function with PHP

I try to change a class, which is stored in a variable without making any changes in the plugin file. I'm not sure how to target the variable inside the function.
This is the function: function learndash_mark_complete( $post, $atts = array() ) { Inside this function, there is a variable called $button_class.
if ( isset( $atts['button']['class'] ) ) {
$button_class = ' class="learndash_mark_complete_button ' . esc_attr( $atts['button']['class'] ) . '" ';
} else {
$button_class = ' class="learndash_mark_complete_button" ';
}
Is there a simple way to change the code to..
if ( isset( $atts['button']['class'] ) ) {
$button_class = ' class="myclass' . esc_attr( $atts['button']['class'] ) . '" ';
} else {
$button_class = ' class="myclass" ';
}
without change the plugin file. Maybe to create a function in functions.php or in a seperate (new) plugin?
I saw articles on the internet about add_filter, but I'm not sure how to target the part I need without wipe the whole function.
I know I could change the class with jQuery or something, and maybe it should be a lot easier, but I like to learn new things.
If plugin does not provide filter hook to change the class name then you can not you filter value.
But, if you are writing your own plugin then you can use this type of logic to change the value without touching original source.
This code should be in the plugin file,
$arrayToFilter = array(
'class_name' => 'learndash_mark_complete_button',
'key1' => 'value1', // So on
);
$value = apply_filters( 'change_class', $arrayToFilter );
if ( isset( $atts['button']['class'] ) ) {
$button_class = ' class="'.$value['class_name'].'' . esc_attr( $atts['button']['class'] ) . '" ';
} else {
$button_class = ' class="'.$value['class_name'].'" ';
}
And add this filter into theme functions.php file to modify change_class hook's value
function example_callback($args) {
// Here you can get $arrayToFilter as $args
$args['class_name'] = 'myclass';
return $args;
}
add_filter( 'change_class', 'example_callback',10 , 1 ); // Where $priority is 10, $accepted_args is 1.
I hope you got basic idea of add_filter().

Function output not appearing in div

This is my first try at php.
Trying to create a custom shortcode in wordpress to call custom metadata and put it inside a page content. It worked fine without the
function wpsl_staff() {
echo '<div class="staff">' .wpsl_get_staff(). '</div>';
function wpsl_get_staff() {
and with the shortcode being
add_shortcode( 'wpsl_staff', 'wpsl_get_staff' );
The output was correct but the output appeared at the top of the page above all other content and when I inspected in the browser it had no div or class id and just appeared as text. How do I wrap this in a div and give id so it sits properly on the content page (It should display between 2 images and under another shortcode) I have managed to give it a class id previously and get it to appear in a div but the output still appears at the top of the page above the images and other shortcode.
<?php
function wpsl_get_staff() {
global $post;
$queried_object = get_queried_object();{
$Manager = get_post_meta( $queried_object->ID, 'wpsl_Manager', true );
if (!empty( $Manager )) return 'Manager : ' .$Manager . "<br>";
else {}
$Assitant = get_post_meta( $queried_object->ID, 'wpsl_Assistant_Manager', true );
if (!empty( $Assistant )) return 'Assistant Manager : ' .$assistant . "<br>";
else {}
$Agent = get_post_meta( $queried_object->ID, 'wpsl_Agent', true );
if (!empty( $Agent )) return 'Agent : ' .$Agent . "<br>";
else {}
}
}
function wpsl_staff() {
echo '<div class="staff">' .wpsl_get_staff(). '</div>';
}
add_shortcode( 'wpsl_staff', 'wpsl_dio_staff' );
Thanks
Toca
Shortcode functions are supposed to return the result, not directly output it.
function wpsl_staff() {
return '<div class="staff">' .wpsl_get_staff(). '</div>';
}
Edit: You can only return one value from a function - so if your wpsl_get_staff is supposed to return data for all three types, then you need to assemble that data into a string variable first, and then return that at the end of the function - something like this:
function wpsl_get_staff() {
global $post;
$queried_object = get_queried_object();
$output = '';
$Manager = get_post_meta( $queried_object->ID, 'wpsl_Manager', true );
if (!empty( $Manager )) {
$output .= 'Manager : ' .$Manager . "<br>";
}
$Assitant = get_post_meta( $queried_object->ID, 'wpsl_Assistant_Manager', true );
if (!empty( $Assistant )) {
$output .= 'Assistant Manager : ' .$assistant . "<br>";
}
$Agent = get_post_meta( $queried_object->ID, 'wpsl_Agent', true );
if (!empty( $Agent )) {
$output .= 'Agent : ' .$Agent . "<br>";
}
return $output;
}

How to print to console from a php file in wordpress

I have a php file which is part of a wordpress plugin. I need to debug an issue we are having. I want to find out what a variable's value is. How can I print the variable's value to console? echo or chrome or firefox extensions have been suggested. I couldn't get echo to output to console (echo β€œ$variablename";) and neither using the firephp extension for firefox.
To answer your question, you can do this:
echo '<script>console.log("PHP error: ' . $error . '")</script>';
but I would recommend doing one of the things #Ishas suggested instead. Make sure $error doesn't contain anything that can mess up your script.
If you are thinking about the javascript console, you can not do this from PHP.
You have a few options you could choose from:
echo
var_dump
create a log file
xdebug
For a quick check for a variables value I would use var_dump, it will also show you the data type of the variable. This will be output to the browser when you request the page.
Logging to the DevTools console from PHP in WordPress
Here you can see my solution for the problem in action while debugging coupon logic in WooCommerce. This solution is meant for debug purposes, only. (Note: Screenshot not up to date, it will also expose private members.)
Features
Allow printing before and after rendering has started
Works in front-end and back-end
Print any amount of variables
Encode arrays and objects
Expose private and protected members of objects
Also log to the log file
Safely and easily opt-out in the production environment (in case you keep the calls)
Print the caller class, function and hook (quality of life improvement)
Solution
wp-debug.php
function console_log(): string {
list( , $caller ) = debug_backtrace( false );
$action = current_action();
$encoded_args = [];
foreach ( func_get_args() as $arg ) try {
if ( is_object( $arg ) ) {
$extract_props = function( $obj ) use ( &$extract_props ): array {
$members = [];
$class = get_class( $obj );
foreach ( ( new ReflectionClass( $class ) )->getProperties() as $prop ) {
$prop->setAccessible( true );
$name = $prop->getName();
if ( isset( $obj->{$name} ) ) {
$value = $prop->getValue( $obj );
if ( is_array( $value ) ) {
$members[$name] = [];
foreach ( $value as $item ) {
if ( is_object( $item ) ) {
$itemArray = $extract_props( $item );
$members[$name][] = $itemArray;
} else {
$members[$name][] = $item;
}
}
} else if ( is_object( $value ) ) {
$members[$name] = $extract_props( $value );
} else $members[$name] = $value;
}
}
return $members;
};
$encoded_args[] = json_encode( $extract_props( $arg ) );
} else {
$encoded_args[] = json_encode( $arg );
}
} catch ( Exception $ex ) {
$encoded_args[] = '`' . print_r( $arg, true ) . '`';
}
$msg = '`πŸ“œ`, `'
. ( array_key_exists( 'class', $caller ) ? $caller['class'] : "\x3croot\x3e" )
. '\\\\'
. $caller['function'] . '()`, '
. ( strlen( $action ) > 0 ? '`πŸͺ`, `' . $action . '`, ' : '' )
. '` ➑️ `, ' . implode( ', ', $encoded_args );
$html = '<script type="text/javascript">console.log(' . $msg . ')</script>';
add_action( 'wp_enqueue_scripts', function() use ( $html ) {
echo $html;
} );
add_action( 'admin_enqueue_scripts', function() use ( $html ) {
echo $html;
} );
error_log( $msg );
return $html;
}
wp-config.php (partially)
// ...
define( 'WP_DEBUG', true );
// ...
/** Include WP debug helper */
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && file_exists( ABSPATH . 'wp-debug.php' ) ) {
include_once ABSPATH . 'wp-debug.php';
}
if ( ! function_exists( 'console_log' ) ) {
function console_log() {
}
}
/** Sets up WordPress vars and included files. */
require_once( ABSPATH . 'wp-settings.php' );
Usage
Before the HTML <head> is rendered:
console_log( $myObj, $myArray, 123, "test" );
After the HTML <head> is rendered (in templates, etc. / use when the above does not work):
echo console_log( $myObj, $myArray, 123, "test" );
Output format
πŸ“œ <caller class>\<caller function>() πŸͺ <caller action/hook> ➑️ <variables ...>
Special thanks to
Andre Medeiros for the property extraction method
You can write a utility function like this:
function prefix_console_log_message( $message ) {
$message = htmlspecialchars( stripslashes( $message ) );
//Replacing Quotes, so that it does not mess up the script
$message = str_replace( '"', "-", $message );
$message = str_replace( "'", "-", $message );
return "<script>console.log('{$message}')</script>";
}
The you may call the function like this:
echo prefix_console_log_message( "Error Message: This is really a 'unique' problem!" );
and this will output to console like this:
Error Message: This is really a -unique- problem!
Notice the quotes replaced with "-". It is done so that message does not mess up your script as pointed by #Josef-Engelfrost
You may also go one step further and do something like this:
function prefix_console_log_message( $message, $type = "log" ) {
$message_types = array( 'log', 'error', 'warn', 'info' );
$type = ( in_array( strtolower( $type ), $message_types ) ) ? strtolower( $type ) : $message_types[0];
$message = htmlspecialchars( stripslashes( $message ) );
//Replacing Quotes, so that it does not mess up the script
$message = str_replace( '"', "-", $message );
$message = str_replace( "'", "-", $message );
return "<script>console.{$type}('{$message}')</script>";
}
and call the function like this:
echo prefix_console_log_message( "Error Message: This is really a 'unique' problem!" , 'error');
It will output error in console.

Two different WordPress hooks with the same callback

I made a plugin that converts any uri to a hyperlink, if it finds hyper-link it will ignore it and only convert the no hyper-links uri.
In the plugin admin page I set two options, first to convert links only for the front-end, and the second option is to convert uri when ever a post/comment saved to database.
// permanently means before save to database
if ( $this->plugin_options['uri2links_convert_method'] == 'permanently' ) {
add_action( 'wp_insert_post_data', array($this, 'make_post_url_clickable' ) );
//add_action( 'preprocess_comment', array($this, 'make_comment_url_clickable' ) );
}
else {
add_filter( 'the_content', array($this, 'make_post_url_clickable' ) );
//add_filter( 'preprocess_comment', array($this, 'make_comment_url_clickable' ) );
}
My problem here if I set the plugin option to convert uri for front-end it will ignore hyper-links and convert the other uri, but if I set it to convert before save to database it 'll not ignore hyper-links and treat them as normal uri witch make the results look like this:
<a class="sdf" href=" <a href="http://test.test-75.1474.stackoverflow.com/" >http://test.test-75.1474.stackoverflow.com/ </a>
<a class="sdf" href=" <a href="https://www.stackoverflow.com" >https://www.stackoverflow.com </a>
The complete plugin source code:
<?php
/*
Plugin name: URIs to a click-able links
Plugin URI:
Description: Convert URI's to a click-able links
Author: h Abdou
Author URI: habdou.me
Version: 1.0
*/
// The admin page for the plugin
require_once( 'uri2links-menu.php' );
class Uri2Links {
protected $css = '';
protected $rel = '';
protected $target = '';
protected $convert_links = '';
protected $convert_emails = '';
protected $plugin_options = array();
protected $url_match_pattern = '/[a-zA-Z0-9\.\/\?\:#\-_=#]+\.([a-zA-Z0-9\.\/\?\:#\-_=#])+/';
protected $email_match_pattern = '/^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$/';
//protected $links_match_pattern = '/<a(?:"[^"]*"[\'"]*|\'[^\']*\'[\'"]*|[^\'">])+>^[a-zA-Z0-9_.+-]+#[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$<\/a>/';
protected $links_match_pattern = '/<a[^>]*>(.*?)<\/a>/';
protected $links_matched = array();
public function __construct() {
//$this->plugin_options = get_option( 'uri2links_plugin_options' );
$this->plugin_options = array( 'uri2links_convertLinksEmails' => array( 'Links', 'Emails' ), 'uri2links_convert_method' => 'permanently' );
$this->css = isset( $this->plugin_options['uri2links_custom_css'] ) ? ' class="' . $this->plugin_options['uri2links_custom_css'] . '"' : '';
$this->rel = isset( $this->plugin_options['uri2links_rel_attr'] ) ? ' rel="' . $this->plugin_options['uri2links_rel_attr'] . '"' : '';
if ( isset( $this->plugin_options['uri2links_open_links_method'] ) && $this->plugin_options['uri2links_open_links_method'] == 'new')
$this->target = ' target="_blank"';
$this->convert_links = isset( $this->plugin_options['uri2links_convertLinksEmails'][0] ) ? $this->plugin_options['uri2links_convertLinksEmails'][0] : '';
$this->convert_emails = isset( $this->plugin_options['uri2links_convertLinksEmails'][1] ) ? $this->plugin_options['uri2links_convertLinksEmails'][1] : '';
if ( $this->plugin_options['uri2links_convert_method'] == 'permanently' ) {
add_action( 'wp_insert_post_data', array($this, 'make_post_url_clickable' ) );
//add_action( 'preprocess_comment', array($this, 'make_comment_url_clickable' ) );
}
else {
add_filter( 'the_content', array($this, 'make_post_url_clickable' ) );
//add_filter( 'preprocess_comment', array($this, 'make_comment_url_clickable' ) );
}
// The admin page for the plugin
new Uri2LinksMenu;
}
// Convert all URI in a post to hyper-links.
public function make_post_url_clickable( $content ) {
$links = $this->hash_links( $content );
if ( $this->convert_links == 'Links' ) {
$content = preg_replace($this->url_match_pattern, ' <a href="\\0"' . $this->css . $this->rel . $this->target . ' >\\0</a> ', $content);
}
if ( $this->convert_emails == 'Emails' ) {
$content = preg_replace($this->email_match_pattern, ' <a href="mailto:\\0"' . $this->css . $this->rel . $this->target . ' >\\0</a> ', $content);
}
// Replace back the hashed 'a' tags to the original status.
foreach ( $links as $link_hash => $link_text ) {
$content = str_replace( $link_hash, $link_text, $content );
}
return $content;
}
// Same as 'make_post_url_clickable' but this for comments
public function make_comment_url_clickable( $content ) {
$links = hash_links( $content['comment_content']['comment_content'] );
if ( $this->convert_links == 'Links' ) {
$content['comment_content'] = preg_replace($this->url_match_pattern, ' <a href="\\0"' . $this->css . $this->rel . $this->target . ' >\\0</a> ', $content['comment_content']);
}
if ( $this->convert_emails == 'Emails' ) {
$content['comment_content'] = preg_replace($this->email_match_pattern, ' <a href="mailto:\\0"' . $this->css . $this->rel . $this->target . ' >\\0</a> ', $content['comment_content']);
}
foreach ( $links as $link_hash => $link_text ) {
$content['comment_content'] = str_replace( $link_hash, $link_text, $content['comment_content'] );
}
return $content;
}
// hash all 'a' tags so 'make_*_url_clickable' will ignore them.
public function hash_links( &$content ) {
$links = array();
if ( preg_match_all( $this->links_match_pattern, $content, $matches ) ) {
$array_size = sizeof( $matches[0] );
for ( $i = 0; $i < $array_size; ++$i ) {
$link_hash = md5( $matches[0][$i] );
$links[$link_hash] = $matches[0][$i];
$content = str_replace( $matches[0][$i], $link_hash, $content );
}
}
//die('hash_links called!');
return $links;
}
}
new Uri2Links;
?>
I just want to mention that WordPress already got the make_clickable() function that takes text uri to HTML links.
To activate it for the post content we only need this simple plugin:
<?php
/** Plugin Name: Make text uri to HTML links in the post content **/
add_filter( 'the_content', 'make_clickable', 9 );
By default this function runs on the comment text:
add_filter( 'comment_text', 'make_clickable', 9 );

Characters being replaced by bbcode plugin

I have a bbcode plugin for wordpress.
But for some reason, if I post something like
[i]v497212he2x2MfMi[/i] the "X" character is outputted as Γ—, which is some other sort of X. How can I fix this?
Plugin code is below:
class BBCode {
// Plugin initialization
function BBCode() {
// This version only supports WP 2.5+ (learn to upgrade please!)
if ( !function_exists('add_shortcode') ) return;
// Register the shortcodes
add_shortcode( 'b' , array(&$this, 'shortcode_bold') );
add_shortcode( 'i' , array(&$this, 'shortcode_italics') );
}
// No-name attribute fixing
function attributefix( $atts = array() ) {
if ( empty($atts[0]) ) return $atts;
if ( 0 !== preg_match( '#=("|\')(.*?)("|\')#', $atts[0], $match ) )
$atts[0] = $match[2];
return $atts;
}
// Bold shortcode
function shortcode_bold( $atts = array(), $content = NULL ) {
if ( NULL === $content ) return '';
return '<strong>' . do_shortcode( $content ) . '</strong>';
}
// Italics shortcode
function shortcode_italics( $atts = array(), $content = NULL ) {
if ( NULL === $content ) return '';
return '<em>' . do_shortcode( $content ) . '</em>';
}
}
// Start this plugin once all other plugins are fully loaded
add_action( 'plugins_loaded', create_function( '', 'global $BBCode; $BBCode = new BBCode();' ) );
This transformation is taking place because of Wordpress's wptexturize() function that returns given text with transformations of quotes to smart quotes, apostrophes, dashes, ellipses, the trademark symbol, and the multiplication symbol.
This is from WP 3.2.1 wp-includes/formatting.php line 55:
$dynamic_characters = array('/\'(\d\d(?:’|\')?s)/', '/\'(\d)/', '/(\s|\A|[([{<]|")\'/', '/(\d)"/', '/(\d)\'/', '/(\S)\'([^\'\s])/', '/(\s|\A|[([{<])"(?!\s)/', '/"(\s|\S|\Z)/', '/\'([\s.]|\Z)/', '/\b(\d+)x(\d+)\b/');
$dynamic_replacements = array('’$1','’$1', '$1β€˜', '$1β€³', '$1β€²', '$1’$2', '$1' . $opening_quote . '$2', $closing_quote . '$1', '’$1', '$1Γ—$2');
The last regex in that $dynamic_characters array is the one turning the "X" into Γ—
As stated on the function page for wptexturize... "[t]ext enclosed in the tags <pre>, <code>, <kbd>, <style>, <script>, <tt>, and [code] will be skipped.", you can fix this by putting that bbcode in one of those tags, or use a plugin that can disable wptexturize, such as InScript or Disabler or Disable wptexturize.

Categories