[WooCommerce] Sort by Custom Attributes

Update

I created a plugin for this plus many other features. Click here to view it.

To add extra sorting options to your WooCommerce pages using products’ meta data you can use the following

http://docs.woothemes.com/document/custom-sorting-options-ascdesc/

However, I wanted to add some sorting options that use the WooCommerce’s custom attributes. According to this thread, the product attributes are saved in a serialized format in the database and therefore it’s not feasible to do it directly.

To use the provided WooCommerce filters the attributes should be saved as meta data.

When a post that has some custom attributes set is updated, the submitted data ($_REQUEST) contains the following:


'attribute_names' =>
 array (
 0 => 'pa_pub-year',
 1 => 'pa_pub-author',
...
 ),
 'attribute_position' =>
 array (
 0 => '1',
 1 => '1',
......
'attribute_is_taxonomy' =>
 array (
 0 => '1',
......
 ),
 'attribute_values' =>
 array (
 0 => '1990',
 1 => '',
 2 => '',
......
 ),

The approach I followed is to get the submitted attributes and save them as post meta data. Afterwards, the code provided by WooCommerce to sort using attributes, with a tiny modification, worked successfully.

The code is as follows


/************* Add sorting by attributes **************/

/**
 *	Defines the criteria for sorting with options defined in the method below
 */
add_filter('woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args');

function custom_woocommerce_get_catalog_ordering_args( $args ) {
	global $wp_query;
        // Changed the $_SESSION to $_GET
	if (isset($_GET['orderby'])) {
		switch ($_GET['orderby']) :
			case 'pa_pub-year' :
				$args['order'] = 'ASC';
				$args['meta_key'] = 'pa_pub-year';
				$args['orderby'] = 'meta_value_num';
			break;
		endswitch;
	}
	return $args;
}

/**
 *	Adds the sorting options to dropdown list .. The logic/criteria is in the method above
 */
add_filter('woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby');

function custom_woocommerce_catalog_orderby( $sortby ) {
	$sortby['pa_pub-year'] = 'Sort by Year: Older to Newer';
	return $sortby;
}

/**
 *	Save custom attributes as post's meta data as well so that we can use in sorting and searching
 */
add_action( 'save_post', 'save_woocommerce_attr_to_meta' );
function save_woocommerce_attr_to_meta( $post_id ) {
        // Get the attribute_names .. For each element get the index and the name of the attribute
        // Then use the index to get the corresponding submitted value from the attribute_values array.
	foreach( $_REQUEST['attribute_names'] as $index => $value ) {
		update_post_meta( $post_id, $value, $_REQUEST['attribute_values'][$index] );
	}
}
/************ End of Sorting ***************************/

This should be placed in the functions.php file of your theme.

 

MagCloud Widget WordPress plugin

HP MagCloud is a web service that empowers users to self-publish and distribute content—for business or personal use—as a professional-quality print publication or digitally for mobile and online viewing on today’s most popular devices. http://www.magcloud.com/learn

After uploading your PDF, one way of advertising your published magazine is to copy and paste some HTML code to your website. However, the HTML is not always matching the design of the blog. This widget will allow people to paste MagCloud HTML code, write their own template, and with the help of some short codes they get the output that match their themes.

I did it for a client but found it might be useful for somebody out there and here you go.

http://wordpress.org/extend/plugins/magcloud-widget/

[Django] Applying changes done to views.py immediately on Hostgator

Assumptions

You installed Django using Fcgi on Hostgator using their tutorial
https://support.hostgator.com/articles/django-with-fastcgi

To get the changes you just did to your views.py to be applied immediately to the deployed django application on hostgator .. Here are the steps:

  1. Use SSH to execute the following commands. (How to get your SSH to work)
  2. Get the processes of the current user
    ps -u CPANEL_USERNAME
  3. If your FCGI file name is index.fcgi, you should find it available in the list that the previous command showed. If not, then no process is currently running. Just visit your website now and the changes will be applied.
  4. If you find your index.fcgi file in the list, copy its ID (the 4-5 digits number that appears on the left).
  5. Finally, kill the process
    kill ID_YOU_GOT_IN_STEP_4
  6. Visit your website now, changes should be applied by now.

Technically speaking, when someone visits your django application on hostgator, FCGI process runs. This is done because of the htaccess file you create. The python files are compiled and ran in a, and i am quoting the FCGI website, a persistent isolated process. If people keep on visiting your website, the process will keep on running. If you make changes, they’re not compiled again because you have to wait till the current FCGI process ends. All we do here is to kill the running process and that will lead to compiling our code again, hence applying the changes.

If the application is private and no one, with you excluded, is visiting it yet .. Just wait for about 10 minutes for changes to be applied without refreshing or visiting the application. This way, the process will end and a new visit will compile the new code.

I don’t know yet the drawbacks of this but it’s perfect for the small application that I am working on now. Good luck!

[PHP] Counting Twitter characters

Quoting their official docs

To the human eye the length is clearly four characters. Depending on how the data is represented this could be either five or six UTF-8 bytes. Twitter does not want to penalize a user for the fact we use UTF-8 or for the fact that the API client in question used the longer representation. Therefore, Twitter does count “café” as four characters no matter which representation is sent.

The code to get a string’s length (like twitter) in php is to use the multi-byte strlen function


mb_strlen(utf8_decode(trim($tweet)), 'utf-8');

strlen would give the same result after using the decode function.

[Javascript] jQuery and Chrome extensions

Chrome extensions are usually based on javascript. Nowadays, jQuery is always used/though of when javascript is mentioned. Thus, it’s essential to know how to use jQuery – at least in the popup.

To get familiar with chrome extension development – check this out.

To trigger something when the page is loaded in javascript it’s usually the famous


$(document).ready(function(){
//whatever
});

This, unfortunately, will not work in the popup of your extension. Instead, I used another function


function ext_ready(){
//whatever
}

window.onload = ext_ready;

Ofcourse that is not my solution – but I read it somewhere long time ago that I forgot the resource. Probably it’s on stackoverflow somewhere.

[PHP] Validation

Validation is headache. Fortunately, this function makes it better. Sample usage is as follows:


function fields_validation($field){
	$validation_rules = array();
	if(isset($field->slug)){
		$slug = $field->slug;
	} else {
		$slug = sanitize_title($field->label);
	}
	$label = $field->label;
	if(intval($field->minLength) != '0'){
		$minLength = intval($field->minLength);
		$validation_rules[] = "length>=$minLength,$slug,$label must be at least $minLength characters long.";
	}
	if(intval($field->maxLength) != '0'){
		$maxLength = intval($field->maxLength);
		$validation_rules[] = "length<=$maxLength,$slug,$label must be $maxLength characters long maximum.";
	}				
	if($field->isEmail){
		$validation_rules[] = "valid_email,$slug,Please enter a valid email address.";
	}
	return $validation_rules;
}

and then call the function itself

$validation_rules = fields_validation($field);
$errors = validateFields($_POST, $validation_rules);

$errors will be an array. A simple !empty($errors) will check for errors.

The conditions represents the rule that must be true in order not to produce an error. For example, length <= $maxLength means that the length must be less than max length to pass the check. $slug is the name of the form’s field.