How to send randomly-selected support tickets to Slack once a week for easy review

At GravityView, we’re starting a review process for support to make sure that as we grow, our support continues to be awesome.

We’re starting a Support Review meeting. We will randomly choose tickets to review for each person who has provided support in that time.

Random selection is a pain, so we created a Zapier Zap to do it for us! Here’s how: Continue reading “How to send randomly-selected support tickets to Slack once a week for easy review”

Allow customers to update their cards in disabled gateways using Easy Digital Downloads Recurring Payments

Last year, GravityView was using PayPal Pro to process credit card transations with our shopping cart, Easy Digital Downloads. Over time, we became frustrated with the error rate of PayPal notifications: PayPal kept telling us the country code wasn’t set. But it was. This was preventing customers from checking out, so GravityView switched to using Stripe for credit card transactions.

Now, a year later, customers with outdated credit cards who paid with PayPal aren’t able to update their billing information on the GravityView website. Customers can’t see the “Update Card” link because the PayPal Pro gateway is disabled. Because the PayPal Pro gateway is inactive, the link to update the credit card details for a subscription isn’t visible. Continue reading “Allow customers to update their cards in disabled gateways using Easy Digital Downloads Recurring Payments”

Translating Multiple Branches of Your Premium Plugin with Transifex

Since GravityView launched in 2014, we have used Transifex to manage translations. Our process has always relied on a single translation resource file, and we’ve had the same flow over time:

  • Create an update with new strings
  • Upload the translation file to Transifex
  • Release the update
  • In the next minor release, include any new translations from translators

Transifex recently made it easy to create resource branches using their Command Line Interface (CLI). You can read more about creating branches on their site.

We’re about to release Version 2.0 of GravityView, which includes new strings that I want to have translated before we launch, so I created a branch of the resource.

Here’s how to do it—this assumes you have Transifex installed and configured.

  1. Switch to the branch of your plugin you want translated
  2. Update the translation file to have the new strings (we use the excellent grunt-wp-i18n Grunt package to generate our plugin automatically)
  3. Run tx --version and make sure you see 0.13.x or higher. If you’re running 0.12.x, it won’t work
  4. Push the new resource to Transifex using this format: tx push -s -b "Your Branch Name" – for example, ours was tx push -s -b "2.0" because our branch name was 2.0
  5. That will now create the resource on Transifex. Go to Transifex and confirm the resource’s name. For our 2.0 branch, the resource name was 2-0--gravityview
  6. Update your Transifex config file in the plugin’s .tx directory’s config file. Change the setting to use the new resource name. For example, instead of [gravityview.gravityview] ({name of project}.{name of resource}), it is now [gravityview.2-0--gravityview]
  7. Commit the changes to your repo (see GravityView’s here)

I’m going to be adding a new develop branch as well, so that translators will be able to translate the plugin before it’s released, instead of waiting until later.

Is your Fluid app is too slow? Try nativefier instead

I have used Fluid for years to create single-page native web applications that run on my Mac. I have one for Help Scout, I have another for Trello, but I have noticed a problem: when replying to tickets in Help Scout, I would experience serious lag. Letters would appear hundreds of milliseconds after I typed.

I thought it was an issue with my computer, but I recently got an iMac Pro and it’s still happening, so I know that’s not the problem!

I tried Epichrome instead (like Fluid but using Chrome instead of Safari as the base), and that wasn’t any better.

Enter nativefier. Instead of using Safari or Chrome, it builds a single-page “native” web application using Electron, the same library that runs Slack and many other cross-platform native-ish web apps. nativefier has been working great.

So if you’re experiencing typing lag while using Fluid or Epichrome, check out nativefier!

The Future of WordPress

I will be presenting the WordCamp Denver 2017 keynote on August 26, 2017. It’s a privilege, and I’m looking forward to it! If you don’t have tickets yet, it’s not too late—get a ticket nowSee you soon!

I will update this post with the slides once they are available, and I will also have “show notes”—a list of links I will reference during the talk.

This post was written using Calypso.

Using Tweets to post more regularly

I think the pendulum of social media may have swung for me back to self-publishing. I hope so; I make my living on WordPress, and I love WordPress. I want to control my own content and don’t want to lose the timeline of my thoughts.

Perhaps the katz.co domain name being associated with my business adds just enough pressure to prevent me from posting. I did just buy katz.me, so maybe I’ll start a personal blog there.

I need to practice writing more often. Content is the biggest missing piece of the GravityView business.

So now, I’m creating draft posts from Tweets (when they’re not replies). That’ll give me plenty of momentum to continue writing on the website.

(And yes, I’m sure there’s a plugin for this. For now, this is better than nothing.)

Gwen Ifill

Gwenn Ifill

I did not know Gwen was sick. I didn’t know she had cancer. On Monday, she died.

I respected her and found comfort in her presence. I trusted Gwen to tell me the truth, to find humanity in any situation, to always reflect appropriate levels of concern.

I trusted Gwen Ifill completely. Not because she was on TV, but because she did not hide who she was: she broadcasted it. She was a complete person who was honorable and eminently professional.

Multiple times every week, before dinner, my wife Juniper and I watch the PBS NewsHour. We enjoyed saying hello to Gwen and Judy—out loud!—from our couch. We often would comment to each other that “Gwen and Judy are the best at what they do” and “there is no one else like them.” Then, turning back to the news, Juniper and I would watch Gwen professionally deliver the events of the day with heart and enthusiasm.

Now that she’s gone, I know that Gwen was my role model. She displayed strength, dignity, and professionalism, as well as strong steady passion for her work, kindness, and playfulness.

Thank you, Gwen, for being you.

How to fix UTF-8 filename issues when using wp_handle_upload()

PHP said the file didn’t exist. Except it did.

file_exists() wasn’t working for a file uploaded using wp_handle_upload(). It worked for every other file, except for one provided by a German customer.

I confirmed the following:

  • The file did exist in the correct wp-uploads sub-directory
  • The file had correct permissions
  • The directory and its parents had correct permissions

I was stumped.

Then I renamed the file

I converted indlæsning to indlaesning and it worked. The problem was with UTF-8 characters in the filename.

But how can this be? Let’s see where the file name comes from:

  • _wp_handle_upload() calls
  • wp_unique_filename() to generate a unique file name, which calls
  • sanitize_file_name() to prepare the file name
  • sanitize_file_name() then checks against a list of special characters that are not allowed in file names:
$special_chars = array("?", "[", "]", "/", "\\", "=", "", ":", ";", ",", "'", "\"", "&", "$", "#", "*", "(", ")", "|", "~", "`", "!", "{", "}", "%", "+", chr(0));

This list of characters can be modified using the sanitize_file_name_chars filter, but that seemed more complicated than I wanted.

The sanitize_file_name() function also includes a sanitize_file_name filter, which allows you to modify the name of the file after it’s already been sanitized.

Luckily, WordPress already has a function to convert other UTF-8 characters into Latin equivalents: remove_accents(). I used that to convert the filename into something file_exists() could handle.

Here’s how to fix UTF-8 issues with wp_handle_upload()

That converted the filename from: indlæsning.csv to indlaesning.csv. Note that the æ character got converted to ae.

The result? Finally, file_exists().

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!