XRL  2.0.0
Simple XML-RPC Library (both client and server)
NativeEncoder.php
1 <?php
2 /*
3  * This file is part of XRL, a simple XML-RPC Library for PHP.
4  *
5  * Copyright (c) 2012, XRL Team. All rights reserved.
6  * XRL is licensed under the 3-clause BSD License.
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11 
12 namespace fpoirotte\XRL;
13 
22 {
24  protected $encoder;
25 
32  public function __construct(\fpoirotte\XRL\EncoderInterface $encoder)
33  {
34  $this->encoder = $encoder;
35  }
36 
48  protected static function isUTF8($text)
49  {
50  // From http://w3.org/International/questions/qa-forms-utf-8.html
51  // Pointed out by bitseeker on http://php.net/utf8_encode
52  return (bool) preg_match(
53  '%^(?:
54  [\x09\x0A\x0D\x20-\x7E] # ASCII
55  | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
56  | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
57  | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte
58  | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates
59  | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
60  | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
61  | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
62  )*$%SDxs',
63  $text
64  );
65  }
66 
104  public static function convert($value)
105  {
106  switch (gettype($value)) {
107  case 'NULL':
108  // Support for the <nil> extension
109  // (http://ontosys.com/xml-rpc/extensions.php)
110  return new \fpoirotte\XRL\Types\Nil(null);
111 
112  case 'boolean':
113  return new \fpoirotte\XRL\Types\Boolean($value);
114 
115  case 'integer':
116  try {
117  return new \fpoirotte\XRL\Types\I4($value);
118  } catch (\InvalidArgumentException $e) {
119  }
120  return new \fpoirotte\XRL\Types\I8($value);
121 
122  case 'double':
123  return new \fpoirotte\XRL\Types\Double($value);
124 
125  case 'string':
126  // Encode as a regular string if possible.
127  if (static::isUTF8($value)) {
128  return new \fpoirotte\XRL\Types\String($value);
129  }
130  return new \fpoirotte\XRL\Types\Base64($value);
131 
132  case 'array':
133  $newValue = array_map("static::convert", $value);
134  try {
135  return new \fpoirotte\XRL\Types\ArrayType($newValue);
136  } catch (\InvalidArgumentException $e) {
137  }
138  return new \fpoirotte\XRL\Types\Struct($newValue);
139 
140  case 'object':
141  // A special treatment is applied afterwards.
142  break;
143 
144  case 'resource':
145  if (get_resource_type($value) === 'GMP integer') {
146  try {
147  return new \fpoirotte\XRL\Types\I4($value);
148  } catch (\InvalidArgumentException $e) {
149  }
150  try {
151  return new \fpoirotte\XRL\Types\I8($value);
152  } catch (\InvalidArgumentException $e) {
153  }
154  return new \fpoirotte\XRL\Types\BigInteger($value);
155  }
156  // Fall-through intentional.
157 
158  default:
159  throw new \InvalidArgumentException('Unconvertible type');
160  }
161 
162  // Only objects remain after this points.
163  if ($value instanceof \fpoirotte\XRL\Types\AbstractType) {
164  return $value;
165  }
166 
167  if ($value instanceof \GMP) {
168  try {
169  return new \fpoirotte\XRL\Types\I4($value);
170  } catch (\InvalidArgumentException $e) {
171  }
172  try {
173  return new \fpoirotte\XRL\Types\I8($value);
174  } catch (\InvalidArgumentException $e) {
175  }
176  return new \fpoirotte\XRL\Types\BigInteger($value);
177  }
178 
179  if ($value instanceof \DateTime) {
180  return new \fpoirotte\XRL\Types\DateTimeIso8601($value);
181  }
182 
183  if (($value instanceof \DOMNode) ||
184  ($value instanceof \XMLWriter) ||
185  ($value instanceof \SimpleXMLElement)) {
186  return new \fpoirotte\XRL\Types\Dom($value);
187  }
188 
189  if ($value instanceof \Exception) {
190  return new \fpoirotte\XRL\Types\Struct(
191  array(
192  'faultCode' => new \fpoirotte\XRL\Types\Int($value->getCode()),
193  'faultString' => new \fpoirotte\XRL\Types\String(
194  get_class($value).': '.$value->getMessage()
195  ),
196  )
197  );
198  }
199 
200  if (!($value instanceof \Serializable) && !method_exists($value, '__sleep')) {
201  throw new \InvalidArgumentException('Could not serialize object');
202  }
203  }
204 
206  public function encodeRequest(\fpoirotte\XRL\Request $request)
207  {
208  $newParams = array_map('static::convert', $request->getParams());
209  return $this->encoder->encodeRequest(
210  new \fpoirotte\XRL\Request($request->getProcedure(), $newParams)
211  );
212  }
213 
215  public function encodeError(\Exception $error)
216  {
217  return $this->encoder->encodeError($error);
218  }
219 
221  public function encodeResponse($response)
222  {
223  return $this->encoder->encodeResponse(static::convert($response));
224  }
225 }
Interface for customized serializing.
Interface for an XML-RPC encoder.
An exception that is used to represent XML-RPC errors.
Definition: Exception.php:21
__construct(\fpoirotte\XRL\EncoderInterface $encoder)
encodeError(\Exception $error)
An XML-RPC encoder that transparently converts PHP types to their XML-RPC counterpart.
encodeRequest(\fpoirotte\XRL\Request $request)
A class that represents an XML-RPC request.
Definition: Request.php:20