Wordpress breaks hyperlinks stored with the Options API - php

I have a Wordpress theme that stores a copyright line in a Wordpress option using the update_option function. In the text, I am including a link back to my website.
Copyright © 2015 ABC Company, Inc. Site design by My Company.
That information is then retrieved in the theme's footer.
<p id="footer-copyright"><?php echo get_option('copyright'); ?></p>
However, the link appears as http://www.blogsite.com/"http://www.example.com/". I am assuming that internally Wordpress is trying to create an absolute url from what it believes to be a page slug. How can I stop this behavior? I have examined the get_options function defined in wp-includes/options.php and determined that it is not the problem. The problem is occurring later in the theme processing.
Edit:
Per David's suggestion, I have check the DB. The value of this option is being altered before being written. HTML entities are being parsed and quotes are being escaped. Here is the actual value in the DB.
Copyright © 2015 ABC Company, Inc. All rights reserved. Site design by My Company.
When I manually correct this in the DB, it displays fine. Wordpress is performing some sort of post processing or parsing before writing the option value to the DB.

Wordpress unnecessarily escapes quotes in the option value during it's sanitizing process. The easiest solution is to use the pre_update_option_(option name) hook to process and remove the unnecessary escape characters before the value is written to the database. This hook can be implemented in your theme's functions.php file. (NAME in all caps should be replaced by the name of the option defined elsewhere in the update_option function.
function myplugin_update_option_NAME( $new_value, $old_value ) {
$new_value = str_replace('\"', '"', $new_value); // replaces \" with "
return $new_value;
}
function myplugin_init() {
add_filter( 'pre_update_option_NAME', 'myplugin_update_option_NAME', 10, 2 );
}
add_action( 'init', 'myplugin_init' );
I've intentionally avoided using PHP's stripslashes function in order to keep the code simple and avoid checking for magic quotes.
Wordpress is not actually prepending anything to the hyperlink destination. However, because the hyperlink is not recognized with escaped quotes, it is treated as though it were a relative link causing the described behavior.

Related

WordPress esc_attr returns empty string

I have a form with an input name="title" and in functions.php I'm simply getting all the data from that form
Here's the code:
$title = $_POST['title'];
print_r($_POST);
var_dump($title);
var_dump(esc_attr($title));
The expected outcome would be the same string, but, I have no idea why, WordPress shows an empty string on the esc_attr one
Here's the output:
Array ( [title] => Swedish House Mafia – Doooon\'t You Worry Child ft. John Martin )
string(63) "Swedish House Mafia – Doooon\'t You Worry Child ft. John Martin"
string(0) ""
It's not related to the input field being called title or the variable being called $title and conflicting with other stuff in WordPress, I have no idea why the escape functions are not working.
Let's walk through the thought process of what might be a contributor to this problem.
With the code as presented, nothing in your code is affecting the variable or $_POST. You are just echoing out each variable one after the other (as you presented above).
That means something is wonky with esc_attr. What could the possibilities be:
The function is not available yet.
Something is overriding the returned value and behavior.
Possibility 1 is not feasible because you are working in the theme's function.php file. WordPress has loaded the escaping functions by the time the theme is called. To check that, you can do:
echo function_exists( 'esc_attr' ) ? 'yes, loaded' : 'whoops, not loaded';
That leaves us with Possibility 2. Let's look at the function in WordPress Core.
function esc_attr( $text ) {
$safe_text = wp_check_invalid_utf8( $text );
$safe_text = _wp_specialchars( $safe_text, ENT_QUOTES );
/**
* Filters a string cleaned and escaped for output in an HTML attribute.
*
* Text passed to esc_attr() is stripped of invalid or special characters
* before output.
*
* #since 2.0.6
*
* #param string $safe_text The text after it has been escaped.
* #param string $text The text prior to being escaped.
*/
return apply_filters( 'attribute_escape', $safe_text, $text );
}
There are 3 functions that interact with the text. I don't see anything in the first two. However, look at the filter event attribute_escape. Any other plugin or theme can register to that event and change the returned text, including returning an empty string.
That sounds like a highly probable candidate.
Next Steps
Something is stepping on (filtering) the text when it's passed through esc_attr(). You need to eliminate all variables, strip the site down to the bare bones basics, and then see if the problem resolves itself.
The following steps are a process to discover where the problem lies. It's an elimination methodology. As you walk through it, it'll help you to pinpoint what component (theme, plugin, or even core) is affecting it.
Step 1: Deactive ALL plugins
Step 2: Move your code to the top of the theme's functions.php file. Why? It eliminates anything in the theme from affecting the text as the functions.php file loads first.
Step 3: Manually add the title to $_POST['title']. Put as the first line in functions.php: $_POST['title'] = "Swedish House Mafia – Doooon't You Worry Child ft. John Martin";.
Step 4: Refresh the browser.
Is it working properly, meaning esc_attr() returns the string?
Nope, the problem is still happening.
Hum, that means something then in WordPress Core is not playing nice. You could investigate by digging into Core and finding what is causing the conflict. Or reload a fresh version of it.
Yes, the problem is gone
Add in one plugin at a time. Refresh the browser. Check if the problem reappears. If yes, then you found the plugin that is causing it.
Now what?
Once you find the culprit, you can take steps to fix the problem. Then you can remove the code from functions.php file that I had you add.
This might be edge case, but I had the same issue and the problem was with multibyte characters.
My code looked something like this: esc_attr( substr( $desc, 0, 152 ) )
Without esc_attr() it worked but I sometimes got the �-character. When running it through esc_attr() I got nothing back.
So my solution was to replace substr() with mb_substr(). Read about the difference in this answer.
Retrieve data with this code
echo esc_attr( $title );

Importing PHP string with quotes

So I'm importing ExpressionEngine fields into a php array. I want to display one field, called {gearboxx_body}, unless that field has more then 300 characters, in which case I want to display a field called {article_blurb}. I'm pretty sure there isn't a way to do this just in ExpressionEngine fields and conditionals, so I tried some PHP, which I'm just starting to learn:
<?php
$info = array('{gearboxx_body}','{article_blurb}');
if(mb_strlen($info[0]) <= 300)
echo($info[0]);
}
else {
echo($info[1]);
}
?>
So that works well, but there's a problem. If the tag includes any apostrophes or quote marks, it ends the string and the page won't load. So what can I do about this? I've tried to replace the quote marks in the string, but I have to have loaded the string from the fields first, and as soon as I do that the page is already broken.
Hopefully that made sense. Any suggestions?
I would recommend you handle this in an EE plugin rather than in the template:
Faster to render (because you don't need the overhead of PHP in the templates)
More secure and reliable
Faster to develop once you get the basics of EE development down which is a useful life skill
All around best-practice
The plugin I have in mind takes three parameters:
body, blurb and character limit.
Let's say you call your plugin "Blurby". In the template you would just have this:
{exp:blurby body="{gearboxx_body}" blurb="{article_blurb}" char_limit="300"}
It variably returns either of your fields based on the logic you define in the plugin itself.
See plugin developer documentation.
Alternatively you could use the dreaded HEREDOC syntax to set variables before passing them into your array:
$body = <<<EOT
{gearboxx_body}
EOT;
$blurb = <<<EOT
{article_blurb}
EOT;

PHP character encoding issue

When I grab the title from my Word Press posts in code and pass them around as email, the punctuation gets a bit mangled.
For example "TAMAGOTCHI P’S LOVE & MELODY SET" comes out as "TAMAGOTCHI P’S LOVE & MELODY SET".
Any ideas how I prevent this?
Let me know if you need to see the specific code I'm currently using. (I'm not really sure if this is a WordPress issue, or a PHP issue.
EDIT
What happens is that this title is passed to a form via the query string. Then when the form is submitted, I take the string from the form field and email it.
So I guess I need to decode the html either before I pass it into the form field, or else before I email it.
EDIT 2
Weird, so I looked closer at the code and I'm already doing a urldecode before I pass the value into the form field
jQuery('#product_name').val("<?php echo urldecode(strip_tags($_GET['pname'])); ?>
Is there some default encoding happening when you serialize (for ajax formhandler)
var dataString = $(this).serialize();
EDIT 3
OK turns out the code is more complex. Title is also passed to some kind of wordpress session before it's hits the form. I'll figure it out where exactly I need to put urldecode. Thanks!
This is one WordPress "feature" I could do without.
Here's one down-n-dirty method to get the fancy quotes (or other entities) replaced:
$title = get_the_title( get_the_ID() );
$title = str_replace( '&#8217', "'", $title );
echo $title;
We could integrate deeper, by hooking into the_title, if you want this same de-entities functionality throughout the site. This code block would belong in your theme's functions.php file.
function reform_title($title, $id) {
$title = str_replace( '&#8217', "'", $title );
return $title;
}
add_filter('the_title', 'reform_title', 10, 2);
Im not really sure about wordpress, but the issue itself its that the text its coming out as URLENCODE instead of a UTF-8 or other encode.
You have two options
When you receive the text you never turn it back to normal encoding (Which is weird as usually is de-encoded by php when you access the $_GET or $_POST variables)
You are parsing the message with the urlencode() function.

Tag Array Sorting issue

10/25/2012 - Still Not solved! Please see below:
My client has a WordPress Tag Cloud (tag array) with tags which include ["] character as well as [The] prefix for some tags. I.e:
"rose"
"autumn"
The Abby
The Cloud
The Elephant
Obviously all the tags enclosed in the quotations marks ["] are sorted on the top of the list and all the words starting with [The] prefix are sorted somewhere around the letter [T] (following the logical ASC order).
It was sprinkled on me that: "All tags (in the WP tag cloud) have to be ordered Ascending but those which contain the [" "] or [The] characters have to be sorted with all other tags in the chronological order, ignoring the ["] and [The] prefix.
I looked into the WP core function:
**function wp_generate_tag_cloud**
but I have no idea where to start. In the raw SQL statement, I could probably use the trim() to filter out the [" "] and [The] characters form the tag cloud array but that is only a thought which I have no idea how to apply.
wp_generate_tag_cloud() invokes a filter named tag_cloud_sort, which can override the sort order specified in the $args parameter. The tag_cloud_sort filter receives an array of tags and the actual $args parameter passed to wp_generate_tag_cloud(), so it can inspect the full settings of the wp_generate_tag_cloud() invocation and adjust its behavior accordingly.
You could try something like this:
function custom_tag_sort($tags, $args) {
if ($args['orderby'] != 'name') {
// do not reorder if sort order is not by name.
// wp_generate_tag_cloud() is smart enough to notice order
// is not changed and will proceed with its regular sort logic.
return $tags;
}
uasort($tags, 'custom_tag_sort_compare');
}
function custom_tag_sort_compare($a, $b) {
return strnatcasecmp(
custom_tag_sort_normalize($a->name),
custom_tag_sort_normalize($b->name)
);
}
function custom_tag_sort_normalize($tag) {
// strip quote marks
$tag = trim($tag, '"');
// strip leading definitive article
$tag = preg_replace('/^\s*the\s+/i', '', $tag);
return $tag;
}
add_filter('tag_cloud_sort', 'custom_tag_sort');
Disclaimer: I've written this after only a cursory inspection of the wp_generate_tag_cloud() function. I haven't tested it on a live WordPress installation; I have only verified that the sorting function works correctly on your sample tag cloud:
The Abby
"autumn"
The Cloud
The Elephant
"rose"
ok so you want to avoid modifying the core code of wordpress... when your client hits the update button after you told him not to, then your going to have to go in and mess with it again.. use action hooks instead. there is conveniently one for hooking into the output for the tag cloud function. add this to your themes functions file
function tagCloudFilter($tagCloudString, $args)
{
$tagCloudString = str_replace('The','', $tagCloudString);
$tagCloudString = str_replace('"','', $tagCloudString);
}
add_filter('wp_tag_cloud', 'tagCloudFilter', 10, 2);
That will atleast get rid of the stuff you dont want. as far as sorting it im not to sure but this should get you on your way. it may be easier to sort it with jquery
If you really want to modify the core code run a foreach loop in the tag array before its formatted and use the str_replaces from above in that loop.. The just run sort() on that array and you should be good. But if it were me i would go with the half solution and not have it alphabetized than to modify the wordpress core
Here's a thought:
you could copy the original tag_cloud function and create your own on your functions.php.
You make the changes you want to make and add this filter inside the function:
$return = apply_filters( 'YOUR_tag_cloud_function', $return, $args );
And then create the previous filter to add your function to the hook:
add_filter('wp_tag_cloud', 'YOUR_tag_cloud_function');
I don't know if it works, I didn't test it. What do you think?

What does the WordPress "_e()" function do?

I have these all over my theme, and when if I delete them, there nothing happens to the theme. What does it do? Should I leave them in or are they unnecessary? I want to optimize my site to load faster, so this is why I'm asking.
https://developer.wordpress.org/reference/functions/_e/
In WordPress, strings in the php files are marked for translation to other languages, and localization using two “tags” which are actually functions. They are:
__()
_e()
They are used for localization in WordPress themes. If you're only using one language for your theme, you don't need them.
These are for WordPress localization.
Here is their documentation: http://codex.wordpress.org/Function_Reference/_e
Also a few links on localization in general on WordPress to put the _e's in context:
http://make.wordpress.org/docs/plugin-developer-handbook/plugin-components/internationalization/
http://codex.wordpress.org/I18n_for_WordPress_Developers
It is a WordPress Function used for localization.
See the WordPress Docs for localization.
With this function you can output/assign "hardcoded" strings within your theme/plugin/code that are translateable (with .mo / .po files or plugins like WPML String Translation).
The function __( 'My Text', 'my-text-domain' ); assigns a string "My Text" that is translateable. 'my-text-domain' is the text-doamin the string is referenced to. This function does not echo anything!
The function _e( 'My Text', 'my-text-domain' ); is almost the same but it echoes your string directly.
WordPress Offers several other functions for localization, take a look into the Codex (link on top of my answer).
Those are WordPress library function used on localization in Wordpress themes. Its recommended to use escapes function as much as possible in theme and plugins for safety.
__() = Return the translated string
_e() = echo the translated string
esc_html__() = Escapes & return the translation string use in HTML output
esc_html_e() = Escapes & echo the translation string use in HTML output
esc_attr__() = Escapes & return the translation string use in an attribute
esc_attr_e() = Escapes & echo the translation string use in an attribute
_n() = Retrieve the plural or single form based on the amount.
_x() = Retrieve translated string with gettext context
_ex() = echo translated string with gettext context
esc_attr_x() = Escapes & return translated string with gettext context use in an attribute
esc_html_x() = Escapes & return translated string with gettext context use in HTML output
If you want echo the translated string, then you will be using _e and
when you just want to have the translated string, then you will be using __.
Actually, from my experience, I find that _e() is a function. It is similar to:
<?php function _e($txt) {
echo $txt;
}
It seems to me that if you eliminate it, you run the risk of your text not even showing up. From the uses I have seen, though, it is comments to the WordPress user to remind them to add information to the area, like the footer, header, or whatever. So eliminating may only remove all the hints the theme has built in for you.

Categories