Easy Amazon Wishlist 2.0 WordPress plugin goes live!

Easy Amazon Wishlist 2.0!

Ever since Amazon retired their wishlist API it’s been difficult for customer to find a convenient way to display their Wishlists (and now Idea Lists as well!) Wishlists are great for non-profits, social media stars with loyal customers, birthday, or for whatever reason you might want to provide a mechanism for someone to buy you something. We also added the capability to add an Amazon Idea list to your blog. These are ideal for recommending products on Amazon. We are going to work on a Facebook app to do something similar now, and we have great plans for the future of the plugin, but we have to prioritize, so please let us know what new feature for the Easy Amazon Wishlist pugin you would like to see worked on first! https://wordpress.org/plugins/easy-amazon-wishlist/

Coming Soon
What new feature do you want worked on first?
What new feature do you want worked on first?
What new feature do you want worked on first?

Incomplete WordPress Install

How to manually add a WordPress Admin

Well, we ran into an interesting problem the other day where we were able to install WordPress on a Windows 8 laptop for local development, but it only partially installed and stopped at step 2.

We hit refresh on the page, which resubmitted the login details from the first step and it takes you to a screen that says WordPress has already installed.

Now there are a couple reasons this error can come up…most likely because of a PHP server side timeout error…unfortunately the second step it failed on is the step where it adds the admin user to the WordPress install, so if you click the “Log in” button it takes you to the wp-login.php page, but you don’t have a user to login with, and if you go to the database and look in the users table you can see that it’s empty….so your options are to keep futzing with the php.ini file and restarting Apache until it installs correctly (and for that you just delete all the tables in your WordPress database and hit the /wp-admin/install.php file again), or we can install the admin user manually in the database. No manually adding a user to a WordPress install involved modifying the users, usermeta, and options table (in your install they will probably be called the wp_users, wp_usermeta, and wp_options tables or whatever your prefix might be that you’ve set in your configuration file). So in your MySQL database (or MariaDB I suppose) you want to run the following SQL queries to add rows to the relevant tables. Change “prefix” to whatever value you specified in step 1 for the wordpress database prefix. You can also find it in your wp-config.php file under $table_prefix = ‘prefix_’;

INSERT INTO `prefix_users` (`user_login`, `user_pass`, `user_nicename`, `user_email`, `user_status`)
VALUES ('newadmin', MD5('pass123'), 'firstname lastname', '[email protected]', '0');

INSERT INTO `prefix_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) 
VALUES (NULL, (Select max(id) FROM prefix_users), 'prefix_capabilities', 'a:1:{s:13:"administrator";s:1:"1";}');

INSERT INTO `prefix_usermeta` (`umeta_id`, `user_id`, `meta_key`, `meta_value`) 
VALUES (NULL, (Select max(id) FROM prefix_users), 'prefix_user_level', '10');

Make sure you specify your prefix in prefix_capabilities in the prefix_usermeta table, and prefix_user_level in the prefix_usermeta table (and notice the prefix_capabilities, and prefix_user_level above as well). On a side note, if you have multiple wordpress installs in different directories on the same website make sure prefix_user_roles in prefix_options has the right prefix. Let us know if you have any problems with these directions and we’ll see if we can’t point you in the right direction.

Dusting off the cobwebs

So it’s been awhile since I blogged anything and so much has happened….recently I moved servers from a managed server to a Linode server because I felt like I needed the root access and the responsibility of keeping up my own server. So in my last job I got a lot of experience maintaining my own server (really several servers with MySQL replication setup) and learned a lot about server security and running my own websites. So why Linode? Well, it was recommended to me years ago by a knowledgeable friend and after doing some research on pricing and server stats…how many cores, what kind of CPU, how much throughput per month and will it scale at a reasonable price when traffic increases. I chose Ubuntu for my OS since that’s what I’ve gotten comfortable with and it has huge community support and has been rock solid for me so far. I installed the LAMP stack using this LAMP install guide, because what you get is very bare bones and you are really building up the server yourself. Of course you need to lock down the server fairly quickly because most applications start out fairly wide open when first installed. This Linode security doc was a great help in reminding me what aspects to secure first. First create a standard login user with SUDO access (SUDO access allows a regular user account to act as root)….this is the account you will login with and upload/download files with. Also add it to the same group as www-data user (what the APACHE thread runs as). This makes it so that Apache can access the files and directories you’ve uploaded, and also has the handy feature of making it easy to see what files you’ve uploaded and what files have been created by your server scripts, or uploaded via Apache (which is one of the most vulnerable points of any server).

So moving servers was a real pain…I upgraded my PHP to 7.2 (really wanted the 50% increase in server code execution speed this is supposed to give you), upgraded MySQL servers to 5.7.25, APACHE to 2.4.38…upgrading everything gives me increased security from having all the latest bug fixes and security patches, but also called for a lot of code changes. Also the same reason I upgraded from Ubuntu 18 to Ubuntu 19 which was an adventure in and of itself. This was the
Ubuntu upgrade guide I used, and it came out pretty smooth. Before I upgraded I also had to install sendmail (so my php programs could “mail”). There are multiple mail servers to use, and I will probably use a more advanced one for when I create email accounts with my domains, but sendmail is nice just to get my contact forms back up and running and sendmail is rock solid.

Upgrading to PHP 7.2 (and really any pre-7 to PHP 7) primarily consists of updating the MySQL calls…now ideally I would want to take my current custom code and implement a shiny new frame work like Laravel which has all the code updates for PHP 7, BUT it was quicker to just update my current code base. So my SQL queries were fairly basic, nothing too fancy, so they remained the same and you are just changing these mysql functions with these mysqli procedural versions of the functions and you just search and replace strings like “mysql_query(” with “mysqli_query($connection,” ….the caveat being you need to make sure all your function calls have access to $connection…also mysql_error() with “mysqli_error($connection)” (and/or mysql_error($connection)), etc. Not easy. Check the mysql logs to see what errors are being thrown and fix as you go until all the pages are compiling and no errors are appearing in the logs.

So some other big things I did was move my project code to Bitbucket and Git instead of using Github and SVN, upgrade my very, very old WordPress websites to the latest version including updating the PHP code to 7, installed free SSL certs with LetsEncrypt, installed PHPMyAdmin, Webmin, Fail2Ban Firewall, and put everything behind Cloudflare, and setup local development environments which I will detail in later articles.

The 2 best things since sliced bread

Not going to talk a lot here, but I wanted to share 2 quick things. If you are not using Cloudflare…..use it. It’s a CDN, but also so much more. It can protect your site from attacks and has a handy firewall, also a handy interface to handle your DNS, some nifty analytics, and can also handle your SSL cert to make it dead simple to go https. One of my favorite things is the speed optimizations where it can automatically minify your CSS and JS as well as do some very cool image optimization. Best of all it’s free for small companies and cheap for large….I use it on all my work sites and when I get some time I’m switching this site to it. They’ve also just implemented a new geocentric load balancer that I’m excited to try.
The other things I wanted to mention was this site HTACCESS Tester. If you’ve ever had to deal with an htaccess file, and who hasn’t if you’re doing serious web dev for SEO, you know it’s a pain in the ass….it can do remarkable things w/url rewrites and 301’s, BUT it can be incredibly evil as well. You probably already know about the tag you can insert into your virtual host configuration to turn on logging for htaccess (LogLevel alert rewrite:trace6), but that log is waaaay too much info, especially with a large .htaccess file. Enter htaccess tester. Now you can write a rule and check if it gets applied the way you think it will…seriously, it’s a life saver.

Dual Pivot Quicksort Kicks Butt!

So while I was checking out different flavors of quicksort after taking the Coursera Algorithms class I found out about a new version of quicksort that was much faster then I had anticipated.  Java 7 had recently modified their sort function to use a new algorithm called Dual Pivot Quicksort, so I thought I’d check it out.  I found a java version and recoded it to be javascript.  It works well, but currently only sorts integers and in ascending order.  Ideally I should modify it to work the same way the normal array sort algorithm works, that way I’d be comparing apples to apples.  I believe under the hood that the V8 javascript engine has upgraded to the new dual pivot algorithm, but it does have some additional checks and improved functionality where you can pass in the sorting algorithm, which may be why it’s consistently slower then my javascript version of dual pivot quicksort that I coded up.  It’s consistently 10%-50% faster then the default array.sort() algorithm.  The default sort is going to work well enough for 90% of your sorting cases, but if you are following the 10/90 rule and have narrowed down the bottleneck in your code and want to optimize sort, then I would advise taking this code and modifying it for your needs since it will always be faster then the default array.sort().  Check it out on JSPerf http://jsperf.com/javascript-quicksort-comparisons

Technically JS Perf says it’s ±10.25% faster then the default sort the last time I ran it, but it does vary quite a bit. My guess is that it probably varies based on how random the shuffle is.  I suppose it could be because we are comparing a lion to a cheetah….the default sort sorts any object, and lets you pass in the sorting function, while the dual pivot quicksort I coded up only works on integers and in ascending order, but I’d still say it’s worth looking into, ESPECIALLY if whatever language you are coding in hasn’t rewritten their quicksort to use the new algorithm.  I made it a single variable module, and you call it with DualPivotQuicksort.sort(arr). Here’s the code.


/******** Dual Pivot QuickSort ***************/

var DualPivotQuicksort = (function() {

    var dualPivotQS = {};

    dualPivotQS.sort = function(arr, fromIndex, toIndex) {
        if(fromIndex === undefined && toIndex === undefined){
            this.sort(arr, 0, arr.length);
        } else{
            rangeCheck(arr.length, fromIndex, toIndex);
            dualPivotQuicksort(arr, fromIndex, toIndex - 1, 3);
        }
        return arr;
    }

    function rangeCheck(length, fromIndex, toIndex) {
        if (fromIndex > toIndex) {
            console.error("fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            console.error(fromIndex);
        }
        if (toIndex > length) {
            console.error(toIndex);
        }
    }

    function swap(arr, i, j) {
        var temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    function dualPivotQuicksort( arr, left, right, div) {
        var len = right - left;

        if (len < 27) { // insertion sort for tiny array
            for (var i = left + 1; i <= right; i++) {
                for (var j = i; j > left && arr[j] < arr[j - 1]; j--) {
                    swap(arr, j, j - 1);
                }
            }
            return;
        }
        var third = Math.floor(len / div); //TODO: check if we need to round up or down or just nearest

        // "medians"
        var m1 = left  + third;
        var m2 = right - third;

        if (m1 <= left) {
            m1 = left + 1;
        }
        if (m2 >= right) {
            m2 = right - 1;
        }
        if (arr[m1] < arr[m2]) {
            swap(arr, m1, left);
            swap(arr, m2, right);
        }
        else {
            swap(arr, m1, right);
            swap(arr, m2, left);
        }
        // pivots
        var pivot1 = arr[left];
        var pivot2 = arr[right];

        // pointers
        var less  = left  + 1;
        var great = right - 1;

        // sorting
        for (var k = less; k <= great; k++) {
            if (arr[k] < pivot1) {
                swap(arr, k, less++);
            }
            else if (arr[k] > pivot2) {
                while (k < great && arr[great] > pivot2) {
                    great--;
                }
                swap(arr, k, great--);

                if (arr[k] < pivot1) {
                    swap(arr, k, less++);
                }
            }
        }
        // swaps
        var dist = great - less;

        if (dist < 13) {
            div++;
        }
        swap(arr, less  - 1, left);
        swap(arr, great + 1, right);

        // subarrays
        dualPivotQuicksort(arr, left,   less - 2, div);
        dualPivotQuicksort(arr, great + 2, right, div);

        // equal elements
        if (dist > len - 13 && pivot1 != pivot2) {
            for (var k = less; k <= great; k++) {
                if (arr[k] == pivot1) {
                    swap(arr, k, less++);
                }
                else if (arr[k] == pivot2) {
                    swap(arr, k, great--);

                    if (arr[k] == pivot1) {
                        swap(arr, k, less++);
                    }
                }
            }
        }
        // subarray
        if (pivot1 < pivot2) {
            dualPivotQuicksort(arr, less, great, div);
        }
    }
    return dualPivotQS;
}());

/************************************************/

Javascript Modular Design

So I just completed my update of my Facebook app My Amazon Wishlist  I converted all of my messy initialization and jquery UI event handling code into a nice neat single variable javascript module.  It is sooooo much prettier….cleaner, more modular (it’s right there in the name!), less likely to interfere with any other javascript includes.  I briefly contemplated creating javascript objects for the lists….if I were to recode it from the start that’s how I would do it, but for now I’ll leave it as is because cloning the objects is faster and it can stay as is until I decide to implement more features.  The back-end is all php objects, and has made it incredibly easy to update and add features, as well as re-use in my wordpress plugin.  I also updated from jQuery 1.8.1 to 1.10 and had to update a few deprecated function calls that were removed in 1.9 ….GO $(document).on(‘click’, ‘id’, function(){});!…I also had to replace window.parent.document calls inside an iframe with  with jQuery postmessage calls….they actually turned out quite nicely….you have to setup a listener in the parent frame, then in the iframe (or another website even..it solves the cross-domain problem). post the message to the parent.  In my case I was sending multiple pieces of data, so I put it into an array, stringified it and passed it to the parent.  One thing I would note….in the listener you should make it so that it only accepts messages from the website you expect to be sending messages.  Here’s the code from the iframe:

var msgArray = new Object();
msgArray[‘newHeight’] = $(‘#aws-item’).height().toString();
msgArray[‘listNo’] = listNo;
msgArray[‘itemNo’] = itemNo;
msgArray[‘iframeID’] = iframeID;
var message = JSON.stringify(msgArray);
parent.window.postMessage(message, ‘*’);

And so ends my first article for my new website!  I think I’ll write the next one on how I localized (L10N) my WordPress plugin http://wordpress.org/plugins/easy-amazon-wishlist/