Advertisement
Guest User

unzend.com_278

a guest
Jun 17th, 2015
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 24.52 KB | None | 0 0
  1. <?php
  2. // Ioncube Decoder Unzend.Com Email unzend@gmail.com
  3. // http://www.unzend.com
  4. /**
  5.  * CWsdlGenerator class file.
  6.  *
  7.  * @author Qiang Xue <qiang.xue@gmail.com>
  8.  * @link http://www.yiiframework.com/
  9.  * @copyright 2008-2013 Yii Software LLC
  10.  * @license http://www.yiiframework.com/license/
  11.  */
  12.  
  13. /**
  14.  * CWsdlGenerator generates the WSDL for a given service class.
  15.  *
  16.  * The WSDL generation is based on the doc comments found in the service class file.
  17.  * In particular, it recognizes the '@soap' tag in the comment and extracts
  18.  * API method and type definitions.
  19.  *
  20.  * In a service class, a remote invokable method must be a public method with a doc
  21.  * comment block containing the '@soap' tag. In the doc comment, the type and name
  22.  * of every input parameter and the type of the return value should be declared using
  23.  * the standard phpdoc format.
  24.  *
  25.  * CWsdlGenerator recognizes the following primitive types (case-sensitive) in
  26.  * the parameter and return type declarations:
  27.  * <ul>
  28.  * <li>str/string: maps to xsd:string;</li>
  29.  * <li>int/integer: maps to xsd:int;</li>
  30.  * <li>float/double: maps to xsd:float;</li>
  31.  * <li>bool/boolean: maps to xsd:boolean;</li>
  32.  * <li>date: maps to xsd:date;</li>
  33.  * <li>time: maps to xsd:time;</li>
  34.  * <li>datetime: maps to xsd:dateTime;</li>
  35.  * <li>array: maps to xsd:string;</li>
  36.  * <li>object: maps to xsd:struct;</li>
  37.  * <li>mixed: maps to xsd:anyType.</li>
  38.  * </ul>
  39.  *
  40.  * If a type is not a primitive type, it is considered as a class type, and
  41.  * CWsdlGenerator will look for its property declarations. Only public properties
  42.  * are considered, and they each must be associated with a doc comment block containg
  43.  * the '@soap' tag. The doc comment block should declare the type of the property.
  44.  *
  45.  * CWsdlGenerator recognizes the array type with the following format:
  46.  * <pre>
  47.  * typeName[]: maps to tns:typeNameArray
  48.  * </pre>
  49.  *
  50.  * The following is an example declaring a remote invokable method:
  51.  * <pre>
  52.  * / **
  53.  *   * A foo method.
  54.  *   * @param string name of something
  55.  *   * @param string value of something
  56.  *   * @return string[] some array
  57.  *   * @soap
  58.  *   * /
  59.  * public function foo($name,$value) {...}
  60.  * </pre>
  61.  *
  62.  * And the following is an example declaring a class with remote accessible properties:
  63.  * <pre>
  64.  * class Foo {
  65.  *     / **
  66.  *       * @var string name of foo {nillable=1, minOccurs=0, maxOccurs=2}
  67.  *       * @soap
  68.  *       * /
  69.  *     public $name;
  70.  *     / **
  71.  *       * @var Member[] members of foo
  72.  *       * @soap
  73.  *       * /
  74.  *     public $members;
  75.  * }
  76.  * </pre>
  77.  * In the above, the 'members' property is an array of 'Member' objects. Since 'Member' is not
  78.  * a primitive type, CWsdlGenerator will look further to find the definition of 'Member'.
  79.  *
  80.  * Optionally, extra attributes (nillable, minOccurs, maxOccurs) can be defined for each
  81.  * property by enclosing definitions into curly brackets and separated by comma like so:
  82.  *
  83.  * {[attribute1 = value1][, attribute2 = value2], ...}
  84.  *
  85.  * where the attribute can be one of following:
  86.  * <ul>
  87.  * <li>nillable = [0|1|true|false]</li>
  88.  * <li>minOccurs = n; where n>=0</li>
  89.  * <li>maxOccurs = n; where [n>=0|unbounded]</li>
  90.  * </ul>
  91.  *
  92.  * Additionally, each complex data type can have assigned a soap indicator flag declaring special usage for such a data type.
  93.  * A soap indicator must be declared in the doc comment block with the '@soap-indicator' tag.
  94.  * Following soap indicators are currently supported:
  95.  * <ul>
  96.  * <li>all - (default) allows any sorting order of child nodes</li>
  97.  * <li>sequence - all child nodes in WSDL XML file will be expected in predefined order</li>
  98.  * <li>choice - supplied can be either of the child elements</li>
  99.  * </ul>
  100.  * The Group indicators can be also injected via custom soap definitions as XML node into WSDL structure.
  101.  *
  102.  * In the following example, class Foo will create a XML node <xsd:Foo><xsd:sequence> ... </xsd:sequence></xsd:Foo> with children attributes expected in pre-defined order.
  103.  * <pre>
  104.  * / *
  105.  *   * @soap-indicator sequence
  106.  *   * /
  107.  * class Foo {
  108.  *     ...
  109.  * }
  110.  * </pre>
  111.  * For more on soap indicators, see See {@link http://www.w3schools.com/schema/schema_complex_indicators.asp}.
  112.  *
  113.  * Since the variability of WSDL definitions is virtually unlimited, a special doc comment tag '@soap-wsdl' can be used in order to inject any custom XML string into generated WSDL file.
  114.  * If such a block of the code is found in class's comment block, then it will be used instead of parsing and generating standard attributes within the class.
  115.  * This gives virtually unlimited flexibility in defining data structures of any complexity.
  116.  * Following is an example of defining custom piece of WSDL XML node:
  117.  * <pre>
  118.  * / *
  119.  *   * @soap-wsdl <xsd:sequence>
  120.  *   * @soap-wsdl   <xsd:element minOccurs="1" maxOccurs="1" nillable="false" name="name" type="xsd:string"/>
  121.  *   * @soap-wsdl   <xsd:choice minOccurs="1" maxOccurs="1" nillable="false">
  122.  *   * @soap-wsdl       <xsd:element minOccurs="1" maxOccurs="1" nillable="false" name="age" type="xsd:integer"/>
  123.  *   * @soap-wsdl       <xsd:element minOccurs="1" maxOccurs="1" nillable="false" name="date_of_birth" type="xsd:date"/>
  124.  *   * @soap-wsdl   </xsd:choice>
  125.  *   * @soap-wsdl </xsd:sequence>
  126.  *   * /
  127.  * class User {
  128.  *     / **
  129.  *       * @var string User name {minOccurs=1, maxOccurs=1}
  130.  *       * @soap
  131.  *       * /
  132.  *     public $name;
  133.  *     / **
  134.  *       * @var integer User age {nillable=0, minOccurs=1, maxOccurs=1}
  135.  *       * @example 35
  136.  *       * @soap
  137.  *       * /
  138.  *     public $age;
  139.  *     / **
  140.  *       * @var date User's birthday {nillable=0, minOccurs=1, maxOccurs=1}
  141.  *       * @example 1980-05-27
  142.  *       * @soap
  143.  *       * /
  144.  *     public $date_of_birth;
  145.  * }
  146.  * </pre>
  147.  * In the example above, WSDL generator would inject under XML node <xsd:User> the code block defined by @soap-wsdl lines.
  148.  *
  149.  * By inserting into SOAP URL link the parameter "?makedoc", WSDL generator will output human-friendly overview of all complex data types rather than XML WSDL file.
  150.  * Each complex type is described in a separate HTML table and recognizes also the '@example' PHPDoc tag. See {@link buildHtmlDocs()}.
  151.  *
  152.  * @author Qiang Xue <qiang.xue@gmail.com>
  153.  * @package system.web.services
  154.  * @since 1.0
  155.  */
  156. class CWsdlGenerator extends CComponent
  157. {
  158.     /**
  159.      * @var string the namespace to be used in the generated WSDL.
  160.      * If not set, it defaults to the name of the class that WSDL is generated upon.
  161.      */
  162.     public $namespace;
  163.     /**
  164.      * @var string the name of the generated WSDL.
  165.      * If not set, it defaults to "urn:{$className}wsdl".
  166.      */
  167.     public $serviceName;
  168.  
  169.     protected static $typeMap=array(
  170.         'string'=>'xsd:string',
  171.         'str'=>'xsd:string',
  172.         'int'=>'xsd:int',
  173.         'integer'=>'xsd:integer',
  174.         'float'=>'xsd:float',
  175.         'double'=>'xsd:float',
  176.         'bool'=>'xsd:boolean',
  177.         'boolean'=>'xsd:boolean',
  178.         'date'=>'xsd:date',
  179.         'time'=>'xsd:time',
  180.         'datetime'=>'xsd:dateTime',
  181.         'array'=>'soap-enc:Array',
  182.         'object'=>'xsd:struct',
  183.         'mixed'=>'xsd:anyType',
  184.     );
  185.  
  186.     /**
  187.     * @var array List of recognized SOAP operations that will become remotely available.
  188.     * All methods with declared @soap parameter will be included here in the format operation1 => description1, operation2 => description2, ..
  189.     */
  190.     protected $operations;
  191.  
  192.     /**
  193.     * @var array List of complex types used by operations.
  194.     * If an SOAP operation defines complex input or output type, all objects are included here containing all sub-parameters.
  195.     * For instance, if an SOAP operation "createUser" requires complex input object "User", then the object "User" will be included here with declared subparameters such as "firstname", "lastname", etc..
  196.     */
  197.     protected $types;
  198.  
  199.     /**
  200.     * @var array Map of request and response types for all operations.
  201.     */
  202.     protected $messages;
  203.  
  204.     /**
  205.      * Generates the WSDL for the given class.
  206.      * @param string $className class name
  207.      * @param string $serviceUrl Web service URL
  208.      * @param string $encoding encoding of the WSDL. Defaults to 'UTF-8'.
  209.      * @return string the generated WSDL
  210.      */
  211.     public function generateWsdl($className, $serviceUrl, $encoding='UTF-8')
  212.     {
  213.         $this->operations=array();
  214.         $this->types=array();
  215.         $this->messages=array();
  216.         if($this->serviceName===null)
  217.             $this->serviceName=$className;
  218.         if($this->namespace===null)
  219.             $this->namespace='urn:'.str_replace('\\','/',$className).'wsdl';
  220.  
  221.         $reflection=new ReflectionClass($className);
  222.         foreach($reflection->getMethods() as $method)
  223.         {
  224.             if($method->isPublic())
  225.                 $this->processMethod($method);
  226.         }
  227.  
  228.         $wsdl=$this->buildDOM($serviceUrl,$encoding)->saveXML();
  229.  
  230.         if(isset($_GET['makedoc']))
  231.             $this->buildHtmlDocs();
  232.  
  233.         return $wsdl;
  234.     }
  235.  
  236.     /**
  237.      * @param ReflectionMethod $method method
  238.      */
  239.     protected function processMethod($method)
  240.     {
  241.         $comment=$method->getDocComment();
  242.         if(strpos($comment,'@soap')===false)
  243.             return;
  244.         $comment=strtr($comment,array("\r\n"=>"\n","\r"=>"\n")); // make line endings consistent: win -> unix, mac -> unix
  245.  
  246.         $methodName=$method->getName();
  247.         $comment=preg_replace('/^\s*\**(\s*?$|\s*)/m','',$comment);
  248.         $params=$method->getParameters();
  249.         $message=array();
  250.         $n=preg_match_all('/^@param\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches);
  251.         if($n>count($params))
  252.             $n=count($params);
  253.         for($i=0;$i<$n;++$i)
  254.             $message[$params[$i]->getName()]=array($this->processType($matches[1][$i]), trim($matches[3][$i])); // name => type, doc
  255.  
  256.         $this->messages[$methodName.'Request']=$message;
  257.  
  258.         if(preg_match('/^@return\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/im',$comment,$matches))
  259.             $return=array($this->processType($matches[1]),trim($matches[2])); // type, doc
  260.         else
  261.             $return=null;
  262.         $this->messages[$methodName.'Response']=array('return'=>$return);
  263.  
  264.         if(preg_match('/^\/\*+\s*([^@]*?)\n@/s',$comment,$matches))
  265.             $doc=trim($matches[1]);
  266.         else
  267.             $doc='';
  268.         $this->operations[$methodName]=$doc;
  269.     }
  270.  
  271.     /**
  272.      * @param string $type PHP variable type
  273.      */
  274.     protected function processType($type)
  275.     {
  276.         if(isset(self::$typeMap[$type]))
  277.             return self::$typeMap[$type];
  278.         elseif(isset($this->types[$type]))
  279.             return is_array($this->types[$type]) ? 'tns:'.$type : $this->types[$type];
  280.         elseif(($pos=strpos($type,'[]'))!==false)
  281.         {   // array of types
  282.             $type=substr($type,0,$pos);
  283.             $this->types[$type.'[]']='tns:'.$type.'Array';
  284.             $this->processType($type);
  285.             return $this->types[$type.'[]'];
  286.         }
  287.         else
  288.         {   // process class / complex type
  289.             $type=Yii::import($type,true);
  290.             $class=new ReflectionClass($type);
  291.  
  292.             $comment=$class->getDocComment();
  293.             $comment=strtr($comment,array("\r\n"=>"\n","\r"=>"\n")); // make line endings consistent: win -> unix, mac -> unix
  294.             $comment=preg_replace('/^\s*\**(\s*?$|\s*)/m','',$comment);
  295.  
  296.             // extract soap indicator flag, if defined, e.g. @soap-indicator sequence
  297.             // see http://www.w3schools.com/schema/schema_complex_indicators.asp
  298.             if(preg_match('/^@soap-indicator\s+(\w+)\s*?(.*)$/im', $comment, $matches))
  299.             {
  300.                 $indicator=$matches[1];
  301.                 $attributes=$this->getWsdlElementAttributes($matches[2]);
  302.             }else{
  303.                 $indicator='all';
  304.                 $attributes=$this->getWsdlElementAttributes('');
  305.             }
  306.  
  307.             $custom_wsdl=false;
  308.             if(preg_match_all('/^@soap-wsdl\s+(\S.*)$/im',$comment,$matches)>0)
  309.                 $custom_wsdl=implode("\n", $matches[1]);
  310.  
  311.             $this->types[$type]=array(
  312.                 'indicator'=>$indicator,
  313.                 'nillable'=>$attributes['nillable'],
  314.                 'minOccurs'=>$attributes['minOccurs'],
  315.                 'maxOccurs'=>$attributes['maxOccurs'],
  316.                 'custom_wsdl'=>$custom_wsdl,
  317.                 'properties'=>array()
  318.             );
  319.  
  320.             foreach($class->getProperties() as $property)
  321.             {
  322.                 $comment=$property->getDocComment();
  323.                 if($property->isPublic() && strpos($comment,'@soap')!==false)
  324.                 {
  325.                     if(preg_match('/@var\s+([\w\.]+(\[\s*\])?)\s*?(.*)$/mi',$comment,$matches))
  326.                     {
  327.                         $attributes=$this->getWsdlElementAttributes($matches[3]);
  328.  
  329.                         if(preg_match('/{(.+)}/',$comment,$attr))
  330.                             $matches[3]=str_replace($attr[0],'',$matches[3]);
  331.  
  332.                         // extract PHPDoc @example
  333.                         $example='';
  334.                         if(preg_match("/@example[:]?(.+)/mi",$comment,$match))
  335.                             $example=trim($match[1]);
  336.  
  337.                         $this->types[$type]['properties'][$property->getName()]=array(
  338.                             $this->processType($matches[1]),
  339.                             trim($matches[3]),
  340.                             $attributes['nillable'],
  341.                             $attributes['minOccurs'],
  342.                             $attributes['maxOccurs'],
  343.                             $example
  344.                         ); // name => type, doc, nillable, minOccurs, maxOccurs, example
  345.                     }
  346.                 }
  347.             }
  348.             return 'tns:'.$type;
  349.         }
  350.     }
  351.  
  352.     /**
  353.     * Parse attributes nillable, minOccurs, maxOccurs
  354.     * @param string $comment Extracted PHPDoc comment
  355.     */
  356.     protected function getWsdlElementAttributes($comment) {
  357.         $nillable=$minOccurs=$maxOccurs=null;
  358.         if(preg_match('/{(.+)}/',$comment,$attr))
  359.         {
  360.             if(preg_match_all('/((\w+)\s*=\s*(\w+))/mi',$attr[1],$attr))
  361.             {
  362.                 foreach($attr[2] as $id=>$prop)
  363.                 {
  364.                     $prop=strtolower($prop);
  365.                     $val=strtolower($attr[3][$id]);
  366.                     if($prop=='nillable'){
  367.                         if($val=='false' || $val=='true')
  368.                             $nillable=$val;
  369.                         else
  370.                             $nillable=$val ? 'true' : 'false';
  371.                     }elseif($prop=='minoccurs')
  372.                         $minOccurs=intval($val);
  373.                     elseif($prop=='maxoccurs')
  374.                         $maxOccurs=($val=='unbounded') ? 'unbounded' : intval($val);
  375.                 }
  376.             }
  377.         }
  378.         return array(
  379.             'nillable'=>$nillable,
  380.             'minOccurs'=>$minOccurs,
  381.             'maxOccurs'=>$maxOccurs
  382.         );
  383.     }
  384.  
  385.     /**
  386.     * Import custom XML source node into WSDL document under specified target node
  387.     * @param DOMDocument $dom XML WSDL document being generated
  388.     * @param DOMElement $target XML node, to which will be appended $source node
  389.     * @param DOMNode $source Source XML node to be imported
  390.     */
  391.     protected function injectDom(DOMDocument $dom, DOMElement $target, DOMNode $source)
  392.     {
  393.         if ($source->nodeType!=XML_ELEMENT_NODE)
  394.             return;
  395.  
  396.         $import=$dom->createElement($source->nodeName);
  397.  
  398.         foreach($source->attributes as $attr)
  399.             $import->setAttribute($attr->name,$attr->value);
  400.  
  401.         foreach($source->childNodes as $child)
  402.             $this->injectDom($dom,$import,$child);
  403.  
  404.         $target->appendChild($import);
  405.     }
  406.  
  407.     /**
  408.      * @param string $serviceUrl Web service URL
  409.      * @param string $encoding encoding of the WSDL. Defaults to 'UTF-8'.
  410.      */
  411.     protected function buildDOM($serviceUrl,$encoding)
  412.     {
  413.         $xml="<?xml version=\"1.0\" encoding=\"$encoding\"?>
  414. <definitions name=\"{$this->serviceName}\" targetNamespace=\"{$this->namespace}\"
  415.      xmlns=\"http://schemas.xmlsoap.org/wsdl/\"
  416.      xmlns:tns=\"{$this->namespace}\"
  417.      xmlns:soap=\"http://schemas.xmlsoap.org/wsdl/soap/\"
  418.      xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
  419.      xmlns:wsdl=\"http://schemas.xmlsoap.org/wsdl/\"
  420.      xmlns:soap-enc=\"http://schemas.xmlsoap.org/soap/encoding/\"></definitions>";
  421.  
  422.         $dom=new DOMDocument();
  423.         $dom->formatOutput=true;
  424.         $dom->loadXml($xml);
  425.         $this->addTypes($dom);
  426.  
  427.         $this->addMessages($dom);
  428.         $this->addPortTypes($dom);
  429.         $this->addBindings($dom);
  430.         $this->addService($dom,$serviceUrl);
  431.  
  432.         return $dom;
  433.     }
  434.  
  435.     /**
  436.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  437.      */
  438.     protected function addTypes($dom)
  439.     {
  440.         if($this->types===array())
  441.             return;
  442.         $types=$dom->createElement('wsdl:types');
  443.         $schema=$dom->createElement('xsd:schema');
  444.         $schema->setAttribute('targetNamespace',$this->namespace);
  445.         foreach($this->types as $phpType=>$xmlType)
  446.         {
  447.             if(is_string($xmlType) && strrpos($xmlType,'Array')!==strlen($xmlType)-5)
  448.                 continue;  // simple type
  449.             $complexType=$dom->createElement('xsd:complexType');
  450.             if(is_string($xmlType))
  451.             {
  452.                 if(($pos=strpos($xmlType,'tns:'))!==false)
  453.                     $complexType->setAttribute('name',substr($xmlType,4));
  454.                 else
  455.                     $complexType->setAttribute('name',$xmlType);
  456.                 $complexContent=$dom->createElement('xsd:complexContent');
  457.                 $restriction=$dom->createElement('xsd:restriction');
  458.                 $restriction->setAttribute('base','soap-enc:Array');
  459.                 $attribute=$dom->createElement('xsd:attribute');
  460.                 $attribute->setAttribute('ref','soap-enc:arrayType');
  461.                 $attribute->setAttribute('wsdl:arrayType',substr($xmlType,0,strlen($xmlType)-5).'[]');
  462.  
  463.                 $arrayType=($dppos=strpos($xmlType,':')) !==false ? substr($xmlType,$dppos + 1) : $xmlType; // strip namespace, if any
  464.                 $arrayType=substr($arrayType,0,-5); // strip 'Array' from name
  465.                 $arrayType=(isset(self::$typeMap[$arrayType]) ? 'xsd:' : 'tns:') .$arrayType.'[]';
  466.                 $attribute->setAttribute('wsdl:arrayType',$arrayType);
  467.  
  468.                 $restriction->appendChild($attribute);
  469.                 $complexContent->appendChild($restriction);
  470.                 $complexType->appendChild($complexContent);
  471.             }
  472.             elseif(is_array($xmlType))
  473.             {
  474.                 $complexType->setAttribute('name',$phpType);
  475.                 if($xmlType['custom_wsdl']!==false)
  476.                 {
  477.                     $custom_dom=new DOMDocument();
  478.                     $custom_dom->loadXML('<root xmlns:xsd="http://www.w3.org/2001/XMLSchema">'.$xmlType['custom_wsdl'].'</root>');
  479.                     foreach($custom_dom->documentElement->childNodes as $el)
  480.                         $this->injectDom($dom,$complexType,$el);
  481.                 }else{
  482.                     $all=$dom->createElement('xsd:' . $xmlType['indicator']);
  483.  
  484.                     if(!is_null($xmlType['minOccurs']))
  485.                         $all->setAttribute('minOccurs',$xmlType['minOccurs']);
  486.                     if(!is_null($xmlType['maxOccurs']))
  487.                         $all->setAttribute('maxOccurs',$xmlType['maxOccurs']);
  488.                     if(!is_null($xmlType['nillable']))
  489.                         $all->setAttribute('nillable',$xmlType['nillable']);
  490.  
  491.                     foreach($xmlType['properties'] as $name=>$type)
  492.                     {
  493.                         $element=$dom->createElement('xsd:element');
  494.                         if(!is_null($type[3]))
  495.                             $element->setAttribute('minOccurs',$type[3]);
  496.                         if(!is_null($type[4]))
  497.                             $element->setAttribute('maxOccurs',$type[4]);
  498.                         if(!is_null($type[2]))
  499.                             $element->setAttribute('nillable',$type[2]);
  500.                         $element->setAttribute('name',$name);
  501.                         $element->setAttribute('type',$type[0]);
  502.                         $all->appendChild($element);
  503.                     }
  504.                     $complexType->appendChild($all);
  505.                 }
  506.             }
  507.             $schema->appendChild($complexType);
  508.             $types->appendChild($schema);
  509.         }
  510.         $dom->documentElement->appendChild($types);
  511.     }
  512.  
  513.     /**
  514.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  515.      */
  516.     protected function addMessages($dom)
  517.     {
  518.         foreach($this->messages as $name=>$message)
  519.         {
  520.             $element=$dom->createElement('wsdl:message');
  521.             $element->setAttribute('name',$name);
  522.             foreach($this->messages[$name] as $partName=>$part)
  523.             {
  524.                 if(is_array($part))
  525.                 {
  526.                     $partElement=$dom->createElement('wsdl:part');
  527.                     $partElement->setAttribute('name',$partName);
  528.                     $partElement->setAttribute('type',$part[0]);
  529.                     $element->appendChild($partElement);
  530.                 }
  531.             }
  532.             $dom->documentElement->appendChild($element);
  533.         }
  534.     }
  535.  
  536.     /**
  537.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  538.      */
  539.     protected function addPortTypes($dom)
  540.     {
  541.         $portType=$dom->createElement('wsdl:portType');
  542.         $portType->setAttribute('name',$this->serviceName.'PortType');
  543.         $dom->documentElement->appendChild($portType);
  544.         foreach($this->operations as $name=>$doc)
  545.             $portType->appendChild($this->createPortElement($dom,$name,$doc));
  546.     }
  547.  
  548.     /**
  549.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  550.      * @param string $name method name
  551.      * @param string $doc doc
  552.      */
  553.     protected function createPortElement($dom,$name,$doc)
  554.     {
  555.         $operation=$dom->createElement('wsdl:operation');
  556.         $operation->setAttribute('name',$name);
  557.  
  558.         $input=$dom->createElement('wsdl:input');
  559.         $input->setAttribute('message', 'tns:'.$name.'Request');
  560.         $output=$dom->createElement('wsdl:output');
  561.         $output->setAttribute('message', 'tns:'.$name.'Response');
  562.  
  563.         $operation->appendChild($dom->createElement('wsdl:documentation',$doc));
  564.         $operation->appendChild($input);
  565.         $operation->appendChild($output);
  566.  
  567.         return $operation;
  568.     }
  569.  
  570.     /**
  571.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  572.      */
  573.     protected function addBindings($dom)
  574.     {
  575.         $binding=$dom->createElement('wsdl:binding');
  576.         $binding->setAttribute('name',$this->serviceName.'Binding');
  577.         $binding->setAttribute('type','tns:'.$this->serviceName.'PortType');
  578.  
  579.         $soapBinding=$dom->createElement('soap:binding');
  580.         $soapBinding->setAttribute('style','rpc');
  581.         $soapBinding->setAttribute('transport','http://schemas.xmlsoap.org/soap/http');
  582.         $binding->appendChild($soapBinding);
  583.  
  584.         $dom->documentElement->appendChild($binding);
  585.  
  586.         foreach($this->operations as $name=>$doc)
  587.             $binding->appendChild($this->createOperationElement($dom,$name));
  588.     }
  589.  
  590.     /**
  591.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  592.      * @param string $name method name
  593.      */
  594.     protected function createOperationElement($dom,$name)
  595.     {
  596.         $operation=$dom->createElement('wsdl:operation');
  597.         $operation->setAttribute('name', $name);
  598.         $soapOperation=$dom->createElement('soap:operation');
  599.         $soapOperation->setAttribute('soapAction', $this->namespace.'#'.$name);
  600.         $soapOperation->setAttribute('style','rpc');
  601.  
  602.         $input=$dom->createElement('wsdl:input');
  603.         $output=$dom->createElement('wsdl:output');
  604.  
  605.         $soapBody=$dom->createElement('soap:body');
  606.         $soapBody->setAttribute('use', 'encoded');
  607.         $soapBody->setAttribute('namespace', $this->namespace);
  608.         $soapBody->setAttribute('encodingStyle', 'http://schemas.xmlsoap.org/soap/encoding/');
  609.         $input->appendChild($soapBody);
  610.         $output->appendChild(clone $soapBody);
  611.  
  612.         $operation->appendChild($soapOperation);
  613.         $operation->appendChild($input);
  614.         $operation->appendChild($output);
  615.  
  616.         return $operation;
  617.     }
  618.  
  619.     /**
  620.      * @param DOMDocument $dom Represents an entire HTML or XML document; serves as the root of the document tree
  621.      * @param string $serviceUrl Web service URL
  622.      */
  623.     protected function addService($dom,$serviceUrl)
  624.     {
  625.         $service=$dom->createElement('wsdl:service');
  626.         $service->setAttribute('name', $this->serviceName.'Service');
  627.  
  628.         $port=$dom->createElement('wsdl:port');
  629.         $port->setAttribute('name', $this->serviceName.'Port');
  630.         $port->setAttribute('binding', 'tns:'.$this->serviceName.'Binding');
  631.  
  632.         $soapAddress=$dom->createElement('soap:address');
  633.         $soapAddress->setAttribute('location',$serviceUrl);
  634.         $port->appendChild($soapAddress);
  635.         $service->appendChild($port);
  636.         $dom->documentElement->appendChild($service);
  637.     }
  638.  
  639.     /**
  640.     * Generate human friendly HTML documentation for complex data types.
  641.     * This method can be invoked either by inserting URL parameter "&makedoc" into URL link, e.g. "http://www.mydomain.com/soap/create?makedoc", or simply by calling from another script with argument $return=true.
  642.     *
  643.     * Each complex data type is described in a separate HTML table containing following columns:
  644.     * <ul>
  645.     * <li># - attribute ID</li>
  646.     * <li>Attribute - attribute name, e.g. firstname</li>
  647.     * <li>Type - attribute type, e.g. integer, date, tns:SoapPovCalculationResultArray</li>
  648.     * <li>Nill - true|false - whether the attribute is nillable</li>
  649.     * <li>Min - minimum number of occurrences</li>
  650.     * <li>Max - maximum number of occurrences</li>
  651.     * <li>Description - Detailed description of the attribute.</li>
  652.     * <li>Example - Attribute example value if provided via PHPDoc property @example.</li>
  653.     * <ul>
  654.     *
  655.     * @param bool $return If true, generated HTML output will be returned rather than directly sent to output buffer
  656.     */
  657.     public function buildHtmlDocs($return=false)
  658.     {
  659.         $html='<html><head>';
  660.         $html.='<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';
  661.         $html.='<style type="text/css">
  662. table{border-collapse: collapse;background-color: #DDDDDD;}
  663. tr{background-color: #FFFFFF;}
  664. th{background-color: #EEEEEE;}
  665. th, td{font-size: 12px;font-family: courier;padding: 3px;}
  666. </style>';
  667.         $html.='</head><body>';
  668.         $html.='<h2>WSDL documentation for service '.$this->serviceName.'</h2>';
  669.         $html.='<p>Generated on '.date('d.m.Y H:i:s').'</p>';
  670.         $html.='<table border="0" cellspacing="1" cellpadding="1">';
  671.         $html.='<tr><td>';
  672.  
  673.         if(!empty($this->types))
  674.         {
  675.             foreach($this->types as $object=>$options){
  676.                 if(!is_array($options) || empty($options) || !is_array($options['properties']) || empty($options['properties'])){
  677.                     continue;
  678.                 }
  679.                 $params=$options['properties'];
  680.                 $html.="\n\n<h3>Object: {$object}</h3>";
  681.                 $html.='<table border="1" cellspacing="1" cellpadding="1">';
  682.                 $html.='<tr><th>#</th><th>Attribute</th><th>Type</th><th>Nill</th><th>Min</th><th>Max</th><th>Description</th><th>Example</th></tr>';
  683.                 $c=0;
  684.                 foreach($params as $param=>$prop){
  685.                     ++$c;
  686.                     $html.="\n<tr>"
  687.                                 ."\n\t<td>{$c}</td>"
  688.                                 ."\n\t<td>{$param}</td>"
  689.                                 ."\n\t<td>".(str_replace('xsd:','',$prop[0]))."</td>"
  690.                                 ."\n\t<td>".$prop[2]."</td>"
  691.                                 ."\n\t<td>".($prop[3]==null ? '&nbsp;' : $prop[3])."</td>"
  692.                                 ."\n\t<td>".($prop[4]==null ? '&nbsp;' : $prop[4])."</td>"
  693.                                 ."\n\t<td>{$prop[1]}</td>"
  694.                                 ."\n\t<td>".(trim($prop[5])=='' ? '&nbsp;' : $prop[5])."</td>"
  695.                             ."\n</tr>";
  696.                 }
  697.                 $html.="\n</table><br/>";
  698.             }
  699.         }
  700.         else
  701.             $html.='No complex data type found!';
  702.  
  703.         $html.='</td></tr></table></body></html>';
  704.  
  705.         if($return)
  706.             return $html;
  707.  
  708.         echo $html;
  709.         Yii::app()->end(); // end the app to avoid conflict with text/xml header
  710.     }
  711. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement