Source for file WsdlGenerator.php

Documentation is available at WsdlGenerator.php

  1. <?php
  2. // vim: foldmethod=marker
  3. /**
  4.  *  WsdlGenerator.php
  5.  *
  6.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  7.  *  @license    http://www.opensource.org/licenses/bsd-license.php The BSD License
  8.  *  @package    Ethna
  9.  *  @version    $Id: a90dca237e36ae5c2da24a1bec8e810421e956a7 $
  10.  */
  11.  
  12. // {{{ Ethna_SOAP_WsdlGenerator
  13. /**
  14.  *  指定されたコントローラに対応するWSDLを生成するクラス
  15.  *
  16.  *  @author     Masaki Fujimoto <fujimoto@php.net>
  17.  *  @access     public
  18.  *  @package    Ethna
  19.  */
  20. {
  21.     /**#@+
  22.      *  @access private
  23.      */
  24.  
  25.     /** @var    object  Ethna_Controller    controllerオブジェクト */
  26.     var $controller;
  27.  
  28.     /** @var    object  Ethna_Config        設定オブジェクト */
  29.     var $config;
  30.  
  31.     /** @var    object  Ethna_ActionError   アクションエラーオブジェクト */
  32.     var $action_error;
  33.  
  34.     /** @var    object  Ethna_ActionError   アクションエラーオブジェクト(省略形) */
  35.     var $ae;
  36.  
  37.     /** @var    string      WSDL */
  38.     var $wsdl;
  39.  
  40.     /** @var    string      ゲートウェイクラスコード */
  41.     var $gateway;
  42.  
  43.     /** @var    string      ゲートウェイクラス識別名 */
  44.     var $name;
  45.  
  46.     /** @var    string      ゲートウェイクラスネームスペース */
  47.     var $namespace;
  48.  
  49.     /**#@-*/
  50.  
  51.     /**
  52.      *  Ethna_SOAP_WsdlGeneratorクラスのコンストラクタ
  53.      */
  54.     public function __construct($gateway)
  55.     {
  56.         $this->controller Ethna_Controller::getInstance();
  57.         $this->config $this->controller->getConfig();
  58.         $this->action_error null;
  59.         $this->ae $this->action_error;
  60.         $this->wsdl "";
  61.         $this->name $this->controller->getAppId();
  62.         $this->namespace $this->_getNameSpace();
  63.         $this->gateway $gateway;
  64.     }
  65.  
  66.     /**
  67.      *  WSDLを生成する
  68.      *
  69.      *  @access public
  70.      *  @return string  WSDL
  71.      */
  72.     function generate()
  73.     {
  74.         $current_type $this->controller->getClientType();
  75.         $this->controller->setClientType(CLIENT_TYPE_SOAP);
  76.  
  77.         $this->wsdl .= $this->_getHeader();
  78.         $this->wsdl .= $this->_getTypes();
  79.         $this->wsdl .= $this->_getMessage();
  80.         $this->wsdl .= $this->_getPortType();
  81.         $this->wsdl .= $this->_getBinding();
  82.         $this->wsdl .= $this->_getService();
  83.         $this->wsdl .= $this->_getFooter();
  84.  
  85.         $this->controller->setClientType($current_type);
  86.  
  87.         return $this->wsdl;
  88.     }
  89.  
  90.     /**
  91.      *  WSDL(ヘッダ部分)を取得する
  92.      *
  93.      *  @access private
  94.      *  @return string  WSDL(ヘッダ部分)
  95.      */
  96.     function _getHeader()
  97.     {
  98.         $header =<<<EOD
  99. <?xml version="1.0" encoding="utf-8"?>
  100. <definitions xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
  101.     xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  102.     xmlns:s="http://www.w3.org/2001/XMLSchema"
  103.     xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
  104.     xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/"
  105.     xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
  106.     xmlns:tns="%s"
  107.     targetNamespace="%s"
  108.     name="%s"
  109.     xmlns="http://schemas.xmlsoap.org/wsdl/">\n\n
  110. EOD;
  111.         return sprintf($header$this->namespace$this->namespace$this->name);
  112.     }
  113.  
  114.     /**
  115.      *  WSDL(型定義部分)を取得する
  116.      *
  117.      *  @access private
  118.      *  @return string  WSDL(型定義部分)
  119.      */
  120.     function _getTypes()
  121.     {
  122.         $types sprintf(" <types>\n  <s:schema targetNamespace=\"%s\">\n"$this->namespace);
  123.  
  124.         // 基本型
  125.         $types .=<<<EOD
  126.    <s:complexType name="ArrayOfInt">
  127.     <s:complexContent mixed="false">
  128.      <s:restriction base="soapenc:Array">
  129.       <s:attribute d7p1:arrayType="s:int[]" ref="soapenc:arrayType" xmlns:d7p1="http://schemas.xmlsoap.org/wsdl/" />
  130.      </s:restriction>
  131.     </s:complexContent>
  132.    </s:complexType>
  133.    <s:complexType name="ArrayOfString">
  134.     <s:complexContent mixed="false">
  135.      <s:restriction base="soapenc:Array">
  136.       <s:attribute d7p1:arrayType="s:string[]" ref="soapenc:arrayType" xmlns:d7p1="http://schemas.xmlsoap.org/wsdl/" />
  137.      </s:restriction>
  138.     </s:complexContent>
  139.    </s:complexType>
  140.    <s:complexType name="Result">
  141.     <s:sequence>
  142.      <s:element name="errormessage" type="s:string" />
  143.      <s:element name="errorcode" type="s:int" />
  144.     </s:sequence>
  145.    </s:complexType>\n
  146. EOD;
  147.         
  148.         // アクション固有
  149.         foreach ($this->controller->soap_action as $k => $v{
  150.             $action_form_name $this->controller->getActionFormName($k);
  151.             $form new $action_form_name($this->controller);
  152.             if ($form->retval == null{
  153.                 continue;
  154.             }
  155.  
  156.             // デフォルトエントリを追加
  157.             Ethna_SOAP_Util::fixRetval($form->retval);
  158.  
  159.             // シリアライズ
  160.             $retval_name preg_replace('/_(.)/e'"strtoupper('\$1')"ucfirst($k)) "Result";
  161.             $types .= $this->_serializeTypes($form->retval$retval_name);
  162.         }
  163.  
  164.         return $types "  </s:schema>\n </types>\n\n";
  165.     }
  166.  
  167.     /**
  168.      *  WSDL(Message部分)を取得する
  169.      *
  170.      *  @access private
  171.      *  @return string  WSDL(Message部分)
  172.      *  @todo   respect access controlls
  173.      */
  174.     function _getMessage()
  175.     {
  176.         $n 1;
  177.         $message "";
  178.         foreach ($this->controller->soap_action as $k => $v{
  179.             $message .= $this->_serializeMessage($k$n);
  180.             $n++;
  181.         }
  182.  
  183.         return $message "\n";
  184.     }
  185.  
  186.     /**
  187.      *  WSDL(PortType部分)を取得する
  188.      *
  189.      *  @access private
  190.      *  @return string  WSDL(PortType部分)
  191.      */
  192.     function _getPortType()
  193.     {
  194.         $port_type sprintf(" <portType name=\"%sSoap\">\n"$this->name);
  195.  
  196.         $n 1;
  197.         foreach ($this->controller->soap_action as $k => $v{
  198.             $port_type .= $this->_serializePortType($k$n);
  199.             $n++;
  200.         }
  201.  
  202.         $port_type .= " </portType>\n\n";
  203.  
  204.         return $port_type;
  205.     }
  206.  
  207.     /**
  208.      *  WSDL(Binding部分)を取得する
  209.      *
  210.      *  @access private
  211.      *  @return string  WSDL(Binding部分)
  212.      */
  213.     function _getBinding()
  214.     {
  215.         $namespace "urn:" $this->name;
  216.         $binding " <binding name=\"" $this->name "Soap\" type=\"tns:" $this->name "Soap\">\n";
  217.         $binding .= "  <soap:binding style=\"rpc\" transport=\"http://schemas.xmlsoap.org/soap/http\" />\n";
  218.  
  219.         $n 1;
  220.         foreach ($this->controller->soap_action as $k => $v{
  221.             $binding .= "  <operation name=\"$k\">\n";
  222.             $binding .= "   <soap:operation soapAction=\"$k\" style=\"rpc\" />\n";
  223.             $binding .= "   <input name=\"${k}${n}SoapIn\">\n";
  224.             $binding .= "    <soap:body use=\"encoded\" namespace=\"$namespace\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n";
  225.             $binding .= "   </input>\n";
  226.             $binding .= "   <output name=\"${k}${n}SoapOut\">\n";
  227.             $binding .= "    <soap:body use=\"encoded\" namespace=\"$namespace\" encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" />\n";
  228.             $binding .= "   </output>\n";
  229.             $binding .= "  </operation>\n";
  230.             $n++;
  231.         }
  232.         $binding .= " </binding>\n";
  233.  
  234.         return $binding;
  235.     }
  236.  
  237.     /**
  238.      *  WSDL(Service部分)を取得する
  239.      *
  240.      *  @access private
  241.      *  @return string  WSDL(Service部分)
  242.      */
  243.     function _getService()
  244.     {
  245.         $name $this->name;
  246.         $gateway$this->gateway;
  247.         $service " <service name=\"$name\">\n";
  248.         $service .= "  <port name=\"${name}Soap\" binding=\"tns:${name}Soap\">\n";
  249.         $service .= "   <soap:address location=\"$gateway\" />\n";
  250.         $service .= "  </port>\n";
  251.         $service .= " </service>\n";
  252.  
  253.         return $service;
  254.     }
  255.  
  256.     /**
  257.      *  WSDL(フッタ部分)を取得する
  258.      *
  259.      *  @access private
  260.      *  @return string  WSDL(フッタ部分)
  261.      */
  262.     function _getFooter()
  263.     {
  264.         return "</definitions>\n";
  265.     }
  266.  
  267.     /**
  268.      *  ネームスペースを取得する
  269.      *
  270.      *  @access private
  271.      *  @return string  ネームスペース
  272.      */
  273.     function _getNameSpace()
  274.     {
  275.         return sprintf("%s/%s"$this->config->get('url')$this->name);
  276.     }
  277.  
  278.     /**
  279.      *  型のシリアライズ
  280.      *
  281.      *  @access private
  282.      *  @param  array   $def    型定義
  283.      *  @param  string  $name   変数名
  284.      *  @return string  シリアライズされた型定義
  285.      */
  286.     function _serializeTypes($def$name)
  287.     {
  288.         if (is_array($def== false{
  289.             // nothing to do
  290.             return;
  291.         }
  292.  
  293.         $types $this->__serializeTypes($def$name);
  294.  
  295.         foreach ($def as $k => $v{
  296.             if (is_array($def[$k]== false || Ethna_SOAP_Util::isArrayOfScalar($def[$k])) {
  297.                 continue;
  298.             }
  299.             $types .= $this->_serializeTypes($def[$k]$k);
  300.         }
  301.  
  302.         return $types;
  303.     }
  304.  
  305.     /**
  306.      *  型のシリアライズ(エレメント対応)
  307.      *
  308.      *  @access private
  309.      *  @param  array   $def    型定義
  310.      *  @param  string  $name   変数名
  311.      *  @return string  シリアライズされた型定義(各要素)
  312.      */
  313.     function __serializeTypes($def$name)
  314.     {
  315.         $keys array_keys($def);
  316.  
  317.         if (Ethna_SOAP_Util::isArrayOfObject($def)) {
  318.             $array_name sprintf("ArrayOf%s"$keys[0]);
  319.             $name $keys[0];
  320.             $types "   <s:complexType name=\"$array_name\">\n";
  321.             $types .= "    <s:complexContent mixed=\"false\">\n";
  322.             $types .= "     <s:restriction base=\"soapenc:Array\">\n";
  323.             $types .= "      <s:attribute d7p1:arrayType=\"tns:$name"[]" "\" " .
  324.                 "ref=\"soapenc:arrayType\" xmlns:d7p1=\"http://schemas.xmlsoap.org/wsdl/\" />\n";
  325.             $types .= "     </s:restriction>\n";
  326.             $types .= "    </s:complexContent>\n";
  327.             $types .= "   </s:complexType>\n";
  328.             return $types;
  329.         }
  330.  
  331.         $types "   <s:complexType name=\"$name\">\n";
  332.         $types .= "    <s:sequence>\n";
  333.         foreach ($keys as $key{
  334.             if (is_array($def[$key])) {
  335.                 $inner_keys array_keys($def[$key]);
  336.                 if (is_array($def[$key][$inner_keys[0]])) {
  337.                     $inner_name sprintf("ArrayOf%s"$inner_keys[0]);
  338.                     $types .= "     <s:element name=\"$key\" type=\"tns:$inner_name\" />\n";
  339.                 else {
  340.                     $type_name "tns:" Ethna_SOAP_Util::getArrayTypeName($def[$key][$inner_keys[0]]);
  341.                     $types .= "     <s:element name=\"$key\" type=\"$type_name\" />\n";
  342.                 }
  343.             else {
  344.                 $type_name Ethna_SOAP_Util::getScalarTypeName($def[$key]);
  345.                 $types .= "     <s:element name=\"$key\" type=\"s:$type_name\" />\n";
  346.             }
  347.         }
  348.         $types .= "    </s:sequence>\n";
  349.         $types .= "   </s:complexType>\n";
  350.  
  351.         return $types;
  352.     }
  353.  
  354.     /**
  355.      *  Messageのシリアライズ
  356.      *
  357.      *  @access private
  358.      *  @param  string  $name   message名
  359.      *  @param  int     $serno  message連番
  360.      *  @return string  シリアライズされたmessage
  361.      */
  362.     function _serializeMessage($name$serno)
  363.     {
  364.         $action_form_name $this->controller->getActionFormName($name);
  365.         $form new $action_form_name($this->controller);
  366.  
  367.         /* SoapIn */
  368.         $message " <message name=\"${name}${serno}SoapIn\">\n";
  369.         $keys array();
  370.         if (is_array($form->form)) {
  371.             $keys array_keys($form->form);
  372.         }
  373.         foreach ($keys as $key{
  374.             $type_id $form->form[$key]['type'];
  375.             if (is_array($type_id)) {
  376.                 $type_keys array_keys($type_id);
  377.                 $type "tns:" Ethna_SOAP_Util::getArrayTypeName($type_id[$type_keys[0]]);
  378.             else {
  379.                 $type "s:" Ethna_SOAP_Util::getScalarTypeName($type_id);
  380.             }
  381.             $message .= "  <part name=\"$key\" type=\"$type\" />\n";
  382.         }
  383.         $message .= " </message>\n";
  384.  
  385.         /* SoapOut */
  386.         $message .= " <message name=\"${name}${serno}SoapOut\">\n";
  387.         if ($form->retval == null{
  388.             $type "tns:Result";
  389.         else {
  390.             $type "tns:${name}Result";
  391.         }
  392.         $message .= "  <part name=\"result\" type=\"$type\" />\n";
  393.         $message .= " </message>\n";
  394.  
  395.         return $message;
  396.     }
  397.  
  398.     /**
  399.      *  PortTypeのシリアライズ
  400.      *
  401.      *  @access private
  402.      *  @param  string  $name   porttype名
  403.      *  @param  int     $serno  porttype連番
  404.      *  @return string  シリアライズされたporttype
  405.      */
  406.     function _serializePortType($name$serno)
  407.     {
  408.         $action_form_name $this->controller->getActionFormName($name);
  409.         $form new $action_form_name($this->controller);
  410.  
  411.         $args null;
  412.         if (is_array($form->form)) {
  413.             $args implode(' 'array_keys($form->form));
  414.         }
  415.  
  416.         $port_type "  <operation name=\"$name\" parameterOrder=\"$args\">\n";
  417.         $port_type .= "   <input name=\"${name}${serno}SoapIn\" message=\"tns:${name}${serno}SoapIn\" />\n";
  418.         $port_type .= "   <output name=\"${name}${serno}SoapOut\" message=\"tns:${name}${serno}SoapOut\" />\n";
  419.         $port_type .= "  </operation>\n";
  420.  
  421.         return $port_type;
  422.     }
  423. }
  424. // }}}

Documentation generated on Fri, 11 Nov 2011 03:59:32 +0900 by phpDocumentor 1.4.3