January 23, 2012

Displaying Multiple Images in WP E-Commerce

I needed a way of displaying multiple images in a WP e-commerce installation. In order to do this I hacked the wpsc-single_product.php file that was being used in my theme (the one copied across to the theme folder)

I replaced the following code form line 32 onwards

32
33
34
35
36
37
38
<a rel="<?php echo wpsc_the_product_title(); ?>" class="<?php echo wpsc_the_product_image_link_classes(); ?>" href="<?php echo wpsc_the_product_image(); ?>">
	<img class="product_image" id="product_image_<?php echo wpsc_the_product_id(); ?>" alt="<?php echo wpsc_the_product_title(); ?>" title="<?php echo wpsc_the_product_title(); ?>" src="<?php echo wpsc_the_product_thumbnail(get_option('product_image_width'),get_option('product_image_height'),'','single'); ?>"/>
</a>
<?php 
if ( function_exists( 'gold_shpcrt_display_gallery' ) )
	echo gold_shpcrt_display_gallery( wpsc_the_product_id() );
?>

with

sb_get_images_for_product(wpsc_the_product_id());//...then display all of the images

sb_get_images_for_product($id) is a function that I wrote into the themes functions.php file as follows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function sb_get_images_for_product($id){
	global $wpdb;
	$attachments = $wpdb->get_results($wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_parent = $id AND post_type = 'attachment' ORDER BY menu_order ASC"));
	$count=0;
	foreach ($attachments as $attachment){
		$count++;
		if ($count==1){//set up first image
			echo "<table><tr><td>";
			$image_attributes = wp_get_attachment_image_src($attachment->ID,'thumbnail');?>
			<a rel="<?php echo wpsc_the_product_title(); ?>" href="<?php echo $attachment->guid; ?>" class="<?php echo wpsc_the_product_image_link_classes(); ?>">
				<img src="<?php echo $image_attributes[0]; ?>" alt="<?php echo wpsc_the_product_title(); ?>"/>
			</a></td></tr><tr><td>
			<?php 
		}
		else{
			$image_attributes = wp_get_attachment_image_src($attachment->ID,'thumbnail');?>
			<a rel="<?php echo wpsc_the_product_title(); ?>" href="<?php echo $attachment->guid; ?>" class="<?php echo wpsc_the_product_image_link_classes(); ?>">
				<img class="resize" src="<?php echo $image_attributes[0]; ?>" alt="<?php echo wpsc_the_product_title(); ?>"/>
			</a>		
			<?php
		}
	}
	echo "</td></tr></table>";
}

to tidy up the images I also added a little bit of css to the single_product.php as follows

<style>
.resize {  
  width: 35px;  
  height : auto;  
}  
 
.resize {  
  width: auto;  
  height : 35px;  
}
 
#TB_additional_images {
	margin-left:8px;
}
</style>

January 11, 2012

Nested categories in WordPress not playing ball

UPDATE** AH! Typically, as soon as I find a hack for a problem I find someone has fixed it far more satisfactorily http://wordpress.org/extend/plugins/category-checklist-tree/

This has been frustrating for a while, but particularly when the same problem reared up in WP e-commerce.

Effectively, when you create a new post (or in the case of WP e-commerce, a new product) I expect the category tree in which I select the appropriate category to look like I created it to look, properly nested according to the tree hierarchy I have created. But it doesn’t… as soon as you start to use categories, WordPress presumes you are more likely to want to use the same categories in future and filters them out and places them at the top of the list…

The only thing I have found to cure this is a core wordpress hack… never my favourite solution but so far the only one I have discovered (I have some ideas for a plugin, but they haven’t come to fruition yet)

The problem occurs in wp-admin/includes/template.php within the function wp_category_checklist


function wp_terms_checklist($post_id = 0, $args = array()) {
$defaults = array(
'descendants_and_self' => 0,
'selected_cats' => false,
'popular_cats' => false,
'walker' => null,
'taxonomy' => 'category',
'checked_ontop' => true
);
extract( wp_parse_args($args, $defaults), EXTR_SKIP );

if ( empty($walker) || !is_a($walker, ‘Walker’) )
$walker = new Walker_Category_Checklist;

$descendants_and_self = (int) $descendants_and_self;

$args = array(‘taxonomy’ => $taxonomy);

$tax = get_taxonomy($taxonomy);
$args['disabled'] = !current_user_can($tax->cap->assign_terms);

if ( is_array( $selected_cats ) )
$args['selected_cats'] = $selected_cats;
elseif ( $post_id )
$args['selected_cats'] = wp_get_object_terms($post_id, $taxonomy, array_merge($args, array(‘fields’ => ‘ids’)));
else
$args['selected_cats'] = array();

if ( is_array( $popular_cats ) )
$args['popular_cats'] = $popular_cats;
else
$args['popular_cats'] = get_terms( $taxonomy, array( ‘fields’ => ‘ids’, ‘orderby’ => ‘count’, ‘order’ => ‘DESC’, ‘number’ => 10, ‘hierarchical’ => false ) );

if ( $descendants_and_self ) {
$categories = (array) get_terms($taxonomy, array( ‘child_of’ => $descendants_and_self, ‘hierarchical’ => 0, ‘hide_empty’ => 0 ) );
$self = get_term( $descendants_and_self, $taxonomy );
array_unshift( $categories, $self );
} else {
$categories = (array) get_terms($taxonomy, array(‘get’ => ‘all’));
}

if ( $checked_ontop ) {
// Post process $categories rather than adding an exclude to the get_terms() query to keep the query the same across all posts (for any query cache)
$checked_categories = array();
$keys = array_keys( $categories );

foreach( $keys as $k ) {
if ( in_array( $categories[$k]->term_id, $args['selected_cats'] ) ) {
$checked_categories[] = $categories[$k];
unset( $categories[$k] );
}
}

// Put checked cats on top
echo call_user_func_array(array(&$walker, ‘walk’), array($checked_categories, 0, $args));
}
// Then the rest of them
echo call_user_func_array(array(&$walker, ‘walk’), array($categories, 0, $args));
}

The trick is to set $checked_ontop to false as follows


$checked_ontop=false;
if ( $checked_ontop ) {
// Post process $categories rather than adding an exclude to the get_terms() query to keep the query the same across all posts (for any query cache)
$checked_categories = array();
$keys = array_keys( $categories );

foreach( $keys as $k ) {
if ( in_array( $categories[$k]->term_id, $args['selected_cats'] ) ) {
$checked_categories[] = $categories[$k];
unset( $categories[$k] );
}
}

 

I suspect there must be a way of setting the value of $checked_ontop to false without hacking core files but I haven't found it yet