Web Development

WordPress make_clickable() usage tips (Updated)

WordPress Tips

Update: I updated “echo” in the code below with “return” because it seems that the add_filter function will output duplicated content with the echo statement.

make_clickable() function is used to convert a text URL in the provided string into a link (make it clickable). It’s one of the useful functions in WordPress.

However, it can ruin your site if you use other features of WordPress, such as shortcodes. As it will convert any string that contains URL to a clickable link, including the URL in shortcodes, make the shortcodes invalid.

In order to ignore the URL in shortcodes, you need to generate the code from the shortcodes before converting any URL. Here is the code for it:

function mc_ignore_shortcode($content) {
	$content = do_shortcode($content);
	return make_clickable($content);
}

add_filter( 'the_content', 'mc_ignore_shortcode' );

It’s also missing a feature to make the external websites open in a new tab/window. I don’t know why, but I assume that all the text URL is from external websites (meaning outside of your website), here is the code for making all the links converted by this function open in a new tab/window (original code from this gist):

function blank_link($content) {
	return preg_replace('/<a /','<a target="_blank" ', make_clickable($content));
}

add_filter( 'the_content', 'blank_link' );

make_clickable() is an useful WordPress function. These two tips should help you to make make_clickable() function even more useful.

Prevent Tab Closing with an Userscript

userscripts

While it’s impossible to prevent close of tab directly using JavaScript, we can at least remind ourselves do not close the current open tab when pressing the CMD + W close tab keyboard shortcut.

Add the following script to either Greasemonkey for Firefox or Tampermonkey for Chrome on the site you want the reminder to appear:

// ==UserScript==
// @name       Always Google Calendar
// @namespace  http://blog.robbychen.com
// @version    0.1
// @description  Prevent close the Google Calendar window through keyboard shortcut
// @match      https://www.google.com/calendar/render
// @copyright  2014, Robby Chen
// @require    http://code.jquery.com/jquery-latest.min.js
// ==/UserScript==

$(document).ready(function() {
    $(document).on("keydown", function(e) {
        if (e.keyCode == "87" || e.keyCode == "93") {
            alert("Do not close this window. If you want to refresh this window, press Left command key and R.");
        }
    });
});

For the above code, change the meta information between “// ==UserScript==” as appropriate. Here is the documentation of the @ headers for Tampermonkey. It should be the same as Greasemonkey.

You can add the following code to the “keydown” event to display the keycode in the JavaScript Console for the specific key you would like to use instead of the W (87) and right CMD (93) keys in the code:

console.log(e.keyCode);

You can also change the reminder message to be displayed when the specified key is pressed by modifying the alert message. If you don’t like alert box, you can display the alert message to any exist element on the page. However, I find that the alert box is most useful reminder method.

Exclude stylesheet in Frontend for admin in WordPress

WordPress Tips

While is_admin() function works great within the backend, using this function in frontend will always return false. For example, consider the following sample code:

if (is_admin()):
	echo "is admin";
else:
	echo "not admin";
endif;

It will display “not admin” in the frontend (such as your homepage). When in the backend (such as WordPress admin) and whether you logged in as an administrator or not, it will display “is admin”.

In order to change layout for certain elements in frontend for non-administrators, you need to use current_user_can() function:

function custom_scripts() {
	if (!current_user_can("administrator")):
		wp_enqueue_style("noAdmin_style", plugins_url("notAdmin.css", __FILE__));
	endif;
}

add_action("wp_enqueue_scripts", "custom_scripts");

Note that if you placed current_user_can() if statement outside of a function and without any hook, it will display a fatal error which is discussed in this article.

Feel free to leave a comment below regarding the use of current_user_can() function.

Two Quick Sublime Text Tips

Sublime Text tips

After a long time, I decided to switch back from Coda to using Sublime Text as my main IDE because it has more customize options. Here are two of the quick tips I found during the setup of Sublime Text:

User Settings

By reading through the default settings in Preferences -> Settings – Default, you can see many useful settings which can be modified. Copy the lines on which the settings you wish to be modified, paste into Preferences -> Settings – User, and modify them from there.

Here are my user settings for Sublime Text:

{
	"font_size": 20.0,
	"highlight_modified_tabs": true,
	"indent_to_bracket": true,
	"spell_check": true,
	"tab_size": 2,
	"word_wrap": true
}

Note that normally when you modified a file in Sublime Text, there will be a filled circle replacing the close button on the tab of modified file. With “highlight_modified_tabs” on, not only does it have the filled circle, the tab also changes color.

highlight_modified_tabs in Sublime Text

Once the user settings are saved, the change is immediate. No restart of Sublime Text is needed.

Move User packages folder

One of the benefits of using Sublime Text is that just like Linux, everything is a file, including its settings. On top of that, most changes modified by you is stored in the User folder inside the Packages folder in Sublime Text root folder (/Users/username/Library/Application Support/Sublime Text 2/Packages/User), such as installing a package and adding a snippet. By using this advantage, you can move the User folder to another location (such as an external hard drive or Dropbox folder) and link to it.

Type the following command into the terminal:

ln -s ~/Development/Sublime/Packages/User "/Users/username/Library/Application Support/Sublime Text 2/Packages"

Replace “~/Development/Sublime/Packages/User” to the location you saved the folder to, as well as “username” with your username. Note that you must move the User folder to your desired location first.

As of this writing, I haven’t found a way to link the file using a File Manager.

Make alias in Finder

The Make Alias command in Finder for Mac does not work for this operation.

Please leave a comment below if you have a GUI way of link the User folder successfully.

Do you have any other tips on Sublime Text? Please share them in the comment below.

Access PHP values within JavaScript in WordPress

WordPress JavaScript

When using JavaScript to access PHP values in WordPress, the official way, according to the WordPress Codex, is

<?php

// Register the script first.
wp_register_script( 'some_handle', 'path/to/myscript.js' );

// Now we can localize the script with our data.
$translation_array = array( 'some_string' => __( 'Some string to translate' ), 'a_value' => '10' );
wp_localize_script( 'some_handle', 'object_name', $translation_array );

// The script can be enqueued now or later.
wp_enqueue_script( 'some_handle' );

?>

And then using JavaScript OOP method to access the variable:

<script>
    alert( object_name.some_string) ; // alerts 'Some string to translate'
</script>

I know that the PHP function is used for translating the values across different languages (such as English to French), and for transferring multiple values to JS as well. However, for transferring simple value such as the location of a file in a plugin and some numbers, you can use inline JS directly.

	// Pass the PHP variables to JS
function js_vars() {
?>
	<script type="text/javascript">
		var dir = "<?php echo plugins_url("", __FILE__); ?>";
	</script>
<?php
}

add_action("wp_head", "js_vars");
?>

And you can access the variable(s) in JS:

$(".ast_gplus img").attr("src", dir + "/Google.png");

Of course, you need to use wp_localize_script PHP function if you follow OOP (Object Oriented Programming) practice.

Have you used wp_localize_script before to transfer such simple values to JavaScript? And for what reason, code consistency by using OOP, have many variables to transfer to JavaScript, or else?

Modifying Woocommerce Templates within a plugin

Woocommerce

Woocommerce template files are located in wp-content/plugins/woocommerce/template, and can only be accessed within a theme or a child theme. However, in order to preserve the original data on the site, the solution to access the templates through a plugin must be found.

Fortunately, there is already an existing code that can do exactly that. Here is the original unmodified code copied from the article:


<?php
function myplugin_plugin_path() {
  // gets the absolute path to this plugin directory
  return untrailingslashit( plugin_dir_path( __FILE__ ) );
}

add_filter( 'woocommerce_locate_template', 'myplugin_woocommerce_locate_template', 10, 3 );

function myplugin_woocommerce_locate_template( $template, $template_name, $template_path ) {
  global $woocommerce;
  $_template = $template;
  if ( ! $template_path ) $template_path = $woocommerce->template_url;
  $plugin_path  = myplugin_plugin_path() . '/woocommerce/';

  // Look within passed path within the theme - this is priority
  $template = locate_template(
    array(
      $template_path . $template_name,
      $template_name
    )
  );

  // Modification: Get the template from this plugin, if it exists
  if ( ! $template && file_exists( $plugin_path . $template_name ) )
    $template = $plugin_path . $template_name;

  // Use default template
  if ( ! $template )
    $template = $_template;

	// Return what we found
  return $template;
}
?>

In case you forgot what’s included in the templates or you are just learning to modify the Woocommerce templates, you can copy the entire templates directory under wp-content/plugins/woocommerce/ to the woocommerce subdirectory in your plugin folder. That way, you will know which file is related to which part of Woocommerce generated page without moving back and forth between woocommerce plugin’s folder and yours.

Is this function ever useful to you? Do you prefer to use Woocommerce templates within a custom/child theme or a plugin? Discuss in the comments section below.

Why create a WordPress Plugin instead of a Child Theme

Plugin vs Child Theme

Lately there is a debate about data portability in WordPress community. Normally I don’t care about this type of discussion on WordPress, until I had a client that uses a theme which contains too many custom post types. On top of that, their old coder modified the theme directly in the theme files without creating a child theme as well as modifying original plugin files.

At beginning of the project, I created a child theme to see if it works fine with the current theme. During that time, I don’t know what’s the fuss about data portability. Perhaps because of my ignorance about this concept, most of the theme-related data was lost in the frontend when switching to the child theme.

I warned about the data loss due to theme change to the client. However, I decided to switch back to the parent theme and stick to it for the rest of the project since the client mentioned that the previous coder already modified the original theme.

At that time while struggling to think of a way to modify the styles without modifying the original theme files despite they were already modified, I remembered the concept of data portability.

Data portability, to me, means to retain the already existing data (such as an installed theme with populated data), manipulating them and adding the new data on the site. It basically is a plugin to add a new layer to the site for adding extra features.

So my WordPress plugin development journey for the client’s website began. This actually was my first very own plugin. Before that, I never wrote a plugin from scratch, just edited someone else’s plugins.

At the beginning, I created two files besides the plugin’s main PHP file: style.css and script.js, and added them to the main PHP file using enqueue_scripts function and hook. The style.css was used to change the look of the site, and the script.js was used to modify the content on the site. I know that I can use add_filter function to modify the content. However, I didn’t know much about the add_filter hooks at that time. Later, I added some more files to the plugin based on client’s requirement.

In conclusion, here are the reasons why you should choose to write a site-specific plugin instead of a custom theme: a large amount of data already populated within the current theme and you don’t want to import duplicated data into the child theme, data created using the plugin will transfer to the new theme whenever the client decides to switch theme. However, there are sometimes that a child theme is better for the site, such as a new site or theme that doesn’t have any theme-related data yet, a simple (no custom post type and no option) theme, and a theme framework such as Genesis Framework.

What do you think? Which is better for a site-modification project, a site-specific plugin or a child theme? Discuss in the comments section below.

Inactive Plugin Issue

WordPress Plugin

Because of my recent experiment of Wordfence Falcon Engine, I deactivated W3 Total Cache and iTheme Security plugins and forgot about it. Until I ran into problem with the homepage. During the development of the site, I want to look how the recent installed plugins behave on the homepage. So I opened a new private Chrome window, and I was surprised to see that my old theme was still active on the site along with some deactivated plugins. I looked around and discovered that only the homepage was affected by this problem, the single post page and other pages were working normally with the new theme.

I searched around online and found out that the only cache-related plugins can cause this issue. Currently I only use one caching plugin which is Wordfence Falcon Engine, and CloudFlare caching feature. I disabled them one by one, but it’s still showing the old theme. And then I remembered there is another caching plugin I didn’t test yet, that is W3 Total Cache.

Of course I deactivated this plugin during the Falcon Engine experiment, but I only deactivated it without any modification, meaning that I didn’t disable any of the caching features of the plugin before I deactivated it. I thought that the plugin was still active somewhere on this site.

But I can’t just delete the plugin and hope that the issue will be solved. By following the steps in this post, I made sure that W3 Total Cache has been completely removed from the site.

Now that the homepage displays normally, I can enable CloudFlare and Falcon Engine for this site.

Note that if you also experience this issue and will not use W3 Total Cache in the future, I recommend you to also remove any of the database tables generated by W3 Total Cache if there is any. To remove them, install the Plugins Garbage Collector through the plugins page in WordPress admin and use it to remove any database tables generated by this plugin and other plugins you deleted.

A Quick PHP array Tip

PHP

Here is a small tip for the nested arrays in PHP.

When using nested arrays, make sure not to include an array in a key. Only include an array in a value.

For instance, the following code results in the “illegal offset type” error:

$fruits = array("apple", "banana", array("good", "well")=>"pineapple");

Here, the problem is in the third pair of the fruits array. Here is the right way to do it:

$fruits = array("apple", "banana", "pineapple"=>array("good", "well"));

Have you experienced this issue before, or did you already know this type of error?