Sometimes running is good :)

We have started migrating sites off of DreamHost. To make sure we have the procedure correct so that we don’t cause any customer interruptions we started with our own site.

The new site is a fresh, untuned Apache instance residing on a clean Digital Ocean Droplet. Check out the performance gain!

slow-dh

Having been forced to take action due to the DreamHost debacle it’s nice to see some positive impacts.

I wonder how much better the new site will be after some performance tuning?

And no, still no response from DreamHost support and management about their planned lockout of their customers

Should you run away from DreamHost?

We curate and host WordPress and WP-eCommerce sites for ourselves and our customers. One of the hosting providers we use, and recommended WAS DreamHost. Their support and pricing had always been good. Their attitude used to be cooperative, communicative and considerate.

Then, last night, while at dinner with the bride, my phone vibrates indicating a priority message. As of that message, DreamHost is no longer on our recommended list.

DreamHost sent out a blast email notifying all of their customers that in 4 business days, and in the middle of holiday shopping season, DreamHost is making a change to their hosting configuration. The change DreamHost is making is a little hard core, removing “sudo” access to the servers. For people that don’t know, sudo is the tool that lets a user log in to make an administrative or configuration change to a server.

For your entertainment value, the message is below.

dumb-dreamhost
Dumb DreamHost

Why this matters? Every once in awhile something goes wrong on a server often a simple fix is restarting a process, or flushing a cache. In the case of e-commerce sites we sometimes have to make subtle adjustments to configurations in response to reports from periodic security scans or security patch notices. After this change, making any critical change will be impossible.

So, after the change, if a web site requires a little tweak or has an issue that is critical to it’s ongoing operations, just turn out the lights.

And no, we don’t think turn out the lights is an exaggeration! All of the commerce sites we curate for our customers are PCI Compliant and are periodically scanned by independent third parties. If a scan detects an issue, as sometimes happens with a recently discovered operating system or application software vulnerability, we get notified. If the issue is severe and is not promptly corrected, the PCI company will notify your credit card processor. If your credit card processor decides that the issue puts them at risk, your payment processing can be turned off.

With this change your sites’ performance is also at risk. Even a common performance enhancement to a WordPress site like turning on memcached now becomes impossible. For some of our commerce and blog sites memcached is important. Memcached speeds WordPress response times up by 5-10 times, and lets us handle spikes in traffic without any degradation in performance. So if your e-commerce site is lucky enough to get busy, even this most obvious performance tweak is not going to be useful.,

For any DreamHost customers that need to find the words to share with DreamHost to express their concern over this change feel free to borrow from the hastily written note we sent to DreamHost last night:

I just received an email that you are making a change to the VPS configuration for my sites in the middle of the christmas shopping season. WITH LESS THAN 10 BUSINESS DAYS NOTICE! “We will be removing admin (sudo) access from all DreamHost VPS instances.” Removing the administrative access to our server instance will cause substantial loss to our business. If you make this change it is a near certainty that my site will not be supportable, will fail, and you will cause a substantial financial loss to our company. The mitigation of your actions, even if they were technically possible in the inadequate time you have provided, will cost of tens of thousands of dollars to implement. The inadequate notice period makes it impossible for us to find another technical resource to host the site, move it and test it in the next few hours before the busiest shopping days of the year are upon us. This change and how you are planning to make it, most notably including the insufficient notice is negligent, and exudes arrogance and incompetence. I insist that I immediately get a call back from a manager explaining this change and why your management team thinks the timing is acceptable. I insist that you provide a viable alternative or cancel the plans that you have made unilaterally. I insist that you forward me the contact address that I need to use for legal notices and correspondence. Please include the postal address, the person’s name, and the telephone number so that I can have correspondence sent. Flabbergasted by this bonehead move, Pye Brook Company, Inc.  

This morning, we start work and check our host status DreamHost server control panel and find this notice:

 

dump-dreamhost-response
Dumb Dreamhost Response

You can get whiplash reading the back-peddling in this note. A very disturbing take-away from this posting is that DreamHost fails to recognize the critical timing of this change and how it could impact customers. Even worse, is the admission that they have not taken the time understand the impact of this change before making the decision to implement the change.

Our takes on this situation are these:

  1. This change makes it technically impossible to implement the standard recommended configuration for highly performing WordPress blogs and e-Commerce sites.
  2. This change makes it technically impossible for us to respond to critical situations that arise from time to time with the sites we host.
  3. MOST CRITICALLY: We can’t rely on a hosting provider whose internal decision making process is so flawed that changes like this are put in process during critical times, without making the necessary effort to understand the impacts, and without sufficient notice.

We are fortunate in that we also have sites running on Amazon AWS and Digital Ocean, so we have a path out the DreamHost debacle.

So the answer is yes, we think you should run away.

If you are already using our curated WordPress or WP-eCommerce services you will be migrated transparently after we consult with you and make sure it won’t impact any planned/expected commerce or marketing events.

If you work on your own, and you feel at risk by this dreamhost move we can migrate your WordPress blog or e-commerce site to your stand-alone AWS server / Digital Ocean server or our curated offering for a one time flat fee.

 

Diagnosing a WP eCommerce Error on GoDaddy Hosting with PHP APC

Recently there were a flurry of bug reports about a fatal error in WP eCommerce in the WordPress support forum. Initially all of the reports were from sites using GoDaddy for hosting. The common cause for the bug reports was a fatal PHP error that looks something like this:

Fatal error: WPSC_Countries::get_countries(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "WPSC_Data_Map" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/content/p3nexnas05_data03/62/2100362/html/wp-content/plugins/wp-e-commerce/wpsc-includes/wpsc-countries.class.php on line 462
Fatal error: WPSC_Countries::_dirty(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "WPSC_Data_Map" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition in /home/content/p3nexnas05_data03/62/2100362/html/wp-content/plugins/wp-e-commerce/wpsc-includes/wpsc-countries.class.php on line 1142

Justin from the WP eCommerce team, quickly figured out that if you turn off WordPress object caching the problem goes away.

The sites in question were asked to install the free WP eCommerce Site Checkup Plugin. On all of the sites checked, the plugin reported information that was helpful in getting started.

Triage of the reports told us a couple of things:

  1. Only seems to happen when APC op-code cache is being used as a WordPress Object Cache.
  2. Issue is highly intermittent
  3. Site checkup reports that APC is part of the PHP configuration
  4. Site checkup reports that WordPress doesn’t think APC is installed as an object cache
  5. Site checkup reports that WordPress doesn’t think an object cache is active.

An easy workaround for the issue is to rename the object-cache.php to something like “_object-cache.php”.  This stops the APC cache from being used as a WordPress object cache.

Because the error was only occurring in production environments, and was very intermittent stepping through in the debugger was not an option. Next best thing was the WordPress developer’s tried and tried method of using WordPress’ debug.log file, and embedding “error_log” calls at strategic places in the code to see what was going on.

We Need To Pass the Site Checkup Object Cache Test

After a couple of strategically placed logging calls showed that the object cache was only being enabled for user facing pages a read through of all of the code in object-cache.php began.  The object-cache.php was from a plugin written by WordPress Guru Mark Jaquith. Because the plugin has been around for at least 5 years, and was written by Mark, anyone would pretty much assume that the issue wasn’t inside the plugin.  But after several trips away from the code, the logging continued to point to something odd going on. Most notable, was that the object cache test in the site checkup plugin was always failing.

Finally, after a no-assumptions careful review of the APC object-cache plugin code, a test was shown to be intentionally stopping the object cache from loading on any admin request.

$oc_blocked_page = ( defined('WP_ADMIN') || defined( 'DOING_AJAX' ) || defined( 'XMLRPC_REQUEST' ) || defined( 'DOING_CRON' ) || 'wp-login.php' === basename( $_SERVER['SCRIPT_FILENAME'] ) );
if ( 'cli' !== php_sapi_name() && function_exists( 'apc_fetch' ) && !$oc_logged_in && !$oc_blocked_page ) :

Because admin requests include anything the store checkup plugin was doing, it explains why the diagnostics are failing.  It also explains why some WP eCommerce configuration options managed by the administrator in the WordPress dashboard were not being updated for the users.  Without the object cache active when the administrator does work cached values would not be refreshed. This would result in stale or invalid data being available to end users, even though it was updated for administrators. The problem would extend to include any WordPress transients that are stored into the object cache when an object cache is enabled. It would also certainly include any value manipulated by an AJAX request or a scheduled CRON.

Changing the test used to decide if the object cache should be loaded to something less specific was easy. Change the condition to check for the presence of the APC extension:

if ( extension_loaded( 'apc' ) ) :

With the APC object cache test passing, and the object cache always available we changed the symptoms of our problem.  Instead of the PHP fatal error being intermittent, it happened all of the time.  I guess that’s progress?

Why Can’t WordPress Load WP eCommerce’s Data?

Remember that the WP eCommerce plugin operates perfectly without an APC object cache and operates perfectly with a Memcached (the daemon) based object cache. But as soon as we turn on APC as an object cache we see get the fatal error.

Because the fatal error was telling us that a class definition was not loaded , the first thing was to confirm that the key classes were being included in the application.  At the top of each PHP file, prior to the class being defined, we put an error log statement to record that the file has been included.  At the top of the file that defined the WPSC_Country class the statement:

error_log( ‘including class WPSC_Country’ );

was added.  At the top of the file that defined the WPSC_Countries class the statement:

error_log( ‘including class WPSC_Countries’ );

was added. At the top of the file that defined the WPSC_Data_Map class the statement

error_log( ‘including class WPSC_Data_Map’ );

was added.  Then a click on the page refresh button in our browser, and a look into the debug.log file. This is what was there:

[12-Apr-2015 23:53:03 UTC] including class WPSC_Country [12-Apr-2015 23:53:03 UTC] including class WPSC_Countries [12-Apr-2015 23:53:03 UTC] including class WPSC_Data_Map [12-Apr-2015 23:53:03 UTC] WPSC_Countries::__construct [12-Apr-2015 23:53:03 UTC] PHP Fatal error: WPSC_Countries::new_get_countries(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition “WPSC_Country” of the object you are trying to operate on was loaded before unserialize() gets called or provide a __autoload() function to load the class definition in /home/content/p3pnexwpnas03_data02/88/2349788/html/wp-content/plugins/wp-e-commerce/wpsc-includes/wpsc-countries.class.php on line 484

Reading the error message it really makes little sense.  The classes are included, then PHP cant find the class definition. Puzzling.

Next experiment was to create a PHP class autoloader, the error message seems to suggest this as a solution. This was added to the plugin code:

function wpsc_class_autoload( $class ) {

   $file = strtolower( str_replace( '_', '-', $class ) );
   error_log( __FUNCTION__ . ' class is ' . $class );

   if ( file_exists( WPSC_FILE_PATH . '/wpsc-includes/' . $file . '.class.php' ) ) {
      require_once( WPSC_FILE_PATH . '/wpsc-includes/' . $file . '.class.php' );
   }
}

error_log( 'autoload register' );
spl_autoload_register( 'wpsc_class_autoload' );
Make note of the error_log call in the autoloader callback function. This should record every request for class autoloading.

Another click of the browser refresh button produced another interesting log snippet:

[13-Apr-2015 10:16:57 UTC] including class WPSC_Country
[13-Apr-2015 10:16:57 UTC] including class WPSC_Countries
[13-Apr-2015 10:16:57 UTC] autoload register
[13-Apr-2015 10:16:57 UTC] including class WPSC_Data_Map
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is Sputnik
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is Sputnik_Admin
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is Sputnik_Updater
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is Sputnik_Pointers
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Module
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is external_links_anchor_utils
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is SitePress
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is WPML_Translation_Management
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is WC_Download_Handler
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Module_Manager
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Feature_Manager
[13-Apr-2015 10:16:57 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Performance
[13-Apr-2015 10:16:57 UTC] WPSC_Countries::__construct
[13-Apr-2015 10:16:57 UTC] PHP Fatal error:  WPSC_Countries::get_countries(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "WPSC_Country" of the object you are trying to operate on was loaded _before_ unserialize() gets called or provide a __autoload() function to load the class definition  in /home/content/p3pnexwpnas03_data02/88/2349788/html/wp-content/plugins/wp-e-commerce/wpsc-includes/wpsc-countries.class.php on line 477

Notice that many classes are recorded as looking for an autoloader, but none of the WP eCommerce classes are requested!

Something was going on where WordPress, APC or PHP was trying to parse the contents of one of our cached values. But fatally failing.

Next experiment was to try to stop APC and PHP from parsing our stored value. Easy enough to do by encoding the cached value so that it wouldn’t be seen as an object by the system code. These functions were created to save and recall the cached value.

function special_set_transient(  $transient, $value, $expiration = 0 )  {
    $value = base64_encode( serialize( $value ) );
    return set_transient( $transient, $value, $expiration );
}

function special_get_transient( $transient )  {
    $value = get_transient( $transient );
    $value = base64_decode( $value );
    $value = maybe_unserialize( $value );
    if ( empty( $value ) ) {
        $value = false;
        delete_transient( $transient );
    }

    return $value;
}

The expectation was that this would not have any effect on the issue. But, that was not the case. This is what was in the log file after many page refresh requests:

[13-Apr-2015 11:28:36 UTC] including class WPSC_Country
[13-Apr-2015 11:28:36 UTC] including class WPSC_Countries
[13-Apr-2015 11:28:36 UTC] autoload register
[13-Apr-2015 11:28:36 UTC] including class WPSC_Data_Map
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is Sputnik
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is Sputnik_Admin
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is Sputnik_Updater
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is Sputnik_Pointers
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Module
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is external_links_anchor_utils
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is SitePress
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is WPML_Translation_Management
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is WC_Download_Handler
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Module_Manager
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Feature_Manager
[13-Apr-2015 11:28:36 UTC] wpsc_class_autoload class is All_in_One_SEO_Pack_Performance
[13-Apr-2015 11:28:36 UTC] WPSC_Countries::__construct
[13-Apr-2015 11:28:37 UTC] wpsc_class_autoload class is JQueryColorboxFrontend
[13-Apr-2015 11:28:37 UTC] wpsc_class_autoload class is Flattr
[13-Apr-2015 11:28:37 UTC] wpsc_class_autoload class is BJLL

No fatal PHP errors, not even any warnings.

Conclusions

  1. We have a fix to the object-cache.php and a potential change in WP eCommerce that will get us by the issue.
  2. The work-around that let’s WP eCommerce work in an environment that uses  APC as an object cache  seems to tell us there is an APC/PHP bug when retrieving cached objects that contain other objects from a WordPress APC object cache.

Is this a bug? Please give us your thoughts?

Creating a Coupon for a Free Product in WP-eCommerce

From time to time you may want to give a product away as a promotion.  This is how to create a coupon for a free product.

 

In the WordPress Dashboard, on the PRODUCTS menu select COUPONS

coupon menu

 

 

 

 

 

 

 

 

Add the coupon for your product using the new coupon form:

add-coupon-button

 

 

 

 

Use a unique coupon code, in the example we use “FreeGift”

Set the discount amount to 100%, this will reduce the cart sub-total by the value of the product being given away

Set a start and end date

DO NOT CHECK  “This coupon affects each product at checkout”, if you check this the shopper will get the whole cart for free 🙁

In Conditions select “Item Name” and “Is Equal To” and enter the name of the product you are giving away.

create-coupon




That’s it!

Customizing PayPal Checkout for WP-eCommerce

PayPal offers a really nice feature that lets you customize the look and feel of the PayPal checkout page to match the look and feel of your web site.  We highly recommend that you use this feature to have your PayPal checkout page look similar to your WP-eCommerce shopping cart pages.  It makes for a much friendlier feeling checkout experience.

But what do you do when you have one PayPal account and multiple stores.  The PayPal Payments Standard 2.0 gateway that comes with WP-eCommerce doesn’t let you override the look and feel settings on a store by store basis.  And the newer PayPal gateways that come with WP-e Commerce may not be suitable for your store for some reason.

There is an easy answer!

The PayPal gateway that comes with WP-eCommerce  has a nifty “filter” that we can use to pick any of the “styles” you have set up in your PayPal settings.  It’s only a few lines of code that you can drop into a file in the mu-plugins directory, or into your theme’s functions.php.

This little snippet of code will tell PayPal to use the ‘pyebrook’ style sheet whenever  WP-eCommerce sends a shopper to PayPal.

add_filter( 'wpsc_paypal_standard_post_data', 'my_wpsc_paypal_standard_post_data', 10 , 1 );

function my_wpsc_paypal_standard_post_data( $paypal_vars ) {
    $paypal_vars['page_style'] = 'pyebrook';
    return $paypal_vars;
}

 

And this is what your shoppers will see:

paypal-checkout-screen
Customized PayPal Checkout

 

 

 

 

 

 

 

 

 

 

SEO and WP-eCommerce Performance Tuning

We have been doing some tuning work on the 80,000+ product Sparkle Gear WP e-Commerce store and wanted to share one experience with the WordPress SEO Plugin by Yoast.

Unless you are a SEO expert, Yoast’s WordPress Plugin is a a tool that will save you alot of work, and keep much the SEO process understandable and accessible to mere mortals.  It’s a great addition for any WordPress site, and especially useful for WPEC that create lots of posts (products are posts) and have lost of taxonomies (variations and categories are taxonomies). IMHO. the dynamic sitemap generation feature of the WorpPress SEO plugin alone makes it a must have.

WordPress SEO Plugin Developed by Joost de Valk

wpecHowever, there are some details about how WPEC is implemented that need to be addressed when you install the SEO plugin.First item, WPEC stores products as posts. WPEC stores 

variations of products as child posts of product posts.  These child posts are used to hold information about an individual product variation.  Details like the variation image, price, stock. etc.  The important detail to note is that these child posts are not directly accessible to the outside world. In WP speak, the permalink for these posts will give you a 404!

Read More

Health Apps: US FDA Plans Oversight of Mobile Medical Apps – CNBC

A fast-growing number of software applications offers doctors the chance to view X-rays or monitor heart rates from iPads or smartphones, prompting U.S. health officials on Tuesday to propose government oversight for some of the more complex health apps.

A portion of the apps perform tasks that mimic the work of medical devices and could cause harm if they failed to perform as promised,Food and Drug Administration officials said.

New FDA guidelines state that in some cases software developers would have to show their apps worked as well as non-mobile devices for the same use.

The agency would have to provide clearance for those apps before they could be sold. FDA officials said they recognized the potential benefits from mobile medical apps and aimed to encourage future development.

Read More

About btHeart

We are working on the documentation for the application.  To get you started a primer of the main screen is below.  Tap on any of the graphs to zoom in on the live picture.

image

The heart rate data read from your heart rate monitor is recorded in a text log file.  The file is in the standard “CSV” format and can be imported into spreadsheet like Microsoft Excel or Google Docs.  The  log files are on your device’s SDCARD, in a directory named “hrmlog” . btScale always writes its log to the file named “hrm.log”.

restartworkoutEvery time you select the “Restart Workout” option the “hrm.log” file will be renamed using the current date and time.  A new HRM.LOG file will then be created.   You can delete any of the logs in this directory at any time they are not in use.