XRL  3.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 
111  public static function convert($value)
112  {
113  switch (gettype($value)) {
114  case 'NULL':
115  // Support for the <nil> extension
116  // (http://ontosys.com/xml-rpc/extensions.php)
117  return new \fpoirotte\XRL\Types\Nil(null);
118 
119  case 'boolean':
120  return new \fpoirotte\XRL\Types\Boolean($value);
121 
122  case 'integer':
123  try {
124  return new \fpoirotte\XRL\Types\I4($value);
125  } catch (\InvalidArgumentException $e) {
126  }
127  return new \fpoirotte\XRL\Types\I8($value);
128 
129  case 'double':
130  return new \fpoirotte\XRL\Types\Double($value);
131 
132  case 'string':
133  // Encode as a regular string if possible.
134  if (static::isUTF8($value)) {
135  return new \fpoirotte\XRL\Types\StringType($value);
136  }
137  return new \fpoirotte\XRL\Types\Base64($value);
138 
139  case 'array':
140  $newValue = array_map("static::convert", $value);
141  try {
142  return new \fpoirotte\XRL\Types\ArrayType($newValue);
143  } catch (\InvalidArgumentException $e) {
144  }
145  return new \fpoirotte\XRL\Types\Struct($newValue);
146 
147  case 'object':
148  case 'resource':
149  // A special treatment is applied afterwards.
150  break;
151  }
152 
153  // Only objects & resources remain after this point.
154  if ($value instanceof \fpoirotte\XRL\Types\AbstractType) {
155  return $value;
156  }
157 
158  if ($value instanceof \GMP ||
159  (is_resource($value) && get_resource_type($value) === 'GMP integer')) {
160  $candidates = array(
161  '\\fpoirotte\\XRL\\Types\\I4',
162  '\\fpoirotte\\XRL\\Types\\I8',
163  '\\fpoirotte\\XRL\\Types\\BigInteger',
164  );
165  foreach ($candidates as $candidate) {
166  try {
167  return new $candidate($value);
168  } catch (\InvalidArgumentException $e) {
169  }
170  }
171  }
172 
173  if ($value instanceof \DateTime) {
174  return new \fpoirotte\XRL\Types\DateTimeIso8601($value);
175  }
176 
177  if (($value instanceof \DOMNode) ||
178  ($value instanceof \XMLWriter) ||
179  ($value instanceof \SimpleXMLElement)) {
180  return new \fpoirotte\XRL\Types\Dom($value);
181  }
182 
183  if ($value instanceof \Exception) {
184  return new \fpoirotte\XRL\Types\Struct(
185  array(
186  'faultCode' => new \fpoirotte\XRL\Types\IntType($value->getCode()),
187  'faultString' => new \fpoirotte\XRL\Types\StringType(
188  get_class($value).': '.$value->getMessage()
189  ),
190  )
191  );
192  }
193 
194  if (is_object($value) && (
195  ($value instanceof \Serializable) ||
196  method_exists($value, '__sleep'))) {
197  $value = serialize($value);
198 
199  // Encode as a regular string if possible.
200  if (static::isUTF8($value)) {
201  return new \fpoirotte\XRL\Types\StringType($value);
202  }
203  return new \fpoirotte\XRL\Types\Base64($value);
204  }
205 
206  throw new \InvalidArgumentException('Unconvertible type');
207  }
208 
210  public function encodeRequest(\fpoirotte\XRL\Request $request)
211  {
212  $newParams = array_map('static::convert', $request->getParams());
213  return $this->encoder->encodeRequest(
214  new \fpoirotte\XRL\Request($request->getProcedure(), $newParams)
215  );
216  }
217 
219  public function encodeError(\Exception $error)
220  {
221  return $this->encoder->encodeError($error);
222  }
223 
225  public function encodeResponse($response)
226  {
227  return $this->encoder->encodeResponse(static::convert($response));
228  }
229 }
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