andy's php projects
Script and site usage:
All of the scripts on this site are provided free for non-commercial, personal or non-profit use. If you wish to use any of these in a commercial system, please refer to the payment plan.

Support:
Support for each of the scripts is given, free of charge, on the message board. Each script has its own message board which can be accessed by clicking on the 'project forum' link (beneath the description of each project).


Proudly hosted with Dreamhost

Save $20 when signing up for Dreamhost by using the promo code amnuts20


If you find these scripts useful to you, appreciate the free support, or are just an all round nice person, then why not donate a little dosh to encourage me to continue? Every little helps!

Zend Certified Engineer logo


CafePress Box

This class will display a random product from your CafePress store. You can supply a simple template to control style, and have the output link directly to the shown product or simply to your main account. You can cache the results so you don't have to connect to the CafePress website all the time. Images can also be cached locally, and can be resized before caching.

class.cafepressbox.php

The main class file. Please view the comments for any instructions on how to call the functions.

<?php

/**
 * $Id: class.cafepressbox.php 52 2007-02-27 11:47:46Z Andrew $
 *
 * Description
 *
 * This class will display a random product from your CafePress store.
 * You can supply a simple template to control style, and have the
 * output link directly to the shown product or simply to your main
 * account.  You can cache the results so you don't have to connect to
 * the CafePress website all the time.  Images can be cached and work
 * on the same time length as the product list caching.  Images can
 * also be resized as desired before saved into the cache.
 *
 * This has only been tested with the free accounts from CafePress,
 * and requires PHP 4.1.0+.  It has not been tested on PHP5.
 *
 * CafePress.com is copyright 1999-2006 CafePress.com.
 *
 * Author
 *
 * Andrew Collington <php@amnuts.com> <http://php.amnuts.com/>
 *
 * Feedback
 *
 * There is message board at the following address:
 *
 *     <http://php.amnuts.com/forums/>
 *
 * Please use that to post up any comments, questions, bug reports, etc.  You
 * can also use the board to show off your use of the script.
 *
 * Support
 *
 * If you like this script, or any of my others, then please take a moment
 * to consider giving a donation.  This will encourage me to make updates and
 * create new scripts which I would make available to you.  If you would like
 * to donate anything, then there is a link from my website to PayPal.
 *
 * Example of use:
 *
 *       $cp =& new cafePressBox('collingtons');
 *       $cp->setCacheDir('./cache');
 *       $cp->setCacheTime(86400);
 *       $cp->setCacheImages(true);
 *       $cp->setResizeCachedImages(120);
 *       $cp->displayItem(true);
 *
 * With a REALLY simple template and showing a specific product:
 *
 *       $cp =& new cafePressBox('amnuts');
 *       $cp->setTemplate('<div style="text-align:center;">[IMG]<br />[TXT]</div>');
 *       $cp->displayItem(false, 947369);
 *
 *    [IMG] is where the product image will be displayed
 *    [TXT] is where the product text will be displayed
 *
 * Example with using a category with a paid-for account:
 *
 *       $cp = new cafePressBox('amnuts', '123456');
 *       $cp->displayItem(true);
 */

class cafePressBox
{
    var 
$storeID;
    var 
$categoryID;
    var 
$products;
    var 
$template;
    var 
$cacheTime;
    var 
$cacheDir;
    var 
$cacheImages;
    var 
$cpPattern;
    var 
$resizeImage;

    
/**
     * Constructor
     *
     * @return cafePressBox
     * @param  bool $id
     * @param  bool $category
     * @access public
     */
    
function cafePressBox($id false$category false)
    {
        
$this->setStore($id$category);
        
$this->products = array();
        
$this->setCacheTime();
        
$this->setCacheDir();
        
$this->setTemplate();
        
$this->setCacheImages();
        
$this->setResizeCachedImages();
    }

    
/**
     * Even though you can pass the store id in the constructor, you can use
     * this function to change the store id.
     *
     * @return void
     * @param  string $id
     * @param  mixed $category
     * @access public
     */
    
function setStore($id$category false)
    {
        
$this->storeID    $id;
        
$this->categoryID $category;
        
$this->products   = array();
        
$this->setPattern();
    }

    
/**
     * Set the time out for the cache file.  If you do not with the results to
     * be cached, then set this to 0.  Time length is in seconds.
     *
     * @return void
     * @param  int $len
     * @access public
     */
    
function setCacheTime($len 0)
    {
        
$this->cacheTime $len;
    }

    
/**
     * Assign the directory to where the cache file will be saved
     *
     * @return void
     * @param  string $dir Path of directory
     * @access public
     */
    
function setCacheDir($dir '.')
    {
        
$this->cacheDir $dir . ($dir[strlen($dir)-1] != '/' '/' '');
    }

    
/**
     * Sets whether or not we should store images locally.  Image caching is
     * based on cache time.
     *
     * @return void
     * @param  bool $okay
     * @access public
     */
    
function setCacheImages($okay false)
    {
        
$this->cacheImages = ($okay === true) ? true false;
    }

    
/**
     * To resize cached images, set the width size with this function
     *
     * @return void
     * @param  int $size
     * @access public
     */
    
function setResizeCachedImages($size 0)
    {
        
$this->resizeImage = ($size 0) ? $size false;
    }

    
/**
     * The pattern string to find the products.  This is likely to change
     * if/when CafePress update their output.
     *
     * @return void
     * @param  string $pattern
     * @access public
     */
    
function setPattern($pattern '')
    {
        if (
$pattern == '') {
            
$this->cpPattern '<a href="/'.$this->storeID.'\.(\d+)"><img .*?alt="([^\"]*)" src="([^"]*)"></a>.*?<a href="/'.$this->storeID.'\.(\d+)">(.*?)</a><br>\$([^<]*)';
        } else {
            
$this->cpPattern $pattern;
        }
    }

    
/**
     * Set the display template.
     *
     * You can pass a string which has some special place holders.  These
     * place holders will then be replaced with the output from the
     * displayItem function.  The place holders are:
     *
     *    o [IMG] = the image
     *    o [TXT] = the text
     *
     * @return void
     * @param  string $template
     * @access public
     */
    
function setTemplate($template '')
    {
        static 
$default '<div style="text-align:center;width:150px;border:1px dashed black;font-family:Verdana, Arial, sans-serif;font-size:11px;text-decoration:none;"><div style="margin-top:5px;">[IMG]</div><br /><p style="margin:10px;">[TXT]</p></div>';

        if (
$template == '' || (!strstr($template'[IMG]') || !strstr($template'[TXT]'))) {
            
$this->template $default;
        } else {
            
$this->template $template;
        }
    }

    
/**
     * Display a random image from those in your inventory.
     *
     * @return void
     * @param  bool $link_to_product If true then add link directly to product information.
     * @param  int  $id Use this to display a particular product.  If the product is not listed then a random one will be chosen.
     * @access public
     */
    
function displayItem($link_to_product false$id false)
    {
        
$got false;
        
$txt $img '';

        
// get products
        
if (empty($this->products)) {
            
$got $this->_getProducts();
        }

        
// if no products now, we couldn't get any
        
if (empty($this->products)) {
            if (!
$got) {
                
$txt 'could not connect';
            } else {
                
$txt 'no products found';
            }
        } else {
            if (!
$id || !array_key_exists($id$this->products)) {
                
$id array_rand($this->products);
            }
            
$img .= '<a href="http://www.cafepress.com/' $this->storeID . ($link_to_product ".$id'/') . '">';
            if (
$this->cacheImages && @file_exists("{$this->cacheDir}{$this->products[$id]['image']}.jpg")) {
                
$sizes getimagesize("{$this->cacheDir}{$this->products[$id]['image']}.jpg");
                
$img .= '<img src="' $this->cacheDir $this->products[$id]['image'] . '.jpg" ' $sizes[3] . ' border="0" title="' $this->products[$id]['description'] . '" />';
            } else {
                
$img .= '<img src="' $this->products[$id]['image_url'] . '" height="150" width="150" border="0" title="' $this->products[$id]['description'] . '" />';
            }
            
$img .= "</a>\n";
            if (
$link_to_product) {
                
$product '<a href="http://www.cafepress.com/' $this->storeID ".$id\">" strtolower($this->products[$id]['description']) . '</a>';
            } else {
                
$product strtolower($this->products[$id]['description']);
            }
            
$txt 'Check out our ' $product ' and other great products at <a href="http://www.cafepress.com/' $this->storeID '/">Cafe Press</a>';
        }

        echo 
str_replace('[TXT]'$txtstr_replace('[IMG]'$img$this->template));
    }

    
/**
     * Saves parsed results to a cache file
     *
     * @return bool
     * @access private
     */
    
function _saveCache()
    {
        
$cache_file $this->cacheDir 'cache.' $this->storeID;
        if (
$this->categoryID) {
            
$cache_file .= '-' $this->categoryID;
        }
        if (
is_dir($this->cacheDir)) {
            
$fp fopen($cache_file'w');
            if (
$fp) {
                
fwrite($fpserialize($this->products));
                
fclose($fp);
                return 
true;
            } else {
                return 
false;
            }
        }
        return 
false;
    }

    
/**
     * Get the product information either from cache file or from CafePress website.
     *
     * @return bool Success of getting product list
     * @access private
     */
    
function _getProducts()
    {
        
$this->products = array();

        
$cache_file $this->cacheDir 'cache.' $this->storeID;
        if (
$this->categoryID) {
            
$cache_file .= '-' $this->categoryID;
        }
        if (
$this->cacheTime && file_exists($cache_file) && ((time() - @filemtime($cache_file)) < $this->cacheTime)) {
            
$this->products = @unserialize(@join('', @file($cache_file)));
        }
        if (empty(
$this->products)) {
            
// connect to the website
            
if ($this->categoryID === false) {
                
$reqheader "GET /cp/store.aspx?s={$this->storeID} HTTP/1.0\r\nHost: www.cafepress.com\r\nUser-Agent: RandomProduct\r\n\r\n";
            } else {
                
$reqheader "GET /cp/store.aspx?s={$this->storeID}.{$this->categoryID} HTTP/1.0\r\nHost: www.cafepress.com\r\nUser-Agent: RandomProduct\r\n\r\n";
            }
            
$errno  0;
            
$errstr '';
            
$socket fsockopen('www.cafepress.com'80$errno$errstr60);
            
// we have the socket open
            
if ($socket) {
                
fputs($socket$reqheader);
                while (!
feof($socket)) {
                    
$line fgets($socket4096);
                    
$matches = array();
                    if (
preg_match("|{$this->cpPattern}|i"$line$matches)) {
                        
$this->products[$matches[1]]['description'] = trim($matches[2]);
                        
$this->products[$matches[1]]['image'] = trim(basename($matches[3]));
                        
$this->products[$matches[1]]['image_url'] = trim($matches[3]);
                        
$this->products[$matches[1]]['price'] = "{$matches[6]}}";
                    }
                }
                
fclose($socket);

                if (
$this->cacheTime) {
                    
$this->_saveCache();
                }
                if (
$this->cacheImages && $this->cacheTime && is_dir($this->cacheDir)) {
                    
// as we're caching, grab the files too
                    
foreach($this->products as $product) {
                        
set_time_limit(120);
                        
$data '';
                        
$fp = @fopen($product['image_url'], 'r');
                        if (
$fp) {
                            while (!
feof($fp)) {
                                
$data .= fgets($fp4096);
                            }
                            
fclose($fp);
                            
$this->_saveImage($product['image'], $data);
                        }
                    }
                }
            } else {
                
// there was a problem
                
return false;
            }
        }
        return 
true;
    }


    
/**
     * Saves image to a file
     *
     * @return bool
     * @param  string $name file name of image
     * @param  string $data image data
     * @access private
     */
    
function _saveImage($name$data)
    {
        if (
is_dir($this->cacheDir)) {
            
$fp = @fopen($this->cacheDir.$name.'.jpg''w');
            if (
$fp) {
                
fwrite($fp$data);
                
fclose($fp);
                if (
$this->resizeImage) {
                    
$this->_doImageResize($this->cacheDir.$name.'.jpg');
                }
                return 
true;
            } else {
                return 
false;
            }
        }
        return 
false;
    }

    
/**
     * Resize an image based on class variable resizeImage
     *
     * @return void
     * @param  string $filename
     * @access private
     */
    
function _doImageResize($filename)
    {
        
$sizes = array();
        
$sizes = @getimagesize($filename);
        if (
$sizes[0] != $this->resizeImage) {
            
$imIn imagecreatefromjpeg($filename);
            
$height $sizes[1] / ($sizes[0] / $this->resizeImage);
            if (
$this->_isTrueColourSupported()) {
                
$imOut imagecreatetruecolor($this->resizeImage$height);
                if (
$imOut) {
                    
imagecopyresampled($imOut$imIn0000$this->resizeImage$height$sizes[0], $sizes[1]);
                }
            } else {
                
$imOut = @imagecreate($this->resizeImage$height);
                if (
$imOut) {
                    @
imagecopy($imOut$imIn0000$this->resizeImage$height$sizes[0], $sizes[1]);
                }
            }
            if (
$imOut) {
                
imagejpeg($imOut$filename100);
                
imagedestroy($imIn);
                
imagedestroy($imOut);
            }
        }
    }

    
/**
     * Can we generate a true colour image
     *
     * Sometimes a check for the GD version like this:
     *
     *     (function_exists('imagecreatetruecolor')) ? 2 : 1;
     *
     * can fail.  This method retrieves the GD information based on what PHP
     * reports to be installed.
     *
     * @return bool
     * @access private
     */
    
function _isTrueColourSupported()
    {
        if (
function_exists('gd_info')) {
            
$gdi = array();
            
$gdi gd_info();
            if (
preg_match('/^(bundled|2)/'$gdi['GD Version'])) {
                return 
true;
            }
        } else {
            
$buffer $line '';
            
ob_start();
            
phpinfo();
            
$buffer ob_get_contents();
            
ob_end_clean();
            foreach (
explode("\n"$buffer) as $line) {
                
$line array_map('trim', (explode('|'strip_tags(str_replace('</td>''|'$line)))));
                if (
'gd version' == strtolower($line[0]) && preg_match('/^(bundled|2)/'$line[1])) {
                    return 
true;
                }
            }
        }

        return 
false;
    }

}

?>
14.41kb in size
last modified Mar 20, 2007 at 4:52pm
6680 views, 7168 downloads

test.cafepressbox.php

A test script so you can see how easy it is to use.

1.79kb in size
last modified May 6, 2006 at 9:54pm
4994 views, 5218 downloads
list all projects :: this project's forum :: script in action
added Jun 12, 2003 at 6:57pm :: updated Mar 20, 2007 at 10:06am :: 2 files :: 29304 views

© Andrew Collington, 2002-2007.