OSDN Git Service

- XMLRPCゲートウェイサポート追加(experimental)
[ethna/ethna.git] / class / Ethna_Controller.php
index af8cb71..69b9ed5 100644 (file)
@@ -13,6 +13,8 @@
 /**
  *  ¥³¥ó¥È¥í¡¼¥é¥¯¥é¥¹
  *
+ *  @todo       gateway¤Çswitch¤·¤Æ¤ë¤È¤³¤í¤¬¥À¥µ¥À¥µ
+ *
  *  @author     Masaki Fujimoto <fujimoto@php.net>
  *  @access     public
  *  @package    Ethna
@@ -38,6 +40,7 @@ class Ethna_Controller
     /** @var    array       ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê */
     var $directory = array(
         'action'        => 'app/action',
+        'action_xmlrpc' => 'app/action_xmlrpc',
         'app'           => 'app',
         'etc'           => 'etc',
         'filter'        => 'app/filter',
@@ -92,12 +95,18 @@ class Ethna_Controller
     /** @var    string  ¸½ºß¼Â¹ÔÃæ¤Î¥¢¥¯¥·¥ç¥ó̾ */
     var $action_name;
 
+    /** @var    string  ¸½ºß¼Â¹ÔÃæ¤ÎXMLRPC¥á¥½¥Ã¥É̾ */
+    var $xmlrpc_method_name;
+
     /** @var    array   forwardÄêµÁ */
     var $forward = array();
 
     /** @var    array   actionÄêµÁ */
     var $action = array();
 
+    /** @var    array   action(XMLRPC)ÄêµÁ */
+    var $action_xmlrpc = array();
+
     /** @var    array   ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥Þ¥Í¡¼¥¸¥ãÄêµÁ */
     var $manager = array();
 
@@ -335,9 +344,20 @@ class Ethna_Controller
      *  @access public
      *  @return string  ¥¢¥¯¥·¥ç¥ó¥Ç¥£¥ì¥¯¥È¥ê
      */
-    function getActiondir()
+    function getActiondir($gateway = null)
     {
-        return (empty($this->directory['action']) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory['action'] . "/"));
+        $key = 'action';
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+        case GATEWAY_CLI:
+            $key = 'action';
+            break;
+        case GATEWAY_XMLRPC:
+            $key = 'action_xmlrpc';
+        }
+
+        return (empty($this->directory[$key]) ? ($this->base . (empty($this->base) ? '' : '/')) : ($this->directory[$key] . "/"));
     }
 
     /**
@@ -509,6 +529,17 @@ class Ethna_Controller
     }
 
     /**
+     *  ¼Â¹ÔÃæ¤ÎXMLRPC¥á¥½¥Ã¥É̾¤òÊÖ¤¹
+     *
+     *  @access public
+     *  @return string  ¼Â¹ÔÃæ¤ÎXMLRPC¥á¥½¥Ã¥É̾
+     */
+    function getXmlrpcMethodName()
+    {
+        return $this->xmlrpc_method_name;
+    }
+
+    /**
      *  »ÈÍѸÀ¸ì¤ò¼èÆÀ¤¹¤ë
      *
      *  @access public
@@ -576,16 +607,19 @@ class Ethna_Controller
      *  XMLRPC¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤Î¥¨¥ó¥È¥ê¥Ý¥¤¥ó¥È
      *
      *  @access public
-     *  @param  string  $class_name     ¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¥³¥ó¥È¥í¡¼¥é¤Î¥¯¥é¥¹Ì¾
-     *  @param  mixed   $action_name    »ØÄê¤Î¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
-     *  @param  mixed   $fallback_action_name   ¥¢¥¯¥·¥ç¥ó¤¬·èÄê¤Ç¤­¤Ê¤«¤Ã¤¿¾ì¹ç¤Ë¼Â¹Ô¤µ¤ì¤ë¥¢¥¯¥·¥ç¥ó̾(¾Êά²Ä)
      *  @static
      */
-    function main_XMLRPC($class_name, $action_name = "", $fallback_action_name = "")
+    function main_XMLRPC($class_name)
     {
+        if (extension_loaded('xmlrpc') == false) {
+            die("xmlrpc extension is required to enable this gateway");
+        } else if (ini_get('always_populate_raw_post_data') == false) {
+            die("always_populate_raw_post_data ini variable should be true to enable this gateway");
+        }
+
         $c =& new $class_name;
         $c->setGateway(GATEWAY_XMLRPC);
-        $c->trigger($action_name, $fallback_action_name);
+        $c->trigger("", "", false);
     }
 
     /**
@@ -700,6 +734,7 @@ class Ethna_Controller
         // ¥ª¥Ö¥¸¥§¥¯¥ÈÀ¸À®
         $form_name = $this->getActionFormName($action_name);
         $this->action_form =& new $form_name($this);
+        $this->action_form->setFormVars();
 
         // ¥Ð¥Ã¥¯¥¨¥ó¥É½èÍý¼Â¹Ô
         $backend =& $this->getBackend();
@@ -756,7 +791,56 @@ class Ethna_Controller
      */
     function _trigger_XMLRPC($action_name = "")
     {
-        die("sorry, xmlrpc gateway is not supported yet");
+        $xmlrpc_gateway_method_name = "_Ethna_XmlrpcGateway";
+
+        $xmlrpc_server = xmlrpc_server_create();
+        $method = null;
+        $param = xmlrpc_decode_request($GLOBALS['HTTP_RAW_POST_DATA'], $method);
+        $this->xmlrpc_method_name = $method;
+
+        $request = xmlrpc_encode_request($xmlrpc_gateway_method_name, $param, array("output_type" => "xml", "verbosity" => "pretty", "escaping" => array('markup'), "version" => "xmlrpc", "encoding" => "utf-8")); 
+        xmlrpc_server_register_method($xmlrpc_server, $xmlrpc_gateway_method_name, $xmlrpc_gateway_method_name);
+        $r = xmlrpc_server_call_method($xmlrpc_server, $request, null, array("output_type" => "xml", "verbosity" => "pretty", "escaping" => array('markup'), "version" => "xmlrpc", "encoding" => "utf-8"));
+
+        header('Content-Length: ' . strlen($r));
+        header('Content-Type: text/xml; charset=UTF-8');
+        print $r;
+    }
+
+    /**
+     *  _trigger_XMLRPC¤Î¥³¡¼¥ë¥Ð¥Ã¥¯¥á¥½¥Ã¥É
+     *
+     *  @access public
+     */
+    function trigger_XMLRPC($method, $param)
+    {
+        // ¥¢¥¯¥·¥ç¥óÄêµÁ¤Î¼èÆÀ
+        $action_obj =& $this->_getAction($method);
+        if (is_null($action_obj)) {
+            return Ethna::raiseError("undefined xmlrpc method [%s]", E_APP_UNDEFINED_ACTION, $method);
+        }
+
+        // ¥ª¥Ö¥¸¥§¥¯¥ÈÀ¸À®
+        $form_name = $this->getActionFormName($method);
+        $this->action_form =& new $form_name($this);
+        $def = $this->action_form->getDef();
+        $n = 0;
+        foreach ($def as $key => $value) {
+            if (isset($param[$n]) == false) {
+                $this->action_form->set($key, null);
+            } else {
+                $this->action_form->set($key, $param[$n]);
+            }
+            $n++;
+        }
+
+        // ¥Ð¥Ã¥¯¥¨¥ó¥É½èÍý¼Â¹Ô
+        $backend =& $this->getBackend();
+        $session =& $this->getSession();
+        $session->restore();
+        $r = $backend->perform($method);
+
+        return $r;
     }
 
     /**
@@ -921,9 +1005,19 @@ class Ethna_Controller
      *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
      *  @return array   ¥¢¥¯¥·¥ç¥óÄêµÁ
      */
-    function &_getAction($action_name)
+    function &_getAction($action_name, $gateway = null)
     {
-        $action =& $this->action;
+        $action = array();
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+        case GATEWAY_CLI:
+            $action =& $this->action;
+            break;
+        case GATEWAY_XMLRPC:
+            $action =& $this->action_xmlrpc;
+            break;
+        }
 
         $action_obj = array();
         if (isset($action[$action_name])) {
@@ -936,7 +1030,7 @@ class Ethna_Controller
         }
 
         // ¥¢¥¯¥·¥ç¥ó¥¹¥¯¥ê¥×¥È¤Î¥¤¥ó¥¯¥ë¡¼¥É
-        $this->_includeActionScript($action_obj, $action_name);
+        $this->_includeActionScript($action_obj, $action_name, $gateway);
 
         // ¾ÊάÃͤÎÊäÀµ
         if (isset($action_obj['class_name']) == false) {
@@ -1048,10 +1142,12 @@ class Ethna_Controller
      *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
      *  @return string  ¥¢¥¯¥·¥ç¥ó¥Õ¥©¡¼¥à̾
      */
-    function getDefaultFormClass($action_name)
+    function getDefaultFormClass($action_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
-        $r = sprintf("%s_Form_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sForm_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
 
         return $r;
@@ -1123,10 +1219,12 @@ class Ethna_Controller
      *  @param  string  $action_name    ¥¢¥¯¥·¥ç¥ó̾
      *  @return string  ¥¢¥¯¥·¥ç¥ó¥¯¥é¥¹Ì¾
      */
-    function getDefaultActionClass($action_name)
+    function getDefaultActionClass($action_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
-        $r = sprintf("%s_Action_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sAction_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default action class [%s]", $r);
 
         return $r;
@@ -1229,10 +1327,12 @@ class Ethna_Controller
      *  @param  string  $forward_name   forward̾
      *  @return string  view class¥¯¥é¥¹Ì¾
      */
-    function getDefaultViewClass($forward_name)
+    function getDefaultViewClass($forward_name, $gateway = null)
     {
+        $gateway_prefix = $this->_getGatewayPrefix($gateway);
+
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
-        $r = sprintf("%s_View_%s", $this->getAppId(), $postfix);
+        $r = sprintf("%s_%sView_%s", $this->getAppId(), $gateway_prefix ? $gateway_prefix . "_" : "", $postfix);
         $this->logger->log(LOG_DEBUG, "default view class [%s]", $r);
 
         return $r;
@@ -1446,6 +1546,31 @@ class Ethna_Controller
     }
 
     /**
+     *  ¥²¡¼¥È¥¦¥§¥¤¤ËÂбþ¤·¤¿¥¯¥é¥¹Ì¾¤Î¥×¥ì¥Õ¥£¥¯¥¹¤ò¼èÆÀ¤¹¤ë
+     *
+     *  @access public
+     *  @param  string  $gateway    ¥²¡¼¥È¥¦¥§¥¤
+     *  @return string  ¥²¡¼¥È¥¦¥§¥¤¥¯¥é¥¹¥×¥ì¥Õ¥£¥¯¥¹
+     */
+    function _getGatewayPrefix($gateway = null)
+    {
+        $gateway = is_null($gateway) ? $this->getGateway() : $gateway;
+        switch ($gateway) {
+        case GATEWAY_WWW:
+        case GATEWAY_CLI:
+            $prefix = '';
+            break;
+        case GATEWAY_XMLRPC:
+            $prefix = 'Xmlrpc';
+            break;
+        default:
+            $prefix = '';
+        }
+
+        return $prefix;
+    }
+
+    /**
      *  ¥Þ¥Í¡¼¥¸¥ã¥¯¥é¥¹Ì¾¤ò¼èÆÀ¤¹¤ë
      *
      *  @access public
@@ -1736,4 +1861,21 @@ class Ethna_Controller
     }
 }
 // }}}
+
+/**
+ *  XMLRPC¥²¡¼¥È¥¦¥§¥¤¤Î¥¹¥¿¥Ö¥¯¥é¥¹
+ *
+ *  @access     public
+ */
+function _Ethna_XmlrpcGateway($method_stub, $param)
+{
+    $ctl =& Ethna_Controller::getInstance();
+    $method = $ctl->getXmlrpcMethodName();
+    $r = $ctl->trigger_XMLRPC($method, $param);
+    if (Ethna::isError($r)) {
+        // ToDo: notify fault
+        return -1;
+    }
+    return $r;
+}
 ?>