Restoring VVV functionality to Pressmatic

I switched from developing using Vagrant with VVV to using the new Mac app Pressmatic. I’ve been very happy, and so has my Mac—the dev environment runs much faster and my computer has been working a lot less. Less fan noise is good.

The server environment that Pressmatic uses don’t have some basic stuff that I needed to maintain compatibility with my setup. This is a running list of items that I’ll update as I come across more requirements:

  • wget
  • Subversion
apt-get install wget subversion curl php5-cli git
apt-get update

To set up unit testing, we’ll need to do a few more things. The following are taken from Tom McFarlin’s great article on unit testing with Pressmatic.

# Make sure required libraries are installed
apt-get install curl php5-cli git

# Install Composer
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Tell Composer what version of PHPUnit to run
composer global require "phpunit/phpunit=4.8.*"

# Tell the server where to find Composer
export PATH="$PATH:$HOME/.composer/vendor/bin"

Oh My Zsh!

I love Oh My Zsh; it’s a simple way to make your shell console a lot better. A big must-have for me is improved directory navigation: I don’t want to prefix changing directories with cd [...]; just let me type ../!

Here’s the code to install it:

apt-get install zsh

# Install oh-my-zsh
sh -c "$(wget https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh -O -)"

Then restart your console and you should be running Zsh. If not, type zsh.

Version 4.0 of the Constant Contact Plugin

I’ve been working on releasing a new version of the Constant Contact plugin for months, and it’s finally ready. The result: faster, more reliable, more features, and did I mention faster!?

The Form Designer, inline editing, and EventSpot are all 100% better. I highly recommend upgrading.

This plugin requires PHP Version 5.5 or newer. If you have a lower version, you will be presented with instructions on upgrading your installation.

Update: Now on WordPress.org

Download Version 4.0 from WordPress.org

Why isn’t this on WordPress.org yet?

WordPress.org doesn’t allow code to use PHP 5.4 or newer. This will be fixed soon, but until it is, please download the plugin here.

Once WordPress.org fixes this issue, I will update this post, and the plugin will resume auto-upgrading as usual.

Details:

  • Version: 4.0.1
  • Released: April 8, 2016
  • Compatible with: WordPress 4.5

Download Constant Contact for WordPress


Changelog:

4.0.1 on April 8, 2016

This is a major update that requires PHP 5.5 or higher. This was needed in order to use the latest Constant Contact code.

  • The Admin now looks great on mobile devices!
  • Constant Analytics has been removed. The authentication process changed significantly, so it was no longer working properly.
  • Added: If a contact exists in the site, link to their profile page from their single Contact page
  • Improved: URLs and emails are now links in the single Campaign page
  • Improved: Inline edit is much faster
  • Added: Campaign summary to the top of single Campaign pages
  • EventSpot:
    • Embedding single events using the shortcode with onlyactive enabled now shows a “The “{title}” event is no longer active.” message.
    • Maps now link to Google Maps SSL
    • Location output includes Address 2 and Address 3, if set
    • Fixed: directtoregistration shortcode setting wasn’t working (“Link directly to registration page, rather than event homepage”)
    • Fixed: Added caching for if Constant Contact account has access to EventSpot
  • Form Designer:
    • New simple default form design
    • Responsive design fits better to all screen sizes
    • Visual feedback when the form is being updated
    • MUCH improved speed when designing a form
    • No longer slows down when processing an update
    • Change background, border, padding settings live
  • Fixed: Logs not being pruned. This could lead to thousands of log posts in the database, slowing down the site.
  • Fixed: Fix fatal error when updating lists in User Profiles
  • Fixed: Improved Form Designer speed when WP_DEBUG is defined
  • Fixed: Admin pages now only process when they’re supposed to
  • Removed: Phone number validation. The phone number validator library was silly big.
  • Tweak: Show list name in single List page
  • Tweak: Add “Status” column to Campaigns table
  • Tweak: Only “Active” users now shown by default in Contacts
  • Tweak: Filtering Contacts by status now loads new request
  • Fixed: Delete caches when de-authenticating plugin
  • Tweak: Allow Draft events to be visible to administrators

Developer Notes:

  • Fixed: The “%%id_attr%%placeholder wasn't getting replaced properly when generating list HTML inKWSContactList`
  • Fixed: Prevent logs from being written during Form Designer AJAX
  • Fixed: Removed deprecated wp_clone() function
  • Fixed: include attribute wasn’t respected in KWSContactList::outputHTML()
  • Tweak: Improved error handling for errors returned by Constant Contact
  • Tweak: Refactor LESS files for admin CSS
  • Modified: Second parameter passed to cc_event_map_link is now a \Ctct\Components\EventSpot\EventSpot object
  • Modified: Removed third parameter passed to cc_event_map_link
  • Added: ctct_oauth_uri_base filter to use your own oAuth domain. See the filter inline docs for more information.

Fixing JSON Parse Error in WordPress Plugins

If you write WordPress plugins and make AJAX requests, you may be familiar the dreaded Javascript error: SyntaxError: JSON Parse Error: Unrecognized token '>'

SyntaxError: JSON Parse Error: Unrecognized token '<'

Why? Why!?!

What it means is that the response your code expected is screwed up because a plugin barfed PHP warnings into the admin-ajax.php ventilation system.

When WP_DEBUG is on, admin-ajax.php responses can include junk HTML output from PHP warnings, like:

<br />
<b>Notice</b>:  Undefined offset: 0 in
<b>/wp-content/plugins/im-gonna-break-ur-ajax.php</b> on line
<b>666</b><br />

The fix? Catch exceptions, then exceed expectations

The way to fix this is to wrap the jQuery.parseJSON() function in try/catch. That will make sure that the code doesn’t fully blow up.

try {
  jQuery.parseJSON( response );
} catch( exception ) {
  console.log( exception );
}

That will prevent your code from breaking, but it won’t make your code work.

The cause of the code breaking is the junk HTML at the beginning on the AJAX response. So, what we want to do is:

  1. Check for a valid JSON response
  2. If the JSON is invalid, strips all characters until finding a JSON-style opening of {".
  3. Check the newly stripped string to see if that is valid JSON
  4. If valid, return the JSON. If not, return an error message.

Here’s the code to achieve that:

Let me know what you think, and please fork the Gist if you have any improvements!

Wanted: Intermediate/Advanced PHP Developers for Ongoing Freelance Work

Are you a self-motivated intermediate or advanced PHP freelance developer? Want to work on taking WordPress plugins to the next level?

I want to work with for someone who is interested in contract or hourly work to work with on GravityView, IDX+, and my other WordPress plugins. There is lots of work to be done. We currently have a team of 3 people working on the plugins, and I’m looking to expand my development and support team.

What you would be doing:

  • Develop additional functionality for existing plugins
  • Refactor existing code – implement appropriate coding patterns
  • Help squash bugs

What we’re looking for:

  • Good code – Write code with well-conceived structure
  • Problem solving – Figure out solutions that are best-practice and maintainable
  • Good communication – Check in when milestones are reached and when you have questions or delays
  • Intermediate to advanced PHP skills (With lots of OOP experience)
  • Experience with WordPress is a plus (familiarity with actions/filters/functions)
  • Experience writing unit tests with PHPUnit is a plus

If you are interested and feel like you would like to work with us, please fill out this form:

Get in touch to work with us:

  • Please check each box to show you've read what we're looking for!
  • What project best shows your abilities, and why?
  • Helpful, but not required.
  • This field is for validation purposes and should be left unchanged.

How to use your own widget icon in the WordPress Widget customizer

Customize WordPress Widget IconIn developing deeper integration with the Customizer functionality of WordPress, I wanted to use a custom icon for my IDX+ plugin’s widgets.

By default, WordPress defines a list of icons using their dashicons icon set and tries to guess the best icon for your widget based on the CSS class of your widget.

Check out the CSS in customize-widgets.css starting on line 415.

For instance, if your widget’s CSS class contains “music”, “radio”, or “audio”, you will have the format-audio dashicon applied to your widget.

How to change the widget icon

Using Dashicons

Note: In order to choose a new icon, go to the Dashicons website and click on the icon you want to use, then click on the “Copy CSS” link to get the correct CSS content value.

#available-widgets [class*=YOUR_CSS_BASE] .widget-title:before{
    content: "\f217"; /* <-- replace this value */
}

Using your own icon font

#available-widgets [class*=YOUR_CSS_BASE] .widget-title:before{
    font-family: idx-plus!important; /* <-- replace this value */
    content: 'd'; /* <-- replace this value */
}

If you want the icon to change color when it’s hovered over, use the following code:

#available-widgets [class*=YOUR_CSS_BASE]:hover .widget-title:before{
    color: #7da838!important; /* <-- replace this value */
}

I hope this helps!

GravityView

Have you ever wanted to take a form submission and show the results on a website? That’s what GravityView does.

GravityView integrates with the popular Gravity Forms plugin and makes it easy to display entries on your website.

  • Embed Gravity Forms entry data in a post or a page
  • Control what data is displayed using a drag & drop interface
  • Moderate what entries are visible before they appear on your website
  • Allow users to edit the entries they created
  • …and more

If you’re using Gravity Forms, you’ll want GravityView.

Help test the Constant Contact API 3.0 plugin beta!

Almost ready.

It’s been a long haul for the new version of the Constant Contact for WordPress plugin. I started working on it before Constant Contact finalized their new API, so let’s just say it has been a major undertaking 🙂 Now I need help getting it ready for release!

The new Constant Contact WordPress plugin has some cool features, such as inline editing of lists and contacts, nicer report layouts, error/activity logging, and much cleaner ways of doing things.

Please help by installing the plugin and reporting issues.

You can download the latest build of the plugin here.

Please help test the plugin and — most important — report issues using this form.

I want to release the plugin in the next three weeks, so please download, install, and submit issues as soon as possible. It would be a huge help.

Are you a developer?

Please help out and contribute on GitHub. Your help will earn you a thank-you link on the plugin’s settings page!

Future plans

Once the new version is released, I plan on allowing this plugin be the connector to Constant Contact for my other integrations (Contact Form 7, Gravity Forms, and Fast Secure Contact Form). That way, other forms can be used instead of the Form Designer and you’d still get all the other functionality of the main API plugin, like viewing and editing contacts.

Thanks for your help!

How to remove WangGuard honeypot fields

WangGuard is a great plugin for blocking spam registrations. Without it, this site gets about 50 per day. No good!

I did encounter an issue, however: The <![if !IE]> tag was showing on my registration form for some reason. The code WangGuard adds inside the tag is used to generate a “honeypot” section: spam bots see the fake form fields but users don’t. Spam bots fill out the fields and when the form is submitted, WangGuard sees that the fake fields are filled in and knows the user is spam. The good news is that WangGuard still works without the honeypot fields.

Add the code below to your functions.php file to remove the honeypot fields:

/**
 * Get rid of WangGuard's honeypot fields on the registration form
 */
function kws_remove_wangguard_honeypots() {
    $i = 1;
 
    // WangGuard generates actions in a random position between 1 and 10, 
    // so we remove all actions that may exist.
    while($i < 11) {
        remove_action('register_form','wangguard_add_hfield_1' , $i);
        remove_action('register_form','wangguard_add_hfield_2' , $i);
        remove_action('register_form','wangguard_add_hfield_3' , $i);
        remove_action('register_form','wangguard_add_hfield_4' , $i);
        $i++;
    }
}
 
add_action('plugins_loaded', 'kws_remove_wangguard_honeypots');

Gravity Forms Directory Security Update

Yesterday a crucial security flaw was discovered in the Gravity Forms Directory plugin and fixed immediately. Version 3.5.4.3 was released and takes care of the issue. __Please update immediately__.

For the security of the users still running older versions, we can’t go into what the flaw was, but it had to do with viewing Gravity Form entries without permission, and was severe.

Gravity Forms Directory versions affected: 2.4.1 – 3.5.4.2. Version 3.5.4.3. fixes the problem

The flaw was discovered by Baruch Moskovits. We released a patch within one hour of the discovery.

How to get all downloads in Easy Digital Downloads

Easy Digital Downloads defaults to using 10 results per page when using the get_products() method. You can modify this default using the edd_api_results_per_page filter.

Here’s how to fetch all products at once:

$EDD_API = new EDD_API;

// Force EDD to show all the downloads at once.
add_filter('edd_api_results_per_page', 'modify_edd_api_results_per_page' );

// Get all the EDD products
$products = $EDD_API->get_products();

// Restore sanity to EDD results per page.
remove_filter('edd_api_results_per_page', 'modify_edd_api_results_per_page' );

/**
* Modify the number of results fetched by EDD
* @param int $per_page Previous results per page setting
* @return int New results per page setting. If you have this many, you're in trouble.
*/
function results_per_page($per_page) {
return 99999999; // Yeah, you've got lots of products!
}

How to Add Support for Display Advertising Code in Google Analytics for WordPress

It’s really simple to use Google’s Display Advertising code, so I thought I’d share how.

To enable the new GA features:

  1. Check the “Show Advanced Settings”
  2. Under “Advanced Settings,” check the checkbox for “Host ga.js locally:”
  3. In the text field that appears, enter: //stats.g.doubleclick.net/dc.js
    • Note: The missing http and https is intentional – if your site’s in secure mode, it will use https, otherwise http)
  4. Save your settings!

30 Years of Mac: White and Male

Apple has a deep-seated diversity problem.

Apple Diversity and GenderIn the 30 Years of Mac mini-site, a thoughtfully prepared homage to the history of the Macintosh and the people who use it to create, there were four women featured out of the twenty-eight profiles. One of the women featured, Noemi Trainor is an educator, a role women are “allowed” to be in. There were no Blacks or Hispanics represented.

There were four non-white males represented in 30 Years of Mac: a Korean, Japanese-American, Japanese, and Lebanese-American were profiled.

It’s easy to say that this has been gone over before. It’s well-known that Apple’s leadership is all white males (soon to include a women, Angela Ahrendts). Using archive.org, I can only find one woman in Apple’s leadership since 1997: Nancy R. Heinen. Nancy Heinen worked at Apple as Senior Vice President and General Counsel from September 1997 to May 2006, until she was sacrificed for backdating stock-options for Steve Jobs. No minorities.

Diversity with a Capital D
Colorlines.com

Board recruitment is not the problem, culture is.

In the next Apple shareholder meeting, Apple will vote to start to improve their board diversity. Their board charter will be updated to include the following statement:

The nominating committee is committed to actively seeking out highly qualified women and individuals from minority groups to include in the pool from which board nominees are chosen.

It’s obvious by looking at their leadership team and board roster that diversity is simply not a part of the Apple culture. This culture will not change with an improved board recruiting policy. Changing a culture is a much tougher nut to crack. On Sheryl Sandberg’s LeanIn.org website, there’s a suite of tools for increasing organizational diversity through non-biased hiring and management practices. Creating a Level Playing Field, a brilliant talk by Stanford Professor Shelley Correll, would be a good place to start.

It’s gotten bad.

I’m mad at Apple. It’s inexcusable that one of the largest companies in the world, a trendsetting company, does not care more about diversity. Apple should be setting the example for the tech world and being a diversity leader. I’m tired of seeing high-resolution images of Bob Mansfield and Jonny Ive.

I’m aghast that the 30 Years of Mac website features mainly white dudes, apparently the only innovative users of Macs. Surely, Apple could have found some African American innovative graphic designers that used the Mac over the past 30 years and represented more than four women. Apple chose not to.

Who was the editor of 30 Years of Mac? Who looked at the featured profiles and said “This represents our users”? Did someone at Apple say “I think we should feature more minorities and women?” or “Gee, that list of people is really, really white”? If not, that voice needs to be heard, and if someone did say that, that voice needs to be louder.

It’s time for Apple to step up their game and change their culture.

[EDIT] – Apple has promoted Denise Young Smith, an African-American woman, to run HR. Here’s a snippet from the Bloomberg article:

Smith is the latest woman to join Apple’s top ranks, which also include Katie Cotton, vice president of communications, and Angela Ahrendts, the former Burberry Group Plc chief executive officer who will lead retail operations.

Gender and race is a touchy topic, and I’m trying to represent my point of view without being disrespectful. If I use any language the you find offensive, please let me know.

Set the Width for a Google Maps InfoWindow

Working with Google Maps v3 is way fun.

If you’re a masochist.

Infowindow width
Scrolling InfoWindow
It seems like there’s no easy way to set the width of an InfoWindow. You can set the minWidth parameter, but that does nothing.

If you have content that exceeds the InfoWindow window, you get this: a scrolling box. That’s terrible.

The solution is horribly easy.

Looking Through the InfoWindow
The solution presents itself.
This will solve all your problems, and make you wish you had the past two hours back of your life: use the provided .gm-style-iw class to style the InfoWindow content container.

/* Just use .gm-style-iw */
.gm-style-iw {
width: 300px; 
min-height: 150px;
}

Testing Translation Function Speeds in WordPress

Speed of memoryAfter reading Pippin Williamson’s post about gettext speed issues, I wanted to learn more. My IDX+ plugin has 815 translatable strings, and I was worried that it was having a performance impact on the plugin.

I created a test that looped through different methods of outputting and printing strings to try and determine their relative speed. WordPress uses different functions for translating strings, as documented in the Codex, and I included __() and _e(), the functions I use the most often.

Here are the results of a 100,000-iteration loop:

  • echo 'Test': 0.1786 seconds
  • $out .= 'Test': 0.2454 seconds (37.4% slower)
  • __('Test'): 0.5301 seconds (196.8% slower)
  • _e('Test'): 0.5639 seconds (215.7% slower)
  • echo __('Test'): 0.5722 seconds (220.4% slower)
  • __('Test', 'test'): 0.5743 seconds (221.6% slower)
  • _e('Test', 'test'): 0.6076 seconds (240.2% slower)
  • echo __('Test', 'test'): 0.614 seconds (243.8% slower)
  • $out .= __('Test', 'test'): 0.6885 seconds (285.5% slower)

“Findings” (non-scientific)

  • Contrary to what I had read, echoing inline was by far the fastest method.
  • Adding a domain (the second parameter) to translation functions slows the functions down a bit.
  • Storing strings in a variable after using __() is slow.
  • All times are well below 1/10th of a second when translating 10,000 strings instead of 100,000.

Conclusion

Although translating 100,000 strings adds half a second processing time, if your site is processing well less than that, you shouldn’t have a problem.

It seems the site Pippin was working on had enough strings to affect the responsiveness of the site, but I would bet that’s not a normal site. I also would bet that the issues the site was having are not because of the translation functions themselves, but the translation plugin the site was running.

I’m going to be using more _e() and less echo __(), but other than that

SEODenver.com: Now katz.co

WordPress SEO Plugin

SEODenver.com is now katz.co

Katz Web Services hasn’t been doing SEO for years – I’ve been focusing on making great WordPress plugins (such as IDX+) and I have been disenchanted with the SEO industry.

So it was time to move the SEODenver.com domain to katz.co. I’m looking forward to writing more blog posts now that there’s not the discord between the domain and my interests.

YOURLS Link Anonymizer

View on GitHub or Download

Link Anonymizer

Anonymously visit links in YOURLS, including referring sites and original URLs.

Sometimes you want to click a link, but you don’t want to have your YOURLS installation be the refferer. So you right click, copy the URL, paste it in your address bar.

Instead, use Link Anonymizer to generate a link for you that will take you to an anonymizer service.

When you click the [anon] link, you will be first redirected through an anonymous referrer service of your choice.

Screenshots

Anonymous links on main admin page

Anonymously visit your own links.

Traffic Sources > Referrers links

Now you can have anonymous Traffic Sources > Referrers links

What service should I use?

You can use any service—there are many—but here are some options:


Thank yous

  • The key icon is from the Silk icon set by FamFamFam.
  • The anonymizer services are independently run – thanks for offering the free services!

Marco.org (With Comments)

I love Marco.org, and I also love Daring Fireball with Comments

Marco.org (with Comments)…so I created Marco.org (with Comments)!

Install the extension for Safari or Chrome and you’ll have Disqus-based comments on Marco.org!

To help keep the conversation civil, rude words lead to moderated comments.  I look forward to our discussions.

– Zack Katz

Marco.org (with Comments) Safari Extension

Marco.org (with Comments) Chrome Extension