AJAX
[ class tree: AJAX ] [ index: AJAX ] [ all elements ]

Source for file Server.php

Documentation is available at Server.php

  1. <?php
  2. /**
  3.  * OO AJAX Implementation for PHP
  4.  *
  5.  * @category   HTML
  6.  * @package    AJAX
  7.  * @author     Joshua Eichorn <josh@bluga.net>
  8.  * @copyright  2005 Joshua Eichorn
  9.  * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
  10.  * @version    Release: @package_version@
  11.  */
  12.  
  13. /**
  14.  * Require the main AJAX library
  15.  */
  16. require_once 'HTML/AJAX.php';
  17.  
  18. /**
  19.  * Class for creating an external AJAX server
  20.  *
  21.  * Can be used in 2 different modes, registerClass mode where you create an instance of the server and add the classes that will be registered
  22.  * and then run handle request
  23.  *
  24.  * Or you can extend it and add init{className} methods for each class you want to export
  25.  *
  26.  * Client js generation is exposed through 2 _GET params client and stub
  27.  *  Setting the _GET param client to `all` will give you all the js classes needed
  28.  *  Setting the _GET param stub to `all` will give you stubs of all registered classes, you can also set it too just 1 class
  29.  *
  30.  * @category   HTML
  31.  * @package    AJAX
  32.  * @author     Joshua Eichorn <josh@bluga.net>
  33.  * @copyright  2005 Joshua Eichorn
  34.  * @license    http://www.opensource.org/licenses/lgpl-license.php  LGPL
  35.  * @version    Release: @package_version@
  36.  * @link       http://pear.php.net/package/PackageName
  37.  */
  38. {
  39.  
  40.     /**
  41.      * Client options array if set to true the code looks at _GET
  42.      * @var bool|array
  43.      */
  44.     var $options = true;
  45.  
  46.     /**
  47.      * HTML_AJAX instance
  48.      * @var HTML_AJAX 
  49.      */
  50.     var $ajax;
  51.  
  52.     /**
  53.      * Set to true if your extending the server to add init{className methods}
  54.      * @var boolean 
  55.      * @access  public
  56.      */
  57.     var $initMethods = false;
  58.  
  59.     /**
  60.      * Location on filesystem of client javascript library
  61.      * @var false|stringif false the default pear data dir location is used
  62.      */
  63.     var $clientJsLocation = false;
  64.  
  65.     /** 
  66.      * An array of options that tell the server howto Cache output
  67.      *
  68.      * The rules are functions that make etag hash used to see if the client needs to download updated content
  69.      * If you extend this class you can make your own rule function the naming convention is _cacheRule{RuleName}
  70.      *
  71.      * <code>
  72.      * array(
  73.      *  'httpCacheClient' => true,   // send 304 headers for responses to ?client=* requests
  74.      *  'ClientCacheRule' => 'File', // create a hash from file names and modified times, options: file|content
  75.      *  'ClientCacheExpects'=> 'files', // what type of content to send to the hash function, options: files|classes|content
  76.      *  'httpCacheStub'   => true,   // send 304 headers for responses to ?stub=* requests
  77.      *  'StubCacheRule'   => 'Api',  // create a hash from the exposed api, options: api|content
  78.      *  'StubCacheExpects'=> 'classes', // what type of content to send to the hash function, options: files|classes|content
  79.      * )
  80.      * </code>
  81.      *
  82.      * @var array 
  83.      * @access  public
  84.      */
  85.     var $cacheOptions = array(
  86.         'httpCacheClient'       => true
  87.         'ClientCacheRule'       => 'file',
  88.         'ClientCacheExpects'    => 'files',
  89.         'httpCacheStub'         => true
  90.         'StubCacheRule'         => 'api'
  91.         'StubCacheExpects'      => 'classes'
  92.         );
  93.  
  94.     /**
  95.      * Javascript library names and there path
  96.      *
  97.      * the return of $this->clientJsLocation(), is prepended before running readfile on them
  98.      *
  99.      * @access  public
  100.      * @var array 
  101.      */
  102.     var $javascriptLibraries = array(
  103.         'all'           =>  'HTML_AJAX.js',
  104.         'html_ajax'     =>  'HTML_AJAX.js',
  105.         'html_ajax_lite'=>  'HTML_AJAX_lite.js',
  106.         'json'          =>  'serializer/JSON.js',
  107.         'request'       =>  'Request.js',
  108.         'main'          =>  array('Compat.js','Main.js','clientPool.js'),
  109.         'httpclient'    =>  'HttpClient.js',
  110.         'dispatcher'    =>  'Dispatcher.js',
  111.         'util'          =>  'util.js',
  112.         'loading'       =>  'Loading.js',
  113.         'phpserializer' =>  'serializer/phpSerializer.js',
  114.         'urlserializer' =>  'serializer/UrlSerializer.js',
  115.         'haserializer'  =>  'serializer/haSerializer.js',
  116.         'clientpool'    =>  'clientPool.js',
  117.         'iframe'        =>  'IframeXHR.js',
  118.         'alias'         =>  'Alias.js',
  119.         'queues'        =>  'Queue.js',
  120.         'behavior'      =>  array('behavior/behavior.js','behavior/cssQuery-p.js'),
  121.  
  122.         // rules to help you use a minimal library set
  123.         
  124.         'standard'      =>  array('Compat.js','clientPool.js','util.js','Main.js','HttpClient.js','Request.js','serializer/JSON.js',
  125.                                     'Loading.js','serializer/UrlSerializer.js','Alias.js','behavior/behavior.js','behavior/cssQuery-p.js'),
  126.         'jsonrpc'       =>  array('Compat.js','util.js','Main.js','clientPool.js','HttpClient.js','Request.js','serializer/JSON.js'),
  127.         'proxyobjects'  =>  array('Compat.js','util.js','Main.js','clientPool.js','Request.js','serializer/JSON.js','Dispatcher.js'),
  128.  
  129.         // BC rules
  130.         
  131.         'priorityqueue' =>  'Queue.js',
  132.         'orderedqueue'  =>  'Queue.js',
  133.     );
  134.  
  135.     /**
  136.      * Custom paths to use for javascript libraries, if not set {@link clientJsLocation} is used to find the system path
  137.      *
  138.      * @access public
  139.      * @var array 
  140.      * @see registerJsLibrary
  141.      */
  142.     var $javascriptLibraryPaths = array();
  143.  
  144.     /**
  145.      * Array of className => init methods to call, generated from constructor from initClassName methods
  146.      *
  147.      * @access protected
  148.      */
  149.     var $_initLookup = array();
  150.     
  151.  
  152.     /**
  153.      * Constructor creates the HTML_AJAX instance
  154.      *
  155.      * @param string $serverUrl (Optional) the url the client should be making a request too
  156.      */
  157.     function HTML_AJAX_Server($serverUrl = false
  158.     {
  159.         $this->ajax = new HTML_AJAX();
  160.  
  161.         // parameters for HTML::AJAX
  162.         $parameters = array('stub''client');
  163.  
  164.         // keep in the query string all the parameters that don't belong to AJAX
  165.         // we remove all string like "parameter=something&". Final '&' can also
  166.         // be '&amp;' (to be sure) and is optional. '=something' is optional too.
  167.         $querystring '';
  168.         if (isset($_SERVER['QUERY_STRING'])) {
  169.             $querystring preg_replace('/(' join('|'$parameters')(?:=[^&]*(?:&(?:amp;)?|$))?/'''$this->ajax->_getServer('QUERY_STRING'));
  170.         }
  171.  
  172.         // call the server with this query string
  173.         if ($serverUrl === false{
  174.             $serverUrl htmlentities($this->ajax->_getServer('PHP_SELF'));
  175.         }
  176.  
  177.         if (substr($serverUrl,-1!= '?'{
  178.             $serverUrl .= '?';
  179.         }
  180.         $this->ajax->serverUrl =  $serverUrl htmlentities($querystring);
  181.         
  182.         $methods get_class_methods($this);
  183.         foreach($methods as $method{
  184.             if (preg_match('/^init([a-zA-Z0-9_]+)$/',$method,$match)) {
  185.                 $this->_initLookup[strtolower($match[1])$method;
  186.             }
  187.         }
  188.     }
  189.  
  190.     /**
  191.      * Handle a client request, either generating a client or having HTML_AJAX handle the request
  192.      *
  193.      * @return boolean true if request was handled, false otherwise
  194.      */
  195.     function handleRequest(
  196.     {
  197.         if ($this->options == true{
  198.             $this->_loadOptions();
  199.         }
  200.         //basically a hook for iframe but allows processing of data earlier
  201.         $this->ajax->populatePayload();
  202.         if (!isset($_GET['c']&& (count($this->options['client']> 0 || count($this->options['stub']> 0) ) {
  203.             $this->generateClient();
  204.             return true;
  205.         else {
  206.             if (!empty($_GET['c'])) {
  207.                 $this->_init($this->_cleanIdentifier($this->ajax->_getVar('c')));
  208.             }
  209.             return $this->ajax->handleRequest();
  210.         }
  211.     }
  212.  
  213.     /**
  214.      * Register method passthrough to HTML_AJAX
  215.      *
  216.      * @see HTML_AJAX::registerClass for docs
  217.      */
  218.     function registerClass(&$instance$exportedName = false$exportedMethods = false
  219.     {
  220.         $this->ajax->registerClass($instance,$exportedName,$exportedMethods);
  221.     }
  222.  
  223.     /**
  224.      * Change default serialization - important for exporting classes
  225.      *
  226.      * I wanted this for the xml serializer :)
  227.      */
  228.     function setSerializer($type
  229.     {
  230.         $this->ajax->serializer = $type;
  231.         $this->ajax->unserializer = $type;
  232.     }
  233.  
  234.     /**
  235.      * Register a new js client library
  236.      *
  237.      * @param string          $libraryName name you'll reference the library as
  238.      * @param string|array   $fileName   actual filename with no path, for example customLib.js
  239.      * @param string|false   $path   Optional, if not set the result from jsClientLocation is used
  240.      */
  241.     function registerJSLibrary($libraryName,$fileName,$path = false{
  242.         $libraryName strtolower($libraryName);
  243.         $this->javascriptLibraries[$libraryName$fileName;
  244.  
  245.         if ($path !== false{
  246.             $this->javascriptLibraryPaths[$libraryName$path;
  247.         }
  248.     }
  249.  
  250.     /**
  251.      * Register init methods from an external class
  252.      *
  253.      * @param object    $instance an external class with initClassName methods
  254.      */
  255.     function registerInitObject(&$instance{
  256.         $instance->server =$this;
  257.         $methods get_class_methods($instance);
  258.         foreach($methods as $method{
  259.             if (preg_match('/^init([a-zA-Z0-9_]+)$/',$method,$match)) {
  260.                 $this->_initLookup[strtolower($match[1])= array(&$instance,$method);
  261.             }
  262.         }
  263.     }
  264.  
  265.     /**
  266.      * Register a callback to be exported to the client
  267.      *
  268.      * This function uses the PHP callback pseudo-type
  269.      *
  270.      */
  271.     function registerPhpCallback($callback)
  272.     {
  273.         if (!is_callable($callback)) {
  274.             // invalid callback
  275.             return false;
  276.         }
  277.         
  278.         if (is_array($callback&& is_object($callback[0])) {
  279.             // object method
  280.             $this->registerClass($callback[0]strtolower(get_class($callback[0]))array($callback[1]));
  281.             return true;
  282.         }
  283.         
  284.         // static callback
  285.         $this->ajax->registerPhpCallback($callback);
  286.     }
  287.  
  288.     /**
  289.      * Generate client js
  290.      *
  291.      * @todo    this is going to need tests to cover all the options
  292.      */
  293.     function generateClient(
  294.     {
  295.         $headers = array();
  296.  
  297.         ob_start();
  298.  
  299.         // create a list list of js files were going to need to output
  300.         // index is the full file and so is the value, this keeps duplicates out of $fileList
  301.         $fileList = array();
  302.  
  303.         if(!is_array($this->options['client'])) {
  304.             $this->options['client'= array();
  305.         }
  306.         foreach($this->options['client'as $library{
  307.             if (isset($this->javascriptLibraries[$library])) {
  308.                 $lib = (array)$this->javascriptLibraries[$library];
  309.                 foreach($lib as $file{
  310.                     if (isset($this->javascriptLibraryPaths[$library])) {
  311.                         $fileList[$this->javascriptLibraryPaths[$library].$file$this->javascriptLibraryPaths[$library].$file;
  312.                     }
  313.                     else {
  314.                         $fileList[$this->clientJsLocation().$file$this->clientJsLocation().$file;
  315.                     }
  316.                 }
  317.             }
  318.         }
  319.  
  320.         // do needed class init if were running an init server
  321.         if(!is_array($this->options['stub'])) {
  322.             $this->options['stub'= array();
  323.         }
  324.         $classList $this->options['stub'];
  325.         if ($this->initMethods{
  326.             if (isset($this->options['stub'][0]&& $this->options['stub'][0=== 'all'{
  327.                     $this->_initAll();
  328.             else {
  329.                 foreach($this->options['stub'as $stub{
  330.                     $this->_init($stub);
  331.                 }
  332.             }
  333.         }
  334.         if (isset($this->options['stub'][0]&& $this->options['stub'][0=== 'all'{
  335.             $classList array_keys($this->ajax->_exportedInstances);
  336.         }
  337.  
  338.         // if were doing stub and client we have to wait for both ETags before we can compare with the client
  339.         $combinedOutput = false;
  340.         if ($classList != false && count($classList> 0 && count($fileList> 0{
  341.             $combinedOutput = true;
  342.         }
  343.  
  344.  
  345.         if ($classList != false && count($classList> 0{
  346.  
  347.             // were setup enough to make a stubETag if the input it wants is a class list
  348.             if ($this->cacheOptions['httpCacheStub'&& 
  349.                 $this->cacheOptions['StubCacheExpects'== 'classes'
  350.             {
  351.                 $stubETag $this->_callCacheRule('Stub',$classList);
  352.             }
  353.  
  354.             // if were not in combined output compare etags, if method returns true were done
  355.             if (!$combinedOutput && isset($stubETag)) {
  356.                 if ($this->_compareEtags($stubETag)) {
  357.                     ob_end_clean();
  358.                     return;
  359.                 }
  360.             }
  361.  
  362.             // output the stubs for all the classes in our list
  363.             foreach($classList as $class{
  364.                     echo $this->ajax->generateClassStub($class);
  365.             }
  366.  
  367.             // if were cacheing and the rule expects content make a tag and check it, if the check is true were done
  368.             if ($this->cacheOptions['httpCacheStub'&& 
  369.                 $this->cacheOptions['StubCacheExpects'== 'content'
  370.             {
  371.                 $stubETag $this->_callCacheRule('Stub',ob_get_contents());
  372.             }
  373.  
  374.             // if were not in combined output compare etags, if method returns true were done
  375.             if (!$combinedOutput && isset($stubETag)) {
  376.                 if ($this->_compareEtags($stubETag)) {
  377.                     ob_end_clean();
  378.                     return;
  379.                 }
  380.             }
  381.         }
  382.  
  383.         if (count($fileList> 0{
  384.             // if were caching and need a file list build our jsETag
  385.             if ($this->cacheOptions['httpCacheClient'&& 
  386.                 $this->cacheOptions['ClientCacheExpects'=== 'files'
  387.             {
  388.                 $jsETag $this->_callCacheRule('Client',$fileList);
  389.  
  390.             }
  391.  
  392.             // if were not in combined output compare etags, if method returns true were done
  393.             if (!$combinedOutput && isset($jsETag)) {
  394.                 if ($this->_compareEtags($jsETag)) {
  395.                     ob_end_clean();
  396.                     return;
  397.                 }
  398.             }
  399.  
  400.             // output the needed client js files
  401.             foreach($fileList as $file{
  402.                 $this->_readFile($file);
  403.             }
  404.  
  405.             // if were caching and need content build the etag
  406.             if ($this->cacheOptions['httpCacheClient'&& 
  407.                 $this->cacheOptions['ClientCacheExpects'=== 'content'
  408.             {
  409.                 $jsETag $this->_callCacheRule('Client',ob_get_contents());
  410.             }
  411.  
  412.             // if were not in combined output compare etags, if method returns true were done
  413.             if (!$combinedOutput && isset($jsETag)) {
  414.                 if ($this->_compareEtags($jsETag)) {
  415.                     ob_end_clean();
  416.                     return;
  417.                 }
  418.             }
  419.             // were in combined output, merge the 2 ETags and compare
  420.             else if (isset($jsETag&& isset($stubETag)) {
  421.                 if ($this->_compareEtags(md5($stubETag.$jsETag))) {
  422.                     ob_end_clean();
  423.                     return;
  424.                 }
  425.             }
  426.         }
  427.  
  428.  
  429.         // were outputting content, add our length header and send the output
  430.         $length ob_get_length();
  431.         $output ob_get_contents();
  432.         ob_end_clean();
  433.  
  434.         if ($this->ajax->packJavaScript{
  435.             $output $this->ajax->packJavaScript($output);
  436.             $length strlen($output);
  437.         }
  438.         if ($length > 0 && $this->ajax->_sendContentLength()) 
  439.             //$headers['Content-Length'] = $length;
  440.         }
  441.         $headers['Content-Type''text/javascript; charset=utf-8';
  442.         $this->ajax->_sendHeaders($headers);
  443.         echo($output);
  444.     }
  445.  
  446.     /**
  447.      * Run readfile on input with basic error checking
  448.      *
  449.      * @param   string  $file   file to read
  450.      * @access  private
  451.      * @todo    is addslashes enough encoding for js?
  452.      */
  453.     function _readFile($file
  454.     {
  455.         if (file_exists($file)) {
  456.             readfile($file);
  457.         else {
  458.             $file addslashes($file);
  459.             echo "alert('Unable to find javascript file: $file');";
  460.         }
  461.     }
  462.  
  463.     /**
  464.      * Get the location of the client js
  465.      * To override the default pear datadir location set $this->clientJsLocation
  466.      *
  467.      * @return  string 
  468.      */
  469.     function clientJsLocation(
  470.     {
  471.         if (!$this->clientJsLocation{
  472.             $path '@data-dir@'.DIRECTORY_SEPARATOR.'HTML_AJAX'.DIRECTORY_SEPARATOR.'js'.DIRECTORY_SEPARATOR;
  473.             if(strpos($path'@'.'data-dir@'=== 0)
  474.             {
  475.                 $path realpath(dirname(__FILE__).DIRECTORY_SEPARATOR.'..'.DIRECTORY_SEPARATOR.'js').DIRECTORY_SEPARATOR;
  476.             }
  477.             return $path;
  478.         else {
  479.             return $this->clientJsLocation;
  480.         }
  481.     }
  482.  
  483.     /**
  484.      * Set the location of the client js
  485.      *
  486.      * @access  public
  487.      * @param   string  $location   Location
  488.      * @return  void 
  489.      */
  490.     function setClientJsLocation($location
  491.     {
  492.         $this->clientJsLocation = $location;
  493.     }
  494.  
  495.     /**
  496.      * Set the path to a Javascript libraries
  497.      *
  498.      * @access  public
  499.      * @param   string  $library    Library name
  500.      * @param   string  $path       Path
  501.      * @return  void 
  502.      */
  503.     function setJavascriptLibraryPath($library$path
  504.     {
  505.         $this->javascriptLibraryPaths[$library$path;
  506.     }
  507.  
  508.     /**
  509.      * Set the path to more than one Javascript libraries at once
  510.      *
  511.      * @access  public
  512.      * @param   array   $paths  Paths
  513.      * @return  void 
  514.      */
  515.     function setJavascriptLibraryPaths($paths
  516.     {
  517.         if (is_array($paths)) {
  518.             $this->javascriptLibraryPaths = array_merge($this->javascriptLibraryPaths$paths);
  519.         }
  520.     }
  521.  
  522.     /**
  523.      * Load options from _GET
  524.      *
  525.      * @access private
  526.      */
  527.     function _loadOptions(
  528.     {
  529.         $this->options = array('client'=>array(),'stub'=>array());
  530.         if (isset($_GET['client'])) {
  531.             $clients explode(',',$this->ajax->_getVar('client'));
  532.             $client = array();
  533.             foreach($clients as $val{
  534.                 $cleanVal $this->_cleanIdentifier($val);
  535.                 if (!empty($cleanVal)) {
  536.                     $client[strtolower($cleanVal);
  537.                 }
  538.             }
  539.  
  540.             if (count($client> 0{
  541.                 $this->options['client'$client;
  542.             }
  543.         }
  544.         if (isset($_GET['stub'])) {
  545.             $stubs explode(',',$this->ajax->_getVar('stub'));
  546.             $stub = array();
  547.             foreach($stubs as $val{
  548.                 $cleanVal $this->_cleanIdentifier($val);
  549.                 if (!empty($cleanVal)) {
  550.                     $stub[strtolower($cleanVal);
  551.                 }
  552.             }
  553.  
  554.             if (count($stub> 0{
  555.                 $this->options['stub'$stub;
  556.             }
  557.         }
  558.     }
  559.  
  560.     /**
  561.      * Clean an identifier like a class name making it safe to use
  562.      *
  563.      * @param   string  $input 
  564.      * @return  string 
  565.      * @access  private
  566.      */
  567.     function _cleanIdentifier($input{
  568.             return trim(preg_replace('/[^A-Za-z_0-9]/','',$input));
  569.     }
  570.  
  571.     /**
  572.      * Run every init method on the class
  573.      *
  574.      * @access private
  575.      */
  576.     function _initAll(
  577.     {
  578.         if ($this->initMethods{
  579.             foreach($this->_initLookup as $class => $method{
  580.                 $this->_init($class);
  581.             }
  582.         }
  583.     }
  584.  
  585.     /**
  586.      * Init one class
  587.      *
  588.      * @param   string  $className 
  589.      * @access private
  590.      */
  591.     function _init($className
  592.     {
  593.         $className strtolower($className);
  594.         if ($this->initMethods{
  595.             if (isset($this->_initLookup[$className])) {
  596.                 $method =$this->_initLookup[$className];
  597.                 if (is_array($method)) {
  598.                     call_user_func($method);
  599.                 }
  600.                 else {
  601.                     $this->$method();
  602.                 }
  603.             else {
  604.                 trigger_error("Could find an init method for class: " $className);
  605.             }
  606.         }
  607.     }
  608.  
  609.     /**
  610.      * Generate a hash from a list of files
  611.      *
  612.      * @param   array   $files  file list
  613.      * @return  string  a hash that can be used as an etag
  614.      * @access  private
  615.      */
  616.     function _cacheRuleFile($files{
  617.         $signature "";
  618.         foreach($files as $file{
  619.             if (file_exists($file)) {
  620.                 $signature .= $file.filemtime($file);
  621.             }
  622.         }
  623.         return md5($signature);
  624.     }
  625.  
  626.     /**
  627.      * Generate a hash from the api of registered classes
  628.      *
  629.      * @param   array   $classes class list
  630.      * @return  string  a hash that can be used as an etag
  631.      * @access  private
  632.      */
  633.     function _cacheRuleApi($classes{
  634.         $signature "";
  635.         foreach($classes as $class{
  636.             if (isset($this->ajax->_exportedInstances[$class])) {
  637.                 $signature .= $class.implode(',',$this->ajax->_exportedInstances[$class]['exportedMethods']);
  638.             }
  639.         }
  640.         return md5($signature);
  641.     }
  642.  
  643.     /**
  644.      * Generate a hash from the raw content
  645.      *
  646.      * @param   array   $content 
  647.      * @return  string  a hash that can be used as an etag
  648.      * @access  private
  649.      */
  650.     function _cacheRuleContent($content{
  651.         return md5($content);
  652.     }
  653.  
  654.     /**
  655.      * Send cache control headers
  656.      * @access  private
  657.      */
  658.     function _sendCacheHeaders($etag,$notModified{
  659.         header('Cache-Control: must-revalidate');
  660.         header('ETag: '.$etag);
  661.         if ($notModified{
  662.             header('HTTP/1.0 304 Not Modified',false,304);
  663.         }
  664.     }
  665.  
  666.     /**
  667.      * Compare eTags
  668.      *
  669.      * @param   string  $serverETag server eTag
  670.      * @return  boolean 
  671.      * @access  private
  672.      */
  673.     function _compareEtags($serverETag{
  674.         if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
  675.             if (strcmp($this->ajax->_getServer('HTTP_IF_NONE_MATCH'),$serverETag== 0{
  676.                 $this->_sendCacheHeaders($serverETag,true);
  677.                 return true;
  678.             }
  679.         }
  680.         $this->_sendCacheHeaders($serverETag,false);
  681.         return false;
  682.     }
  683.  
  684.     /**
  685.      * Call a cache rule and return its retusn
  686.      *
  687.      * @param   string  $rule Stub|Client
  688.      * @param   mixed   $payload 
  689.      * @return  boolean 
  690.      * @access  private
  691.      * @todo    decide if error checking is needed
  692.      */
  693.     function _callCacheRule($rule,$payload{
  694.         $method '_cacheRule'.$this->cacheOptions[$rule.'CacheRule'];
  695.         return call_user_func(array(&$this,$method),$payload);
  696.     }
  697. }
  698. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  699. ?>

Documentation generated on Sat, 05 May 2007 18:00:22 -0400 by phpDocumentor 1.3.0. PEAR Logo Copyright © PHP Group 2004.