Categories
code Wordpress

WordPress tidbits

I recently attended the South Florida WordPress Developers Meetup in Davie. I wanted to re-cap some of the very useful pieces of tidbits that Michael Schofield presented at the meetup. He has a very easy way of presenting information. Michael does not hesitate to dig into the deep details of WordPress. I left the meetup feeling very happy armed with all the useful information he presented.

  1. You can create your own barebones theme by visiting underscores.me. This same website is also used to generate the base TwentyEleven, TwentyTwelve and TwentyThirteen themes that come bundled with the default install of WordPress. At a minimum, a theme can function with just 2 files: index.php and style.css. Michael did a great job at explaining each of the files with the theme. He dissected the code and did easy demos to explain how these files fit into the big picture.
  2. the_excerpt() function is used to display a 255 word excerpt of the blog post. However, this can be problematic if the post has a lot of non-text material in the beginning. An example could be images, special HTML formatting etc. In that case, you can use “get_the_excerpt()” alternatively. This function will strip out all the HTML before printing.
  3. How does WordPress determine which page to show? Here is a helpful infographic that shows how WordPress determines the correct template file to invoke. You can also find a simpler Black and White version of this Template Hierarchy at https://codex.wordpress.org/Template_Hierarchy
  4. For developers, a very useful tool that they can use for quick testing and validation: www.codepen.io. As Michael demonstrated the use of this tool live, I was fascinated with its power. Michael did a quick demo of how to create a Triangle using only CSS and also rotated the triangle. Very Cool indeed!
  5. Another very useful resource (one that I did not know existed) is the ability to test which CSS mechanisms are compliant with which browsers. www.caniuse.com to the rescue. THis will allow you to test which CSS clauses are compliant with each browser. A nice matrix shows you the answer easily.
  6. Also, dont forget the WordPress Codex.

Thanks to this meetup group, I was able to learn quite a few pieces of useful advice that we as developers find very pertinent. I will start using some of these resources in the future.

 

 

Categories
Wordpress

WordCamp 2014 Miami

Having successfully attended my first WordCamp late last year at WordCamp Orlando, I am a fan of these events. I am now looking forward to WordCamp Miami. It is the fifth anniversary event for WordCamp Miami. So this should be an event to remember. Here is the link to the website. The official dates are May 9, 10 and 11th.

Tickets will be available starting February. For more details, sign up on their mailing list.

I had written a post on my feedback from WordCamp Orlando here, so I hope WordCamp Miami can take some cues from this and incorporate this into their speaker presentations. While I understand Social Media and Buzz is important,  I think other WordPress specific issues have a broader impact, such as Security, Speed, scale-ability.

 

Categories
Wordpress

WordPress Speed-Up and Debugging Tips

AS I wrote in my earlier post, WordCamp Orlando 2013 was a very informative event for me. Much more informative in fact than some of the very expensive private conference training sessions. The open source community, especially the WordPress crowd, is more open to sharing their suggestions and ideas.

With that said, here is the summary of all the wonderful tidbits gathered at the event. I will try to broadly classify these below for easy reading.

PHP Debugging (graduate from var_dump)

1. USE IDE  (alternative to Sublime or Textmate)

2. Configure

3. Enable XDEBUG

4. Set Breakpoint

5. Load Page

When the speaker did a live demo of this debugging session using PHPStorm, it seemed like there was a whole new level to debugging PHP.  His recommendation was PHPStorm.

Performance and Speed Up Techniques

The speaker, Hristo, suggested the following tools for checking speed. He emphasized that you must measure your page speed first before, during and after any changes you make. In other words, speed checking tools are your friend(s).

  1. gtmetrix.com
  2. tools.pingdom.com

With these two tools, you are armed with the power of quantifiable measurement.

In addition, Hristo also provided the following pointers.

  1. Make a scroll map test (crazyegg.com).

  2. Reduce the number of posts per page

  3. Progressive page loading (infinite scroll)

I have done #2 of the above list and it has made a marked improvement.

Hristo also advised against going overboard with Social Media widgets and/or plugins. The reason is that these widgets/plugins will ping their respective servers, thereby inadvertently delaying the page loading for your site. Particularly, do not use IFRAME. The recommendation is to use one plugin that covers all the social networks (Facebook, Google+, LinkedIn, Twitter, Pinterest etc), instead of a separate plugin for each network.

He also suggested including only the fonts that you use to be loaded for each page.  Place fonts on your server locally and include them.

Images

  1. Use images with right sizes and specify dimensions.
  2. Smush your images using the WP Smush-It plugin from Yahoo.
  3. Use sprites in your themes

CSS and JS

  1. Minify your CSS and JavaScript files, using W3 Total Cache plugin

Compression

Use .htaccess rules intead of plugins: http://kb.siteground.com/enable-gzip-via-htaccess/

Leverage Browser Caching

The .htaccess rules: http://kb.siteground.com/leverage-browser-caching

Use a CDN Service

  • Measure if your site is working faster

  • Even local business can take advantage by the CDN

  • Bonus: “Always Online” service

Cache your content

  • Use opcode caching – APC, xCache

  • Use Memcached object cashing

  • User reverse proxies like Varnish, nGinx

Presentation Slides available at:

http://www.slideshare.net/siteground

Plugin Performance Profiler (P3 Plugin Analyzer) allows you to check plugin performance.

This last point about the P3 plugin is the most valuable piece. If there is one plugin you have to use for performance, this is the one. This will quickly tell you which of your plugins is having a detrimental effect on your page load times.

I would like to hear your thoughts on tips and techniques that you have employed in speeding up WordPress.

Categories
ecommerce Wordpress

Migrate osCommerce to WooCommerce

In one of my earlier posts, I described the process I followed to migrate from osCommerce to WooCommerce. While this may have been a tedious job without this handy plugin, there were a few quirks I had to sort out. This plugin is not authored by me. I just made a few changes to address a few things. All credit to the original author.

First, the categories were displaying twice, after the import process was completed. Secondly, if you have more than one image for a product, the plugin does not import the additional images.

For the first issue, see my post here to resolve it.

For the second issue, you can simply download the updated version here. Here is the full text version of the file:

<?php
/*
Plugin Name: Woocommerce osCommerce Import
Plugin URI: http://www.advancedstyle.com/
Description: Import products, categories, customers and orders from osCommerce to Woocommerce
Author: David Barnes
Version: 1.1
Author URI: http://www.advancedstyle.com/
*/
if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {

 function woocommerce_osc_submenu_page() {
 add_submenu_page( 'woocommerce', 'osCommerce Import', 'osCommerce Import', 'manage_options', 'woocommerce-osc-import', 'woocommerce_osc_submenu_page_callback' ); 
 }

 function woocommerce_osc_cartesian_product($a) {
 $result = array(array());
 foreach ($a as $k => $list) {
 $_tmp = array();
 foreach ($result as $result_item) {
 foreach ($list as $list_item) {
 $_tmp[] = array_merge($result_item, array($k => $list_item));
 }
 }
 $result = $_tmp;
 }
 return $result;
 }

 function woocommerce_osc_import_image($url){
 $attach_id = 0;
 $wp_upload_dir = wp_upload_dir();

 $filename = $wp_upload_dir['path'].'/'.sanitize_file_name(basename($url));

 if(file_exists($filename)){
 $url = $filename;
 }

 $enc_url = rtrim($_POST['store_url'],'/').'/image/'.rawurlencode(basename($url));

 //echo "Encoded URL ".$enc_url."<br>";

 if($f = @file_get_contents($enc_url)){
 file_put_contents($filename,$f);
 //echo "Writing to ".$filename."<br>";
 $wp_filetype = wp_check_filetype(basename($filename), null );

 $attachment = array(
 'guid' => $wp_upload_dir['url'] . '/' . basename( $filename ), 
 'post_mime_type' => $wp_filetype['type'],
 'post_title' => preg_replace('/\.[^.]+$/', '', basename($filename)),
 'post_content' => '',
 'post_status' => 'inherit'
 );
 $attach_id = wp_insert_attachment( $attachment, $filename, 37 );
 require_once(ABSPATH . 'wp-admin/includes/image.php');
 $attach_data = wp_generate_attachment_metadata( $attach_id, $filename );
 wp_update_attachment_metadata( $attach_id, $attach_data );
 }
 return $attach_id;
 }
 function woocommerce_osc_run_cats($parent=0, $parent_term_id=0){
 global $wpdb, $oscdb, $import_cat_counter;
 echo __LINE__."<br>";
 $categories = $oscdb->get_results("SELECT c.*, cd.* FROM categories c, categories_description cd WHERE c.categories_id=cd.categories_id AND cd.language_id=1 AND c.parent_id='".(int)$parent."'", ARRAY_A);
 if(!empty($categories)){
 foreach($categories as $category){
 $term = term_exists($category['categories_name'], 'product_cat', (int)$parent_term_id); // array is returned if taxonomy is given
 echo __LINE__."<br>";
 if ((int)$term['term_id'] == 0) {
 $term = wp_insert_term(
 $category['categories_name'], // the term 
 'product_cat', // the taxonomy
 array(
 //'description'=> $category['categories_id'],
 'parent'=> $parent_term_id
 )
 );
 delete_option('product_cat_children'); // clear the cache

 $attach_id = 0;
 if($category['categories_image'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.urlencode($category['categories_image']);
 $attach_id = woocommerce_osc_import_image($url);
 }
 //add_woocommerce_term_meta($term['term_id'], 'order',$category['sort_order']);
 add_woocommerce_term_meta($term['term_id'], 'display_type','');
 add_woocommerce_term_meta($term['term_id'], 'thumbnail_id',(int)$attach_id);
 add_woocommerce_term_meta($term['term_id'], 'osc_id',$category['categories_id']);
 woocommerce_osc_run_cats($category['categories_id'], $term['term_id']);
 $import_cat_counter ++;
 }else{
 woocommerce_osc_run_cats($category['categories_id'], $term['term_id']);
 echo __LINE__."<br>";
 }
 }
 }
 }

 function woocommerce_osc_submenu_page_callback() {
 global $wpdb, $oscdb, $import_cat_counter, $import_prod_counter;
 if(!empty($_POST)){
 $oscdb = new wpdb($_POST['store_user'],$_POST['store_pass'],$_POST['store_dbname'],$_POST['store_host']);
 if($oscdb->ready){
 echo '<p>Starting...<em>(If the page stops loading or shows a timeout error, then just refresh the page and the importer will continue where it left off. If you are using a shared server and are importing a lot of products you may need to refresh several times)</p>';
 // Do customer import
 if($_POST['dtype']['customers'] == 1){
 $country_data = $oscdb->get_results("SELECT * FROM countries", ARRAY_A);
 $countries_id = array();
 foreach($country_data as $cdata){
 $countries_id[$cdata['countries_id']] = $cdata;
 }
 $zones = array();
 $zone_data = $oscdb->get_results("SELECT zone_id, zone_code FROM zones", ARRAY_A);
 foreach($zone_data as $z){
 $zones[$z['zone_id']] = $z['zone_code'];
 }

 if($customers = $oscdb->get_results("SELECT c.customers_id, c.customers_firstname, c.customers_lastname, c.customers_telephone, c.customers_email_address, ab.entry_country_id, ab.entry_lastname, ab.entry_firstname, ab.entry_street_address, ab.entry_suburb, ab.entry_postcode, ab.entry_city, ab.entry_state, ab.entry_zone_id FROM customers c, address_book ab WHERE c.customers_id=ab.customers_id AND c.customers_default_address_id=ab.address_book_id", ARRAY_A)){
 foreach($customers as $customer){
 //echo "Importing Customer :".$customer['customers_firstname'].$customer['customers_lastname']."<br>";
 if ( !email_exists($customer['customers_email_address'])) {
 $original = strtolower(preg_replace("/[^A-Za-z0-9]/", '', $customer['customers_firstname'].$customer['customers_lastname']));
 $user_name = $original;

 $i = 1;
 while($user_id = username_exists( $user_name )){
 $user_name = $original.$i;
 $i++;
 }

 $random_password = wp_generate_password();
 $user_id = wp_create_user( $user_name, $random_password, $customer['customers_email_address'] );

 $data = array('first_name' => $customer['customers_firstname'],
 'last_name' => $customer['customers_lastname'],
 'billing_country' => $countries_id[$customer['entry_country_id']]['countries_iso_code_2'],
 'billing_first_name' => $customer['entry_firstname'],
 'billing_last_name' => $customer['entry_lastname'],
 'billing_address_1' => $customer['entry_street_address'],
 'billing_address_2' => $customer['entry_suburb'],
 'billing_city' => $customer['entry_city'],
 'billing_state' => ($customer['entry_state'] != '' ? $customer['entry_state'] : $zones[$customer['entry_zone_id']]),
 'billing_postcode' => $customer['entry_postcode'],
 'billing_email' => $customer['customers_email_address'],
 'billing_phone' => $customer['customers_telephone'],
 'shipping_country' => $countries_id[$customer['entry_country_id']]['countries_iso_code_2'],
 'shipping_first_name' => $customer['entry_firstname'],
 'shipping_last_name' => $customer['entry_lastname'],
 'shipping_address_1' => $customer['entry_street_address'],
 'shipping_address_2' => $customer['entry_suburb'],
 'shipping_city' => $customer['entry_city'],
 'shipping_state' => ($customer['entry_state'] != '' ? $customer['entry_state'] : $zones[$customer['entry_zone_id']]),
 'shipping_postcode' => $customer['entry_postcode'],
 'osc_id' => $customer['customers_id']);
 foreach($data as $k => $v){
 update_user_meta( $user_id, $k, $v);
 }

 wp_update_user(array('ID' => $user_id, 'role' => 'customer'));

 $import_customer_counter++;
 }
 }
 }
 }
 //echo __LINE__;
 if($_POST['dtype']['products'] == 1){

 //woocommerce_osc_run_cats();
 //echo __LINE__;
 // Get all categories by OSC cat ID
 $categories = array();
 $terms = get_terms('product_cat',array('hide_empty' => 0));
 foreach ( $terms as $term ) {
 $o = get_woocommerce_term_meta($term->term_id,'osc_id',true);
 $categories[$o] = (int)$term->term_id;
 }
 //echo __LINE__;

 // Import the products
 if($products = $oscdb->get_results("SELECT p.*, pd.*, p2c.categories_id FROM products p, products_description pd, products_to_categories p2c WHERE p.products_id=pd.products_id AND pd.language_id=1 AND p.products_id=p2c.products_id", ARRAY_A)){
 foreach($products as $product){

 $existing_product = get_posts(array('post_type' => 'product','posts_per_page' => 1,'post_status' => 'any',
 'meta_query' => array(
 array(
 'key' => 'osc_id',
 'value' => $product['products_id'],
 )
 )));
 if(empty($existing_product)){
 $product_id = wp_insert_post(array(
 'post_title' => $product['products_name'],
 'post_content' => $product['products_description'],
 'post_status' => 'publish',
 'post_type' => 'product',
 'post_author' => 1
 ));
 echo "Importing Product ".$product['products_name']."<br>";
 update_post_meta($product_id, 'osc_id', $product['products_id']);
 wp_set_object_terms($product_id, 'simple', 'product_type');
 wp_set_object_terms($product_id, $categories[$product['categories_id']], 'product_cat');
 update_post_meta($product_id, '_sku', $product['products_model']);
 update_post_meta($product_id, '_regular_price', $product['products_price']);
 update_post_meta($product_id, '_price', $product['products_price']);
 update_post_meta($product_id, '_visibility', 'visible' );
 update_post_meta($product_id, '_stock_status', ($product['products_status'] ? 'instock' : 'outofstock'));
 update_post_meta($product_id, '_manage_stock', '1' );
 update_post_meta($product_id, '_stock', $product['products_quantity']);

 if($special = $oscdb->get_row("SELECT specials_new_products_price, expires_date FROM specials WHERE status=1 AND products_id='".$product_id."' LIMIT 1", ARRAY_A)){
 update_post_meta($product_id, '_sale_price', $special['specials_new_products_price']);
 $special['expires_date'] = strtotime($special['expires_date']);
 if($special['expires_date'] > time()){
 update_post_meta($product_id, '_sale_price_dates_to', date("Y-m-d",$special['expires_date']));
 update_post_meta($product_id, '_sale_price_dates_from', date("Y-m-d"));
 }
 }

 $attach_id = 0;
 if($product['products_image'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_image'];
 $attach_id = woocommerce_osc_import_image($url);
 }
 set_post_thumbnail($product_id, $attach_id);

 $subimages = array();

 reset($subimages);
 // BEGIN : Multiple Images
 if ($product['products_subimage1'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage1'];
 //echo "Found SubImage 1 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[0] = $attach_id; 
 }

 if ($product['products_subimage2'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage2'];
 //echo "Found SubImage 2 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[1] = $attach_id; 
 } 
 if ($product['products_subimage3'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage3'];
 //echo "Found SubImage 3 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[2] = $attach_id; 
 } 
 if ($product['products_subimage4'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage4'];
 //echo "Found SubImage 4 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[3] = $attach_id; 
 } 
 if ($product['products_subimage5'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage5'];
 //echo "Found SubImage 5 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[4] = $attach_id; 
 } 
 if ($product['products_subimage6'] != ''){
 $url = rtrim($_POST['store_url'],'/').'/image/'.$product['products_subimage6'];
 //echo "Found SubImage 6 : ".$url;
 $attach_id = woocommerce_osc_import_image($url);
 $subimages[5] = $attach_id; 
 } 

 //$subimages = array_filter($subimages);

 if (count($subimages) > 0)
 {
 if (count($subimages) == 1)
 {
 echo "Inserting Single Subimage ".$subimages[0]."<br>";
 update_post_meta( $product_id, '_product_image_gallery', $subimages[0] );
 }
 else 
 { 
 //print_r($subimages);
 echo "Inserting Multiple Subimages ".implode( ",", $subimages )."<br>";
 update_post_meta( $product_id, '_product_image_gallery', implode( ",", $subimages ) );
 }
 }
 else
 {
 echo "No Subimages Found";
 //print_r($subimages);
 //print_r($product);
 }

 unset($subimages);

 // END : Multiple Images

 // Handle attributes
 if($attributes = $oscdb->get_results("SELECT po.products_options_name, pov.products_options_values_name FROM products_attributes pa, products_options po, products_options_values pov WHERE pa.products_id='".$product['products_id']."' AND pov.products_options_values_id = pa.options_values_id AND pov.language_id=po.language_id AND po.language_id=1 AND pa.options_id=products_options_id", ARRAY_A)){
 wp_set_object_terms($product_id, 'variable', 'product_type');

 $attrib_array = array();
 $attrib_combo = array();
 $max_price = $product['products_price'];
 $min_price = $product['products_price'];
 foreach($attributes as $attribute){
 $slug = sanitize_title($attribute['products_options_name']);
 $attrib_array[$slug] = array('name' => $attribute['products_options_name'],
 'value' => ltrim($attrib_array[$slug]['value'].' | '.$attribute['products_options_values_name'],' | '),
 'position' => 0,
 'is_visible' => 1,
 'is_variation' => 1,
 'is_taxonomy' => 0);
 $attrib_combo[$slug][] = array($attribute['products_options_values_name'], ($attribute['price_prefix'] == '-' ? '-' : '').$attribute['options_values_price']);
 }
 // Now it gets tricky...
 $combos = woocommerce_osc_cartesian_product($attrib_combo);
 foreach($combos as $combo){
 $variation_id = wp_insert_post(array(
 'post_title' => 'Product '.$product_id.' Variation',
 'post_content' => '',
 'post_status' => 'publish',
 'post_type' => 'product_variation',
 'post_author' => 1,
 'post_parent' => $product_id
 ));

 $opt_price = $product['products_price'];

 $special_price = $special['specials_new_products_price'];

 foreach($combo as $k => $v){
 update_post_meta($variation_id, 'attribute_'.$k, $v[0]);
 $opt_price += $v[1];
 $special_price += $v[1];
 }
 update_post_meta($variation_id, '_sku', $product['products_model']);
 update_post_meta($variation_id, '_regular_price', $opt_price);
 update_post_meta($variation_id, '_price', $opt_price);
 update_post_meta($variation_id, '_thumbnail_id', 0);
 update_post_meta($variation_id, '_stock', $product['products_quantity'] );
 if($special){
 update_post_meta($variation_id, '_sale_price', $special_price);
 if($special['expires_date'] > time()){
 update_post_meta($variation_id, '_sale_price_dates_to', date("Y-m-d",$special['expires_date']));
 update_post_meta($variation_id, '_sale_price_dates_from', date("Y-m-d"));
 }
 }
 if($opt_price > $max_price){
 $max_price = $opt_price;
 }
 if($opt_price < $min_price){
 $min_price = $opt_price;
 }
 }

 update_post_meta($product_id, '_product_attributes', $attrib_array);
 update_post_meta($product_id, '_max_variation_regular_price',$max_price);
 update_post_meta($product_id, '_min_variation_regular_price', $min_price);
 update_post_meta($product_id, '_max_variation_price', $max_price);
 update_post_meta($product_id, '_min_variation_price', $min_price);
 }

 }
 }
 }
 }

 if($_POST['dtype']['orders'] == 1){
 $customers = $wpdb->get_results("SELECT ID FROM $wpdb->users", ARRAY_A);
 $customer_id = array();
 foreach($customers as $c){
 $osc_id = get_user_meta($c['ID'],'osc_id',true);
 $customer_id[$osc_id] = $c['ID'];
 }

 $product_id = array();
 $products_query = $wpdb->get_results("SELECT ID FROM $wpdb->posts WHERE post_type='product'", ARRAY_A);
 foreach($products_query as $p){
 $osc_id = get_post_meta($p['ID'],'osc_id',true);
 $product_id[$osc_id] = $p['ID'];
 }

 $country_data = $oscdb->get_results("SELECT * FROM countries", ARRAY_A);
 $countries_name = array();
 foreach($country_data as $cdata){
 $countries_name[$cdata['countries_name']] = $cdata;
 }

 if($orders = $oscdb->get_results("SELECT * FROM orders ORDER BY orders_id", ARRAY_A)){
 foreach($orders as $order){
 $existing_order = get_posts(array('post_type' => 'shop_order','posts_per_page' => 1,'post_status' => 'any',
 'meta_query' => array(
 array(
 'key' => 'osc_id',
 'value' => $order['orders_id'],
 )
 )));
 if(empty($existing_order)){
 $totals = array();
 if($total_query = $oscdb->get_results("SELECT * FROM orders_total WHERE orders_id='".$order['orders_id']."'", ARRAY_A)){
 foreach($total_query as $t){
 $totals[$t['class']] = $t;
 }
 }

 $order_key = 'order_'.wp_generate_password(13);

 $data = array('post_type' => 'shop_order',
 'post_date' => $order['date_purchased'],
 'post_author' => $customer_id[$order['customers_id']],
 'post_password' => $order_key,
 'post_title' => 'Order &ndash; '.date("M d, Y @ h:i A",strtotime($order['date_purchased'])),
 'post_status' => 'publish'
 );
 $order_id = wp_insert_post($data);

 $billing_namebits = explode(' ',$order['billing_name']);
 $billing_firstname = $billing_namebits[0];
 $billing_lastname = trim(str_replace($billing_namebits[0],'',$order['billing_name']));

 $shipping_namebits = explode(' ',$order['delivery_name']);
 $shipping_firstname = $shipping_namebits[0];
 $shipping_lastname = trim(str_replace($shipping_namebits[0],'',$order['delivery_name']));

 $meta_data = array('_billing_address_1' => $order['billing_street_address'],
 '_billing_address_2' => $order['billing_suburb'],
 '_wpas_done_all' => 1,
 '_billing_country' => $countries_name[$order['billing_country']]['countries_iso_code_2'],
 '_billing_first_name' => $billing_firstname,
 '_billing_last_name' => $billing_lastname,
 '_billing_company' => $order['billing_company'],
 '_billing_city' => $order['billing_city'],
 '_billing_state' => $order['billing_state'],
 '_billing_postcode' => $order['billing_postcode'],
 '_billing_phone' => $order['customers_telephone'],
 '_billing_email' => $order['customers_email_address'],
 '_shipping_country' => $countries_name[$order['delivery_country']]['countries_iso_code_2'],
 '_shipping_first_name' => $shipping_firstname,
 '_shipping_last_name' => $shipping_lastname,
 '_shipping_company' => $order['delivery_company'],
 '_shipping_address_1' => $order['delivery_street_address'],
 '_shipping_address_2' => $order['delivery_suburb'],
 '_shipping_city' => $order['delivery_city'],
 '_shipping_state' => $order['delivery_state'],
 '_shipping_postcode' => $order['delivery_postcode'],
 '_shipping_method_title' => $totals['ot_shipping']['title'],
 '_payment_method_title' => $order['payment_method'],
 '_order_shipping' => $totals['ot_shipping']['value'],
 '_order_discount' => $totals['ot_coupon']['value'] + $totals['ot_discount']['value'],
 '_order_tax' => $totals['ot_tax']['value'],
 '_order_shipping_tax' => 0,
 '_order_total' => $totals['ot_total']['value'],
 '_order_key' => $order_key,
 '_customer_user' => $customer_id[$order['customers_id']],
 '_order_currency' => $order['currency'],
 '_prices_include_tax' => 'no',
 'osc_id' => $order['orders_id']);
 foreach($meta_data as $k => $v){
 update_post_meta($order_id, $k, $v);
 }

 $order_import_counter++;

 if($order_products = $oscdb->get_results("SELECT * FROM orders_products WHERE orders_id='".$order['orders_id']."'", ARRAY_A)){
 foreach($order_products as $product){
 $item_id = woocommerce_add_order_item( $order_id, array(
 'order_item_name' => $product['products_name'],
 'order_item_type' => 'line_item'
 ) );

 if ( $item_id ) {
 $item_meta = array('_qty' => $product['products_quantity'],
 '_product_id' => $product_id[$product['products_id']],
 '_line_subtotal' => $product['final_price'] * $product['products_quantity'],
 '_line_total' => $product['final_price'] * $product['products_quantity']);
 foreach($item_meta as $k=>$v){
 woocommerce_add_order_item_meta($item_id,$k,$v);
 }
 } 

 }
 }
 }
 }
 }
 }

 $success = true;
 }else{
 echo '<p class="notice">Could not connect to the osCommerce database</p>';
 }
 }
 if($success){
 echo '<h3>The oscommerce data was successfully imported</h3>';
 if($_POST['dtype']['customers'] == 1){
 echo '<p><strong>Customers Imported: '.$import_customer_counter.'</p>';
 }
 if($_POST['dtype']['orders'] == 1){
 echo '<p><strong>Orders Imported: '.$order_import_counter.'</p>';
 }
 if($_POST['dtype']['products'] == 1){
 echo '<p><strong>Categories Imported: '.$import_cat_counter.'</p>';
 echo '<p><strong>Products Imported: '.$import_prod_counter.'</p>';
 }
 }else{
 ?>
 <form action="<?php echo $_SERVER['REQUEST_URI'];?>" method="post">
 <h3>Import data from osCommerce</h3>
 <p>Enter your oscommerce database information (you will need remote access to your oscommerce database)</p>
 <p><label>osCommerce store URL: <input type="text" name="store_url" value="<?php echo $_POST['store_url'];?>"></label></p>
 <p><label>osCommerce Database Host: <input type="text" name="store_host" value="localhost"></label></p>
 <p><label>osCommerce Database User: <input type="text" name="store_user" value="<?php echo $_POST['store_user'];?>"></label></p>
 <p><label>osCommerce Database Password: <input type="text" name="store_pass" value="<?php echo $_POST['store_pass'];?>"></label></p>
 <p><label>osCommerce Database Name: <input type="text" name="store_dbname" value="<?php echo $_POST['store_dbname'];?>"></label></p>
 <p>Data to Import:<br>
 <label><input type="checkbox" name="dtype[customers]" value="1"> Customers (passwords will not be transferred)</label><br>
 <label><input type="checkbox" name="dtype[orders]" value="1"> Orders</label><br>
 <label><input type="checkbox" name="dtype[products]" value="1"> Categories/Products</label>
 </p>
 <p><input type="submit" value="Import Data" class="button button-primary button-large"></p>
 </form>
 <?php
 }
 }
 add_action('admin_menu', 'woocommerce_osc_submenu_page',99);
}
?>
Categories
Wordpress

Wordcamp Orlando 2013: Thoughts and Reactions

WordCamp Orlando 2013 Logo
WordCamp Orlando 2013 Logo

I had been anticipating greatly this Wordcamp. One because of the proximity and second the quality of the speakers. So here is my personal views on WordCamp Orlando 2013 (held at UCF Rosen School Of Hospitality) November 16-17. Overall, this event was a major hit. As my first WordCamp, I am pleased to report this is an event I will continue to attend, over years to come.

Organization

In my eyes, for an event so large, WordCamp scored A+ in organization and friendliness.

1. The WordCamp was extremely well organized. The greeters were friendly and helpful. The name tags were clearly arranged on tables, according to registration level, i.e. camper, micro-sponsor etc.

2. The schedule was clearly displayed prominently in several locations, including the very convenient spot behind your registration name tag. Anytime that you wanted to refer to the schedule, it was within your reach. Great idea, kudos to the WordCamp team.

3. Rooms were clearly marked designating the relevant rooms for each track: developer, Designer or User.

4. The lunch was great, as were the steady supply of soft drinks, snacks and coffee.

Quality of Content

Overall, I think WordCamp receives a score of 8 on a scale of 1 to 10 for content. Even the SMX conference I attended last month was anywhere close in quality of content.

On the Developer track, the most interesting session was the one with Aaron Holbrooke discussing PHP debugging. Aaron did a phenomenal job of walking through a couple of solid real-world debugging example sessions. Listening to Aaron was refreshing and insightful, partly because he presented the material very well and also because he allowed an open Q & A session. The slides from his presentation are here. In short, my takeaway from his presentation was to use either NetBeans or PHPStorm for interactive PHP debugging.

WordPress and the Internet of Things by Tomas Puig was another interesting presentation. Tomas covered some very good statistics about the growth of non-computer devices connecting to the internet. This includes devices such as FitBit and Progressive Auto Sensor.

Of particular interest to me was the Need for Speed presentation by Hristo Pandjorav. Hristo is with Siteground, a WordPress specialized hosting company. He presented some very useful tools for measuring site speed and addressing the reasons for the delays. One of the key takeaways from Hristo’s presentation was summarized as follows. I found this to be the most enlightening aspect of his presentation. If you have ever done a Page Speed test, you know how the results indicate an overall grade and several different component grades. The following mechanism helps you prioritize your plan of attack.

  1. Sort performance issues by their severity
  2. Sort them by the time you need to fix them
  3. Cross-reference the two lists

While we are on the topic of speed, one of the questions (during the keynote presentation) was related to a plugin that can measure performance of all the installed plugins. The Plugin Performance Profiler (aka P3) was the answer.It is one of the first things I did on my blog. Sure enough, I found one culprit that was contributing the most to the page load times. It is super easy to use and provides a lot of high level and detailed level metrics that you can use for getting performance gains.

On the User track, Carol Gann of Orlando Web Wizard  covered the Visual Editor. Carol has a knack for engaging the audience. Carol tied the predisposition of individuals learning styles to their choice of visual editor. I think that was a unique take on the topic and made logical sense.

Conclusion

All in all, I thought WordCamp Orlando 2013 was a great event. The turnout was great, the speakers were of good quality. The food was excellent, the venue was amazing. The content was well presented by the speakers. Not to mention, there were goodies given out by Sponsors such as WP Engine, Site Ground, Constant Contact etc. If you also attended this WordCamp, I would love to hear your thoughts.