Test BenjaminRojas.net | Development Blog

Using/Updating wp_localize_script() Dynamically

One of the greatest features of WordPress is its built-in function library that allows so much flexibility in web design.  Whether you are a plugin developer or theme designer, WordPress has functions that make your life a heck of a lot easier.

On occasion though, some of the functions that are super cool, could sometimes use a little tweaking. One of those functions is wp_localize_script().

Simply put, wp_localize_script: “Localizes a script, but only if script has already been added. Can also be used to include arbitrary Javascript data in a page.”

I usually find myself adding in “arbitrary Javascript data” in the page alongside my localization strings if they are needed at all.  A sample of the code used to generate the localized script looks like this:

1
2
3
4
5
6
7
<?php
$localized_data = array(
  'hello' => __('Hello'),
  'world' => __('world')
);
wp_localize_script('enqueued-script', 'obj', $localized_data);
?>

Note that this function calls a previously enqueued script which is not covered in this tutorial.

WordPress will then print onto the final page a Javascript object that will look like this:

1
2
3
4
5
<script type='text/javascript'>
/* <![CDATA[ */
var obj = {"hello":"Hello","world":"world"};
/* ]]> */
</script>

From time to time, I have wanted to add in an element to this object dynamically, but if I decided to localize the script again prior to the page load, the output would look like this:

1
2
3
4
5
6
<script type='text/javascript'>
/* <![CDATA[ */
var obj = {"hello":"Hello","world":"world"};
var obj = {"hello":"Hello","world":"world","exclamation":"!"};
/* ]]> */
</script>

wp_localize_script just adds the new data as a new line item regardless of whether or not the objects are the same. This is not ideal especially if there is the chance that it could grow any larger than just three elements in the object.

After much searching, I came up with a solution that does not require any hacking or changing of the WordPress core (yay!) and is actually fairly simple to implement.

First, before we call our wp_localize_script function, we need to check and see if any localized data exists in our script that we have already enqueued. To do that, we must access the global $wp_scripts; object and use the get_data() function:

1
2
global $wp_scripts;
$data = $wp_scripts->get_data('obj', 'data');

If the data is empty, we can go ahead and localize our script:

1
2
3
if(empty($data)) {
  wp_localize_script('enqueued-script', 'obj', $localized_data);
}

However, if we have already localized the script and some data exists, we need to convert that into some useable data and add to it before putting it back. First, we are going to check if $data is an array. If not, lets convert it from the JSON format that it exists in. We will need to remove the last semicolon character and the “var obj = ” intro in order to convert it:

1
2
3
if(!is_array($data)) {
  $data = json_decode(str_replace('var obj = ', '', substr($data, 0, -1)), true);
}

Then we can add the existing elements to our new array:

1
2
3
foreach($data as $key => $value) {
  $localized_data[$key] = $value;
}

Finally, we need to empty out the data that is currently localized and then localize our new array:

1
2
$wp_scripts->add_data('enqueued-script', 'data', '');
wp_localize_script('enqueued-script', 'obj', $localized_data);

Altogether, this looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
global $wp_scripts;
$data = $wp_scripts->get_data('enqueued-script', 'data');
if(empty($data)) {
  wp_localize_script('enqueued-script', 'obj', $localized_data);
}
else {
  if(!is_array($data)) {
    $data = json_decode(str_replace('var obj = ', '', substr($data, 0, -1)), true);
  }
  foreach($data as $key => $value) {
    $localized_data[$key] = $value;
  }
  $wp_scripts->add_data('enqueued-script', 'data', '');
  wp_localize_script('enqueued-script', 'obj', $localized_data);
}
?>

In my example, the new Javascript object would look like this:

1
2
3
4
5
<script type='text/javascript'>
/* <![CDATA[ */
var obj = {"hello":"Hello","world":"world","exclamation":"!"};
/* ]]> */
</script>

Let me know if this helps you out in any way!

Posted in PHP, WordPress

Configuring Postfix to Send Mail from Mac OS X Mountain Lion

I recently upgraded my Mac to use Apple’s latest operating system, Mountain Lion, and in so doing, wiped out my postfix configuration that I had previously set up with advice from many different blogs. Postfix is essential for my line of business where I send many emails through MAMP on my local machine.

After hours of updating settings and getting nowhere, I stumbled across a blog post that set me in the right direction.

Rather than do this process again when Apple releases a new upgrade, I decided to document the steps I took to get this working (more for a reference for myself, but also to help those with the same issues).

I personally use Google Apps, so this process is for those also trying to authenticate through Gmail.  This process is much simpler if you don’t need SSL encryption when sending mail.  I use TextMate as a text editor, so the following command line options use the ‘mate’ command.  Alternatively, you can use ‘vi’, ‘vim’ or ‘nano’ depending on what you are familiar with.

Step 1

First, we need to create a Simple Authentication and Security Layer (SASL) password file.  To do this, open up Terminal and enter in the following command:

1
sudo mate /etc/postfix/sasl_passwd

You will be required to enter your root password to edit the file. Enter in the following information, replacing <username@domain.com> with your google apps username and domain or your gmail account, and <password> with your password:

Save and exit.

Step 2

Next, we need to create a postfix lookup for our new SASL password file.  To do this, type the following command in the Terminal:

1
sudo postmap /etc/postfix/sasl_passwd

Step 3

Then we need to configure Postfix’s main.cf file which has all the configuration information for Postfix.  I would recommend backing up this file in case anything happens.  The first line of the following commands does just that, by creating a copy before editing it:

1
2
sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
sudo mate /etc/postfix/main.cf

Most of the information here is commented out.  You just need to scroll down to the bottom and paste in the following lines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Minimum Postfix-specific configurations.
mydomain_fallback = localhost
mail_owner = _postfix
setgid_group = _postdrop
relayhost=smtp.gmail.com:587

# Enable SASL authentication in the Postfix SMTP client.
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options=

# Enable Transport Layer Security (TLS), i.e. SSL.
smtp_use_tls=yes
smtp_tls_security_level=encrypt
tls_random_source=dev:/dev/urandom

Save and exit.

Step 4

At this point, we just need to start up Postfix with our changes.  Use the following command:

1
sudo postfix start

If you entered in any information incorrectly in the main.cf file, this may throw errors.  Fix the errors and then reload Postfix:

1
sudo postfix reload

Step 5

You can test this configuration by sending a test email from Terminal:

1
date | mail -s test youremailaddress@yourdomain.com

If all goes well, you should receive an email to your inbox.

Step 6

Once you have everything working, you can set Postfix to start on boot by adding a key to /System/Library/ LaunchDaemons/org.postfix.master.plist file.

The key to add is:

1
2
<key>RunAtLoad</key>
<true/>

The updated file looks like this (text version below):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>org.postfix.master</string>
  <key>Program</key>
  <string>/usr/libexec/postfix/master</string>
  <key>ProgramArguments</key>
  <array>
    <string>master</string>
    <string>-e</string>
    <string>60</string>
  </array>
  <key>QueueDirectories</key>
  <array>
    <string>/var/spool/postfix/maildrop</string>
  </array>
  <key>AbandonProcessGroup</key>
  <true/>
  <key>OnDemand</key>
  <true/>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

And that’s it! You should now be able to send mail using Mac OS X and Postfix from a PHP install. I am not an expert at this by any means, but feel free to leave a comment below letting me know if this helped you or if you have any issues with it. I would be glad to help in any way I can!

Posted in Email, Mac, MAMP, Postfix

View MAMP Virtual Hosts On Your iPad and iPhone Over The Local Network

When developing sites for mobile devices, I have often wanted a way to view my MAMP virtual hosts on my iPad or iPhone without having to upload the site to a live domain. In the past, I have used CNAME redirects to point specific domain names to my local computer, to help with this issue, but DNS propagation usually takes 24 hours and I usually need to develop my sites sooner than I can wait.

I recently moved to a new location and my ISP prevents this from working for local devices, based on the router they provided for me, so I set out to find a new way to make this happen.

Enter: SquidMan.

From the website: SquidMan is a MacOS X graphical installer and manager for the Squid proxy cache. It is designed to operate as a “personal” proxy server.

When you run Squid on a MacOS X computer, it can:

  • cache downloaded content, reducing network traffic and improving browsing performance on slow links
  • act as a proxy server for other computers on your subnet
  • restore the operation of some MacOS X applications that normally fail through authenticated proxy servers

The part I was most interested in was the proxy server. I figured that if I could create the host redirect on my local machine, and then use my iPhone and iPad to connect to it directly, I would be able to view my virtual hosts on my development machine, since all traffic would be routed through that location. I was right. Here are the steps I took to accomplish this:

1. Install and Configure SquidMan.

Installation of SquidMan is very easy and does include the Squid proxy server, so you don’t need to download it separately. The first screen to appear was the preferences pane. The default port is 8080 and this is what I left it at. You can change this to suit your needs.

The only other tab you need to alter is the Clients tab. You want to restrict the use of this proxy to members of your local subnet to prevent outside access to your proxy server. Just click on the clients tab and set up the options based on the instructions next to it.  I set mine up to work for any computer connected to my local network.

Once you have finished that, save and then start your server.

2. Set up the Proxy on the iOS devices.

On my iPad and iPhone I then set up the new proxy server.  I went to the Wi-Fi tab and then selected my local network.  I then set the HTTP Proxy to “Manual”.  In the server field I used the IP address of my local machine, and then I added the port from the SquidMan settings.

From this point if you can browse the web, you have successfully connected your device to the proxy.  For my installation however, there was still one more step I needed to do to finish this setup.

3.  Add IP address to virtual host inside MAMP.

When trying to access my virtual hosts via the hostname set up inside MAMP, I would receive an access denied error message.

I found an easy fix to this by visiting my MAMP settings and adding the IP address of my localhost in the IP/Port settings of the virtual host.  For some reason, MAMP does not seem to like IP Addresses that have 0′s in them.  If your subnet range is like mine, you will see the red exclamation mark next to the IP address.  You will also not be able to type in the address directly, but will need to select it from the drop down list. You can then apply your settings and restart the SquidMan server for it to take effect.  NOTE: If you are unable to apply your settings, visit the MAMP preferences and select the option to allow apply when the IP of a host isn’t valid.

After saving and restarting both MAMP and SquidMan, I was able to view my virtual host on the iPad.

 

Tagged with: , , , , , , , ,
Posted in iOS, iPad, iPhone, MAMP

WordPress 3.3+ Toolbar Removal

I am currently in the middle of a project creating a user database in WordPress and I needed to remove the toolbar on the front end of the website so that users didn’t have access to it. This process is very simple to do.

The basic function that accomplishes this is:

1
<?php show_admin_bar(false); ?>

You can add this to your functions.php file, or anywhere in your theme above the wp_footer() function.

If you want to use this only for specific roles, try the following example:

1
2
3
4
5
<?php
if(!current_user_can('manage_options') {
  show_admin_bar(false);
}
?>

Alternatively, you can create a function to do this if you are developing a plugin, etc.

1
2
3
4
5
6
<?php
function my_function_admin_bar(){
  return false;
}
add_filter('show_admin_bar' , 'my_function_admin_bar');
?>

The only remaining issue with this fix is that there is still a 28px margin at the top of the page that WordPress adds to make space for the admin bar. The best way to remove this is to add a callback to the admin-bar function to remove this space. You should add this into your themes function.php file directly:

1
2
3
<?php
add_theme_support('admin-bar', array('callback' => '__return_false'));
?>

As a closing note, these methods only work on the toolbar on front end of your site, not on the backend.

Posted in WordPress

Displaying WordPress Shortcodes Without Executing Them

While developing for WordPress, there is always a need to write up tutorials that explain how features work. One feature that is especially hard to document, is shortcodes. Why? because when you try to display the shortcode on your post or page, it tries to execute it.

The solution that WordPress offers, which is by far the simplest is to add an extra set of brackets around the shortcode.

1
[[shortcode_example]]

Unfortunately, this has been known to not work when multiple examples are used in a single post or when using opening and closing shortcodes.

A workaround can be found using the <code> tag.

1
<code>[</code><code>shortcode_example]</code>

By separating out the first bracket, WordPress is unable to execute the shortcode inside and instead displays it for all to see.

Posted in WordPress

Development Blog

Hello everyone,

Thanks for stopping by.  This blog has been a long time in coming.  My intentions are to use this as a development blog to post snippets of things I learn as I continue to work in web design.  Primarily, I will be posting about PHP, MySQL, Javascript, jQuery, AJAX, CSS and HTML.  You may find a few other things here as I find something interesting that ties into one of the former categories, but I may also decide to just post something random.  Who knows.  I guess you will just have to wait and see, right?

Well, that’s all for now.

-Benjamin

1
2
3
<?php
  echo 'hello world';
?>
Posted in General
Twitter Feed