I am a jack of all trades. Excepting those trades I do not like. I am a web developer of simple, reliable solutions to problems.

Search by Category in Shopp

Today I saw a thread on the Shopp forums asking how to limit a search to a particular category. As this was on my big list, I decided to tackle it.

It turns out to not be very difficult, once you understand the way Shopp handles searches.

The trick is that the category template (i.e., theme/shopp/category.php) is used to display searches. This allows you to easily jump in and decide how it is displayed, based on your own criteria.

So, you will want to create a copy of your category.php file named something like category-default.php. Then create a separate file named category-search.php. The former file will handle the default category page functionality. The second will handle searches only.

In category.php, do something like this:

if(isset($_GET['s']) && isset($_GET['catalog']))
{
	include_once('category-search.php');
}
else
{
	include_once('category-default.php');
}

Basically, if the URL parameters for a search exist, use the search template, otherwise, stick to the normal game plan.

Then in category-search.php, you’re going to want to use your own loop to exclude every category but the one you’re interested in:

<?php 
if(isset($_GET['category']))
{
	$category = $_GET['category'];
}
?>
<?php if (shopp('category','has-products')): ?>
	<?php while(shopp('category','products')): ?>
	 	<?php if(shopp('product','in-category',"name=$category") || (!isset($category) || $category == "Everything")): ?>
		// your code to display in your own html using the product tags (model it after the default category template, for example)
 
		<?php endif; ?>
	<?php endwhile; ?>

Lastly, you’ll want to render the search form yourself instead of using the default widget. For example:

			<form id="search" action="<?php bloginfo('url'); ?>" method="get" accept-charset="utf-8"> 
				<div class="search-perimeter">
					<input autocomplete="off" class="search" type="text" name="s" value="" id="find" /> 
					<select size=1 name="category" id="category-dropdown" title="Search in">
						<option value="Category 1 Name">Category 1 Name</option>
						<option value="Category 2 Name">Category 2 Name</option>
						<option value="Everything">Everything</option>
					</select>
					<input type="image" class="search-button" src="<?php bloginfo( 'template_url' ); ?>/images/search.png" />
				</div>
				<input type="hidden" name="catalog" value="true" id="catalog" />
			</form>

That’s about all there is to it. You’ll have to get in deep with the templates, but I think you’ll agree this is conceptually pretty simple.

Lastly, you should note: Category names seem to be case sensitive. “Bags” != “bags”

Good luck,
Clif

Improve HTML E-mails from WordPress, automagically

HTML e-mails are like wild stallions.  They are really hard to tame.

I have been frustrated by the vastly different ways e-mails from my company’s site (http://www.mooreandgiles.com) render in different clients.  After some research, I decided the trick to fix this would be inlining all CSS styles, as various clients will haphazardly abort style blocks you include in your e-mails.

Being lazy and wanting to the greatest flexibility for modifying templates in the future, I came up with a way to automatically process e-mails and inline their styles as they leave.   As this hooks into wp_mail, it should work with most plugins that send HTML e-mails.  Some may go around WordPress and use PHP mail…I can’t help you there.

In your theme functions file, add this:

add_filter('wp_mail', 'html_email_prep');
 
function html_email_prep($email) {
	if(strpos($email['headers'], "html") != false )
	{
		$message = $email['message'];
 
		//Grab CSS block
		require_once TEMPLATEPATH.'/css_to_inline_styles.php';
 
		$cssConverter = new CSSToInlineStyles();
		$cssConverter->setCleanup(true);
		$cssConverter->setHTML($message);
		$cssConverter->setUseInlineStylesBlock(true);
 
		$new_html = $cssConverter->convert();
 
		$email['message'] = $new_html;
	}
 
	return $email;
}

And, simply dropp css_to_inline_styles.php in your theme folder. You may download it here: http://blog.verkoyen.eu/blog/p/detail/convert-css-to-inline-styles-with-php

With this in place, it will automatically parse outgoing e-mail messages. It will find the style block and inline each style, automagically. This instantly fixed most of the rendering problems I was having in various clients.

It automatically excludes e-mails that don’t have HTML. I have seen the class bork up one HTML template, but making a minor change to the markup avoided the problem easily. Make sure you test.