PageRenderTime 46ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Zend/Amf/Parse/Amf0/Serializer.php

https://bitbucket.org/acidel/buykoala
PHP | 362 lines | 208 code | 21 blank | 133 comment | 43 complexity | 3f7f80f9d88bbbd69d212ae0c5efd649 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Amf
  17. * @subpackage Parse_Amf0
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Serializer.php 21968 2010-04-22 03:53:34Z matthew $
  21. */
  22. /** Zend_Amf_Constants */
  23. #require_once 'Zend/Amf/Constants.php';
  24. /** @see Zend_Amf_Parse_Serializer */
  25. #require_once 'Zend/Amf/Parse/Serializer.php';
  26. /**
  27. * Serializer PHP misc types back to there corresponding AMF0 Type Marker.
  28. *
  29. * @uses Zend_Amf_Parse_Serializer
  30. * @package Zend_Amf
  31. * @subpackage Parse_Amf0
  32. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
  36. {
  37. /**
  38. * @var string Name of the class to be returned
  39. */
  40. protected $_className = '';
  41. /**
  42. * An array of reference objects
  43. * @var array
  44. */
  45. protected $_referenceObjects = array();
  46. /**
  47. * Determine type and serialize accordingly
  48. *
  49. * Checks to see if the type was declared and then either
  50. * auto negotiates the type or relies on the user defined markerType to
  51. * serialize the data into amf
  52. *
  53. * @param mixed $data
  54. * @param mixed $markerType
  55. * @param mixed $dataByVal
  56. * @return Zend_Amf_Parse_Amf0_Serializer
  57. * @throws Zend_Amf_Exception for unrecognized types or data
  58. */
  59. public function writeTypeMarker(&$data, $markerType = null, $dataByVal = false)
  60. {
  61. // Workaround for PHP5 with E_STRICT enabled complaining about "Only
  62. // variables should be passed by reference"
  63. if ((null === $data) && ($dataByVal !== false)) {
  64. $data = &$dataByVal;
  65. }
  66. if (null !== $markerType) {
  67. //try to reference the given object
  68. if (!$this->writeObjectReference($data, $markerType)) {
  69. // Write the Type Marker to denote the following action script data type
  70. $this->_stream->writeByte($markerType);
  71. switch($markerType) {
  72. case Zend_Amf_Constants::AMF0_NUMBER:
  73. $this->_stream->writeDouble($data);
  74. break;
  75. case Zend_Amf_Constants::AMF0_BOOLEAN:
  76. $this->_stream->writeByte($data);
  77. break;
  78. case Zend_Amf_Constants::AMF0_STRING:
  79. $this->_stream->writeUTF($data);
  80. break;
  81. case Zend_Amf_Constants::AMF0_OBJECT:
  82. $this->writeObject($data);
  83. break;
  84. case Zend_Amf_Constants::AMF0_NULL:
  85. break;
  86. case Zend_Amf_Constants::AMF0_REFERENCE:
  87. $this->_stream->writeInt($data);
  88. break;
  89. case Zend_Amf_Constants::AMF0_MIXEDARRAY:
  90. // Write length of numeric keys as zero.
  91. $this->_stream->writeLong(0);
  92. $this->writeObject($data);
  93. break;
  94. case Zend_Amf_Constants::AMF0_ARRAY:
  95. $this->writeArray($data);
  96. break;
  97. case Zend_Amf_Constants::AMF0_DATE:
  98. $this->writeDate($data);
  99. break;
  100. case Zend_Amf_Constants::AMF0_LONGSTRING:
  101. $this->_stream->writeLongUTF($data);
  102. break;
  103. case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
  104. $this->writeTypedObject($data);
  105. break;
  106. case Zend_Amf_Constants::AMF0_AMF3:
  107. $this->writeAmf3TypeMarker($data);
  108. break;
  109. default:
  110. #require_once 'Zend/Amf/Exception.php';
  111. throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
  112. }
  113. }
  114. } else {
  115. if (is_resource($data)) {
  116. $data = Zend_Amf_Parse_TypeLoader::handleResource($data);
  117. }
  118. switch (true) {
  119. case (is_int($data) || is_float($data)):
  120. $markerType = Zend_Amf_Constants::AMF0_NUMBER;
  121. break;
  122. case (is_bool($data)):
  123. $markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
  124. break;
  125. case (is_string($data) && (strlen($data) > 65536)):
  126. $markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
  127. break;
  128. case (is_string($data)):
  129. $markerType = Zend_Amf_Constants::AMF0_STRING;
  130. break;
  131. case (is_object($data)):
  132. if (($data instanceof DateTime) || ($data instanceof Zend_Date)) {
  133. $markerType = Zend_Amf_Constants::AMF0_DATE;
  134. } else {
  135. if($className = $this->getClassName($data)){
  136. //Object is a Typed object set classname
  137. $markerType = Zend_Amf_Constants::AMF0_TYPEDOBJECT;
  138. $this->_className = $className;
  139. } else {
  140. // Object is a generic classname
  141. $markerType = Zend_Amf_Constants::AMF0_OBJECT;
  142. }
  143. break;
  144. }
  145. break;
  146. case (null === $data):
  147. $markerType = Zend_Amf_Constants::AMF0_NULL;
  148. break;
  149. case (is_array($data)):
  150. // check if it is an associative array
  151. $i = 0;
  152. foreach (array_keys($data) as $key) {
  153. // check if it contains non-integer keys
  154. if (!is_numeric($key) || intval($key) != $key) {
  155. $markerType = Zend_Amf_Constants::AMF0_OBJECT;
  156. break;
  157. // check if it is a sparse indexed array
  158. } else if ($key != $i) {
  159. $markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
  160. break;
  161. }
  162. $i++;
  163. }
  164. // Dealing with a standard numeric array
  165. if(!$markerType){
  166. $markerType = Zend_Amf_Constants::AMF0_ARRAY;
  167. break;
  168. }
  169. break;
  170. default:
  171. #require_once 'Zend/Amf/Exception.php';
  172. throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data));
  173. }
  174. $this->writeTypeMarker($data, $markerType);
  175. }
  176. return $this;
  177. }
  178. /**
  179. * Check if the given object is in the reference table, write the reference if it exists,
  180. * otherwise add the object to the reference table
  181. *
  182. * @param mixed $object object reference to check for reference
  183. * @param $markerType AMF type of the object to write
  184. * @param mixed $objectByVal object to check for reference
  185. * @return Boolean true, if the reference was written, false otherwise
  186. */
  187. protected function writeObjectReference(&$object, $markerType, $objectByVal = false)
  188. {
  189. // Workaround for PHP5 with E_STRICT enabled complaining about "Only
  190. // variables should be passed by reference"
  191. if ((null === $object) && ($objectByVal !== false)) {
  192. $object = &$objectByVal;
  193. }
  194. if ($markerType == Zend_Amf_Constants::AMF0_OBJECT
  195. || $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY
  196. || $markerType == Zend_Amf_Constants::AMF0_ARRAY
  197. || $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT
  198. ) {
  199. $ref = array_search($object, $this->_referenceObjects, true);
  200. //handle object reference
  201. if($ref !== false){
  202. $this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE);
  203. return true;
  204. }
  205. $this->_referenceObjects[] = $object;
  206. }
  207. return false;
  208. }
  209. /**
  210. * Write a PHP array with string or mixed keys.
  211. *
  212. * @param object $data
  213. * @return Zend_Amf_Parse_Amf0_Serializer
  214. */
  215. public function writeObject($object)
  216. {
  217. // Loop each element and write the name of the property.
  218. foreach ($object as $key => &$value) {
  219. // skip variables starting with an _ private transient
  220. if( $key[0] == "_") continue;
  221. $this->_stream->writeUTF($key);
  222. $this->writeTypeMarker($value);
  223. }
  224. // Write the end object flag
  225. $this->_stream->writeInt(0);
  226. $this->_stream->writeByte(Zend_Amf_Constants::AMF0_OBJECTTERM);
  227. return $this;
  228. }
  229. /**
  230. * Write a standard numeric array to the output stream. If a mixed array
  231. * is encountered call writeTypeMarker with mixed array.
  232. *
  233. * @param array $array
  234. * @return Zend_Amf_Parse_Amf0_Serializer
  235. */
  236. public function writeArray(&$array)
  237. {
  238. $length = count($array);
  239. if (!$length < 0) {
  240. // write the length of the array
  241. $this->_stream->writeLong(0);
  242. } else {
  243. // Write the length of the numeric array
  244. $this->_stream->writeLong($length);
  245. for ($i=0; $i<$length; $i++) {
  246. $value = isset($array[$i]) ? $array[$i] : null;
  247. $this->writeTypeMarker($value);
  248. }
  249. }
  250. return $this;
  251. }
  252. /**
  253. * Convert the DateTime into an AMF Date
  254. *
  255. * @param DateTime|Zend_Date $data
  256. * @return Zend_Amf_Parse_Amf0_Serializer
  257. */
  258. public function writeDate($data)
  259. {
  260. if ($data instanceof DateTime) {
  261. $dateString = $data->format('U');
  262. } elseif ($data instanceof Zend_Date) {
  263. $dateString = $data->toString('U');
  264. } else {
  265. #require_once 'Zend/Amf/Exception.php';
  266. throw new Zend_Amf_Exception('Invalid date specified; must be a DateTime or Zend_Date object');
  267. }
  268. $dateString *= 1000;
  269. // Make the conversion and remove milliseconds.
  270. $this->_stream->writeDouble($dateString);
  271. // Flash does not respect timezone but requires it.
  272. $this->_stream->writeInt(0);
  273. return $this;
  274. }
  275. /**
  276. * Write a class mapped object to the output stream.
  277. *
  278. * @param object $data
  279. * @return Zend_Amf_Parse_Amf0_Serializer
  280. */
  281. public function writeTypedObject($data)
  282. {
  283. $this->_stream->writeUTF($this->_className);
  284. $this->writeObject($data);
  285. return $this;
  286. }
  287. /**
  288. * Encountered and AMF3 Type Marker use AMF3 serializer. Once AMF3 is
  289. * encountered it will not return to AMf0.
  290. *
  291. * @param string $data
  292. * @return Zend_Amf_Parse_Amf0_Serializer
  293. */
  294. public function writeAmf3TypeMarker(&$data)
  295. {
  296. #require_once 'Zend/Amf/Parse/Amf3/Serializer.php';
  297. $serializer = new Zend_Amf_Parse_Amf3_Serializer($this->_stream);
  298. $serializer->writeTypeMarker($data);
  299. return $this;
  300. }
  301. /**
  302. * Find if the class name is a class mapped name and return the
  303. * respective classname if it is.
  304. *
  305. * @param object $object
  306. * @return false|string $className
  307. */
  308. protected function getClassName($object)
  309. {
  310. #require_once 'Zend/Amf/Parse/TypeLoader.php';
  311. //Check to see if the object is a typed object and we need to change
  312. $className = '';
  313. switch (true) {
  314. // the return class mapped name back to actionscript class name.
  315. case Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)):
  316. $className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object));
  317. break;
  318. // Check to see if the user has defined an explicit Action Script type.
  319. case isset($object->_explicitType):
  320. $className = $object->_explicitType;
  321. break;
  322. // Check if user has defined a method for accessing the Action Script type
  323. case method_exists($object, 'getASClassName'):
  324. $className = $object->getASClassName();
  325. break;
  326. // No return class name is set make it a generic object
  327. case ($object instanceof stdClass):
  328. $className = '';
  329. break;
  330. // By default, use object's class name
  331. default:
  332. $className = get_class($object);
  333. break;
  334. }
  335. if(!$className == '') {
  336. return $className;
  337. } else {
  338. return false;
  339. }
  340. }
  341. }