base.php

来自「PHP 知识管理系统(基于树结构的知识管理系统), 英文原版的PHP源码。」· PHP 代码 · 共 1,251 行 · 第 1/3 页

PHP
1,251
字号
        if (isset($this->_namespaces[$ns])) {
            return $this->_namespaces[$ns];
        }
        $prefix = 'ns' . count($this->_namespaces);
        $this->_namespaces[$ns] = $prefix;
        return $prefix;
    }

    function _getNamespaceForPrefix($prefix)
    {
        $flipped = array_flip($this->_namespaces);
        if (isset($flipped[$prefix])) {
            return $flipped[$prefix];
        }
        return null;
    }

    function _isSoapValue(&$value)
    {
        return is_a($value, 'SOAP_Value');
    }

    function _serializeValue(&$value, $name = '', $type = false,
                             $elNamespace = null, $typeNamespace = null,
                             $options = array(), $attributes = array(),
                             $artype = '')
    {
        $namespaces = array();
        $arrayType = $array_depth = $xmlout_value = null;
        $typePrefix = $elPrefix = $xmlout_offset = $xmlout_arrayType = '';
        $xmlout_type = $xmlns = $ptype = $array_type_ns = '';

        if (!$name || is_numeric($name)) {
            $name = 'item';
        }

        if ($this->_wsdl) {
            list($ptype, $arrayType, $array_type_ns, $array_depth)
                = $this->_wsdl->getSchemaType($type, $name, $typeNamespace);
        }

        if (!$arrayType) {
            $arrayType = $artype;
        }
        if (!$ptype) {
            $ptype = $this->_getType($value);
        }
        if (!$type) {
            $type = $ptype;
        }

        if (strcasecmp($ptype, 'Struct') == 0 ||
            strcasecmp($type, 'Struct') == 0) {
            // Struct
            $vars = null;
            if (is_object($value)) {
                $vars = get_object_vars($value);
            } else {
                $vars = &$value;
            }
            if (is_array($vars)) {
                foreach (array_keys($vars) as $k) {
                    // Hide private vars.
                    if ($k[0] == '_') continue;
                    if (is_object($vars[$k])) {
                        if (is_a($vars[$k], 'SOAP_Value')) {
                            $xmlout_value .= $vars[$k]->serialize($this);
                        } else {
                            // XXX get the members and serialize them instead
                            // converting to an array is more overhead than we
                            // should really do.
                            $xmlout_value .= $this->_serializeValue(get_object_vars($vars[$k]), $k, false, $this->_section5 ? null : $elNamespace);
                        }
                    } else {
                        if ($this->isValidField($k, $type))
                        {
                            $xmlout_value .= $this->_serializeValue($vars[$k], $k, false, $this->_section5 ? null : $elNamespace);
                        }
                    }
                }
            }
        } elseif (strcasecmp($ptype, 'Array') == 0 ||
                  strcasecmp($type, 'Array') == 0) {
            // Array.
            $typeNamespace = SOAP_SCHEMA_ENCODING;
            $orig_type = $type;
            $type = 'Array';
            $numtypes = 0;
            // XXX this will be slow on larger arrays.  Basically, it flattens
            // arrays to allow us to serialize multi-dimensional arrays.  We
            // only do this if arrayType is set, which will typically only
            // happen if we are using WSDL
            if (isset($options['flatten']) ||
                ($arrayType &&
                 (strchr($arrayType, ',') || strstr($arrayType, '][')))) {
                $numtypes = $this->_multiArrayType($value, $arrayType,
                                                   $ar_size, $xmlout_value);
            }

            $array_type = $array_type_prefix = '';
            if ($numtypes != 1) {
                $arrayTypeQName =& new QName($arrayType);
                $arrayType = $arrayTypeQName->name;
                $array_types = array();
                $array_val = null;

                // Serialize each array element.
                $ar_size = count($value);
                foreach ($value as $array_val) {
                    if ($this->_isSoapValue($array_val)) {
                        $array_type = $array_val->type;
                        $array_types[$array_type] = 1;
                        $array_type_ns = $array_val->type_namespace;
                        $xmlout_value .= $array_val->serialize($this);
                    } else {
                        $array_type = $this->_getType($array_val);
                        $array_types[$array_type] = 1;
                        $xmlout_value .= $this->_serializeValue($array_val, 'item', $array_type, $this->_section5 ? null : $elNamespace);
                    }
                }

                $xmlout_offset = ' SOAP-ENC:offset="[0]"';
                if (!$arrayType) {
                	/*
                    $numtypes = count($array_types);
                    if ($numtypes == 1) {
                        $arrayType = $array_type;
                    }
					*/
                    // Using anyType is more interoperable.
                    if ($array_type == 'Struct') {
                        $array_type = '';
                    } elseif ($array_type == 'Array') {
                        $arrayType = 'anyType';
                        $array_type_prefix = 'xsd';
                    } else {
                        if (!$arrayType) {
                            $arrayType = $array_type;
                        }
                    }
                }
            }
            if (!$arrayType || $numtypes > 1) {
                // Should reference what schema we're using.
                $arrayType = 'xsd:anyType';
            } else {
                if ($array_type_ns) {
                    $array_type_prefix = $this->_getNamespacePrefix($array_type_ns);
                } elseif (isset($this->_typemap[$this->_XMLSchemaVersion][$arrayType])) {
                    $array_type_prefix = $this->_namespaces[$this->_XMLSchemaVersion];
                }
                if ($array_type_prefix) {
                    $arrayType = $array_type_prefix . ':' . $arrayType;
                }
            }

            $xmlout_arrayType = ' SOAP-ENC:arrayType="' . $arrayType;
            if ($array_depth != null) {
                for ($i = 0; $i < $array_depth; $i++) {
                    $xmlout_arrayType .= '[]';
                }
            }
            $xmlout_arrayType .= "[$ar_size]\"";
        } elseif ($this->_isSoapValue($value)) {
            $xmlout_value = $value->serialize($this);
        } elseif ($type == 'string') {
            $xmlout_value = htmlspecialchars($value);
        } elseif ($type == 'rawstring') {
            $xmlout_value =& $value;
        } elseif ($type == 'boolean') {
            $xmlout_value = $value ? 'true' : 'false';
        } else {
            $xmlout_value =& $value;
        }

        // Add namespaces.
        if ($elNamespace) {
            $elPrefix = $this->_getNamespacePrefix($elNamespace);
            if ($elPrefix) {
                $xmlout_name = "$elPrefix:$name";
            } else {
                $xmlout_name = $name;
            }
        } else {
            $xmlout_name = $name;
        }

        if ($typeNamespace) {
            $typePrefix = $this->_getNamespacePrefix($typeNamespace);
            if ($typePrefix) {
                $xmlout_type = "$typePrefix:$type";
            } else {
                $xmlout_type = $type;
            }
        } elseif ($type &&
                  isset($this->_typemap[$this->_XMLSchemaVersion][$type])) {
            $typePrefix = $this->_namespaces[$this->_XMLSchemaVersion];
            if ($typePrefix) {
                $xmlout_type = "$typePrefix:$type";
            } else {
                $xmlout_type = $type;
            }
        }

        // Handle additional attributes.
        $xml_attr = '';
        if (count($attributes)) {
            foreach ($attributes as $k => $v) {
                $kqn =& new QName($k);
                $vqn =& new QName($v);
                $xml_attr .= ' ' . $kqn->fqn() . '="' . $vqn->fqn() . '"';
            }
        }

        // Store the attachment for mime encoding.
        if (isset($options['attachment']) &&
            !PEAR::isError($options['attachment'])) {
            $this->__attachments[] = $options['attachment'];
        }

        if ($this->_section5) {
            if ($xmlout_type) {
                $xmlout_type = " xsi:type=\"$xmlout_type\"";
            }
            if (is_null($xmlout_value)) {
                $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" .
                    "$xml_attr xsi:nil=\"true\"/>";
            } else {
                $xml = "\r\n<$xmlout_name$xmlout_type$xmlns$xmlout_arrayType" .
                    "$xmlout_offset$xml_attr>$xmlout_value</$xmlout_name>";
            }
        } else {
            if (is_null($xmlout_value)) {
                $xml = "\r\n<$xmlout_name$xmlns$xml_attr/>";
            } else {
                $xml = "\r\n<$xmlout_name$xmlns$xml_attr>" .
                    $xmlout_value . "</$xmlout_name>";
            }
        }

        return $xml;
    }

    /**
     * Converts a PHP type to a SOAP type.
     *
     * @access   private
     *
     * @param string $value  The value to inspect.
     *
     * @return string  The value's SOAP type.
     */
    function _getType(&$value)
    {
        global $SOAP_OBJECT_STRUCT, $SOAP_RAW_CONVERT;

        $type = gettype($value);
        switch ($type) {
        case 'object':
            if (is_a($value, 'soap_value')) {
                $type = $value->type;
            } else {
                $type = 'Struct';
            }
            break;

        case 'array':
            // Hashes are always handled as structs.
            if ($this->_isHash($value)) {
                $type = 'Struct';
            } else {
                $ar_size = count($value);
                reset($value);
                $key1 = key($value);
                if ($ar_size > 0 && is_a($key1, 'SOAP_Value')) {
                    // FIXME: for non-wsdl structs that are all the same type
                    $key2 = key($value);
                    if ($ar_size > 1 &&
                        $this->_isSoapValue($key1) &&
                        $this->_isSoapValue($key2) &&
                        $key1->name != $key2->name) {
                        // This is a struct, not an array.
                        $type = 'Struct';
                    } else {
                        $type = 'Array';
                    }
                } else {
                    $type = 'Array';
                }
            }
            break;

        case 'integer':
        case 'long':
            $type = 'int';
            break;

        case 'boolean':
            break;

        case 'double':
            // double is deprecated in PHP 4.2 and later.
            $type = 'float';
            break;

        case 'null':
            $type = '';
            break;

        case 'string':
            if ($SOAP_RAW_CONVERT) {
                if (is_numeric($value)) {
                    if (strstr($value, '.')) {
                        $type = 'float';
                    } else {
                        $type = 'int';
                    }
                } else {
                    if (SOAP_Type_hexBinary::is_hexbin($value)) {
                        $type = 'hexBinary';
                    } else {
                        if ($this->_isBase64($value)) {
                            $type = 'base64Binary';
                        } else {
                            $dt =& new SOAP_Type_dateTime($value);
                            if ($dt->toUnixtime() != -1) {
                                $type = 'dateTime';
                            }
                        }
                    }
                }
            }
            break;

        default:
            break;
        }

        return $type;
    }

    function _multiArrayType(&$value, &$type, &$size, &$xml)
    {
        $sz = count($value);
        if (is_array($value)) {
            // Seems we have a multi dimensional array, figure it out if we
            // do.
            $c = count($value);
            for ($i = 0; $i < $c; $i++) {
                $this->_multiArrayType($value[$i], $type, $size, $xml);
            }

            if ($size) {
                $size = $sz. ',' . $size;
            } else {
                $size = $sz;
            }

            return 1;
        } else {
            if (is_object($value)) {
                $type = $value->type;
                $xml .= $value->serialize($this);
            } else {
                $type = $this->_getType($value);
                $xml .= $this->_serializeValue($value, 'item', $type);
            }
        }
        $size = null;

        return 1;
    }

    /**
     * Returns whether a string is base64 encoded data.
     *
     * @param string $value  The string to check.
     *
     * @return boolean  True if the specified value seems to be base64 encoded.
     */
    function _isBase64(&$value)
    {
        $l = strlen($value);
        if ($l) {
            return $value[$l - 1] == '=' &&
                preg_match('/[A-Za-z=\/\+]+/', $value);
        }
        return false;
    }

    /**
     * Returns whether a type is a base64 type.
     *
     * @param string $type  A type name.
     *
     * @return boolean  True if the type name is a base64 type.
     */
    function _isBase64Type($type)
    {
        return $type == 'base64' || $type == 'base64Binary';
    }

    /**
     * Returns whether an array is a hash.
     *
     * @param array $a  An array to check.
     *
     * @return boolean  True if the specified array is a hash.
     */
    function _isHash(&$a)
    {
        // I really dislike having to loop through this in PHP code, really
        // large arrays will be slow.  We need a C function to do this.
        $names = array();
        $it = 0;
        foreach ($a as $k => $v) {
            // Checking the type is faster than regexp.

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?