<?php

/**
* This class extends HTTP_Request and can be used to synchronize
* of local files with any remote sources via HTTP
*
* The HTTP_Sync class implementation is not completely realised
* within examples of of the HTTP_Request class
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt.  If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category   HTTP
* @package    HTTP_Sync
* @author     Ildar N. Shaimordanov <ildar-sh@mail.ru>
* @license    http://www.php.net/license/3_0.txt  PHP License 3.0
*/

require_once 'PEAR.php';
require_once 
'HTTP/Request.php';
require_once 
'HTTP/Sync/Download.php';

// {{{

class HTTP_Sync
{

    
// {{{

    /*
    * Target filename
    *
    * @var     string $_target
    * @access  private
    */
    
var $_target '';

    
// }}}
    // {{{

    /*
    * Source URL
    *
    * @var     string $_source
    * @access  private
    */
    
var $_source '';

    
// }}}
    // {{{

    /*
    * Last modified time
    *
    * @var     string $_lastModified
    * @access  private
    */
    
var $_lastModified null;

    
// }}}
    // {{{

    /*
    * Request params
    *
    * @var     array $_params
    * @access  private
    */
    
var $_params = array();

    
// }}}
    // {{{

    /*
    * HTTP_Request listener/downloader
    *
    * @var     HTTP_Sync_Download $_downloader
    * @access  private
    */
    
var $_downloader null;

    
// }}}
    // {{{

    /*
    * Constructor
    *
    * Creates the object
    *
    * Example 1:
    * Synchronization of the local target file with the remote source as the static URL. 
    * The target filename will get from the URL. 
    * <code>
    * include_once 'HTTP/Sync.php';
    * 
    * $target = '';
    * $source = 'http://www.example.com/path/to/static/source.html';
    * $lastModified = strtotime('2006/06/06 06:06:06');
    * 
    * // HTTP request parameters
    * $params = array(
    *     // HTTP_Request parameters
    *     // (...)
    * );
    * 
    * // initialize object
    * $sync =& new HTTP_Sync($target, $source, $lastModified, $params);
    * 
    * // check local file (it exists and fresh)
    * // if it necessary to download and save
    * $result = $sync->synchronize();
    * 
    * // check result and handle it
    * if ( is_bool($result) ) {
    *     // here any code to working with valid data
    *     // (...)
    *     $filename = $sync->getTarget();
    *     echo file_get_contents($filename);
    * } else {
    *     echo 'Error occurs:';
    *     echo '<pre>' . print_r($result, true) . '</pre>';
    * }
    * </code>
    *
    * Example 2:
    * Syncronization of the local target file with the remote source as the dynamic URL. 
    * The local filename is set manually. 
    * <code>
    * include_once 'HTTP/Sync.php';
    * 
    * $target = 'local-file-name';
    * $source = 'http://www.example.com/path/to/dynamic-source?with=any&params=here';
    * $lastModified = strtotime('2006/06/06 06:06:06');
    * 
    * // HTTP request parameters
    * $params = array(
    *     // HTTP_Request parameters
    *     // (...)
    * );
    * 
    * // initialize object
    * $sync =& new HTTP_Sync($target, $source, $lastModified, $params);
    * 
    * // check local file (it exists and fresh)
    * // if it necessary to download and save
    * $result = $sync->synchronize();
    * 
    * // check result and handle it
    * if ( is_object($result) ) {
    *     // here any code to working with valid data
    *     // (...)
    *     $filename = $sync->getTarget();
    *     echo file_get_contents($filename);
    * } else {
    *     echo 'Error occurs:';
    *     echo '<pre>' . print_r($result, true) . '</pre>';
    * }
    * </code>
    *
    * @param   string  $target The filename (including path) where the remote source would be saved
    * @param   string  $source The URL to the remote source
    * @param   integer $lastModified The last modified timestamp of the target file
    * @param   string  $params Assoc.array as defined for the HTTP_Request
    *
    * @access  public
    */
    
function HTTP_Sync($target$source$lastModified=false$params=array())
    {
        
$this->_target $target;
        
$this->_source $source;
        
$this->_lastModified $lastModified $lastModified time();
        
$this->_params $params;
        
$this->_downloader null;
    }

    
// }}}
    // {{{

    /*
    * Returns the actual target filename. If the contsructor argument $target is empty string
    * this value will be returned from the HEAD request. 
    *
    * NB: This method returns a valid value for the defined target filename or successfully downloaded file
    *
    * @param   void
    *
    * @return  string The actual target filename
    *
    * @access  public
    */
    
function getTarget()
    {
        if ( 
$this->_target ) {
            return 
$this->_target;
        } else {
            if ( ! isset(
$this->_downloader) || empty($this->_downloader->_target) ) {
                
$this->_download(HTTP_REQUEST_METHOD_HEAD);
            }
            return 
$this->_downloader->_target;
        }
    }

    
// }}}
    // {{{

    /*
    * Check the local target file and if it is necessary download it from the remote source
    * If the target file is not exists in the system or filemtime less or equals to the lastModified parameter
    * then there will an attempt to connect, download from the remote source and save it
    *
    * @param   void
    *
    * @return  boolean True if the target file is outdated and had been downloaded from the source 
    *          or false if target file is not outdated or PEAR_Error on HTTP_Request error occurs
    *
    * @access  public
    */
    
function synchronize()
    {
        if ( ! 
file_exists($this->_target) || filemtime($this->_target) <= $this->_lastModified ) {
            
$result $this->_download();
            if ( 
PEAR::isError($result) ) {
                return 
$result;
            }
            return 
true;
        }
        return 
false;
    }

    
// }}}
    // {{{

    /*
    * Creates an instance of HTTP_Request attach a listener for download the source to the target file
    *
    * @param   void
    *
    * @return  Result of the HTTP_Request::sendRequest method
    *
    * @access  private
    */
    
function _download($method=null)
    {
        
$this->_downloader =& new HTTP_Sync_Download($this->_target);
        
$req =& new HTTP_Request($this->_source$this->_params);
        if ( 
$method ) {
            
$req->setMethod($method);
        }
        
$req->attach(& $this->_downloader);
        
$response $req->sendRequest(false);
        return 
$response;
    }

    
// }}}

}

// }}}

?>