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

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

https://github.com/tanduy/zf
PHP | 349 lines | 207 code | 22 blank | 120 comment | 36 complexity | 74832258cde789b02f525cf068da3e70 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$
  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 misc $data
  54. * @param misc $markerType
  55. * @return Zend_Amf_Parse_Amf0_Serializer
  56. * @throws Zend_Amf_Exception for unrecognized types or data
  57. */
  58. public function writeTypeMarker($data, $markerType = null)
  59. {
  60. if (null !== $markerType) {
  61. //try to refrence the given object
  62. if( !$this->writeObjectReference($data, $markerType) ) {
  63. // Write the Type Marker to denote the following action script data type
  64. $this->_stream->writeByte($markerType);
  65. switch($markerType) {
  66. case Zend_Amf_Constants::AMF0_NUMBER:
  67. $this->_stream->writeDouble($data);
  68. break;
  69. case Zend_Amf_Constants::AMF0_BOOLEAN:
  70. $this->_stream->writeByte($data);
  71. break;
  72. case Zend_Amf_Constants::AMF0_STRING:
  73. $this->_stream->writeUTF($data);
  74. break;
  75. case Zend_Amf_Constants::AMF0_OBJECT:
  76. $this->writeObject($data);
  77. break;
  78. case Zend_Amf_Constants::AMF0_NULL:
  79. break;
  80. case Zend_Amf_Constants::AMF0_REFERENCE:
  81. $this->_stream->writeInt($data);
  82. break;
  83. case Zend_Amf_Constants::AMF0_MIXEDARRAY:
  84. // Write length of numeric keys as zero.
  85. $this->_stream->writeLong(0);
  86. $this->writeObject($data);
  87. break;
  88. case Zend_Amf_Constants::AMF0_ARRAY:
  89. $this->writeArray($data);
  90. break;
  91. case Zend_Amf_Constants::AMF0_DATE:
  92. $this->writeDate($data);
  93. break;
  94. case Zend_Amf_Constants::AMF0_LONGSTRING:
  95. $this->_stream->writeLongUTF($data);
  96. break;
  97. case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
  98. $this->writeTypedObject($data);
  99. break;
  100. case Zend_Amf_Constants::AMF0_AMF3:
  101. $this->writeAmf3TypeMarker($data);
  102. break;
  103. default:
  104. require_once 'Zend/Amf/Exception.php';
  105. throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
  106. }
  107. }
  108. } else {
  109. if(is_resource($data)) {
  110. $data = Zend_Amf_Parse_TypeLoader::handleResource($data);
  111. }
  112. switch (true) {
  113. case (is_int($data) || is_float($data)):
  114. $markerType = Zend_Amf_Constants::AMF0_NUMBER;
  115. break;
  116. case (is_bool($data)):
  117. $markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
  118. break;
  119. case (is_string($data) && (strlen($data) > 65536)):
  120. $markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
  121. break;
  122. case (is_string($data)):
  123. $markerType = Zend_Amf_Constants::AMF0_STRING;
  124. break;
  125. case (is_object($data)):
  126. if (($data instanceof DateTime) || ($data instanceof Zend_Date)) {
  127. $markerType = Zend_Amf_Constants::AMF0_DATE;
  128. } else {
  129. if($className = $this->getClassName($data)){
  130. //Object is a Typed object set classname
  131. $markerType = Zend_Amf_Constants::AMF0_TYPEDOBJECT;
  132. $this->_className = $className;
  133. } else {
  134. // Object is a generic classname
  135. $markerType = Zend_Amf_Constants::AMF0_OBJECT;
  136. }
  137. break;
  138. }
  139. break;
  140. case (null === $data):
  141. $markerType = Zend_Amf_Constants::AMF0_NULL;
  142. break;
  143. case (is_array($data)):
  144. // check if it is an associative array
  145. $i = 0;
  146. foreach (array_keys($data) as $key) {
  147. // check if it contains non-integer keys
  148. if (!is_numeric($key) || intval($key) != $key) {
  149. $markerType = Zend_Amf_Constants::AMF0_OBJECT;
  150. break;
  151. // check if it is a sparse indexed array
  152. } else if ($key != $i) {
  153. $markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
  154. break;
  155. }
  156. $i++;
  157. }
  158. // Dealing with a standard numeric array
  159. if(!$markerType){
  160. $markerType = Zend_Amf_Constants::AMF0_ARRAY;
  161. break;
  162. }
  163. break;
  164. default:
  165. require_once 'Zend/Amf/Exception.php';
  166. throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data));
  167. }
  168. $this->writeTypeMarker($data, $markerType);
  169. }
  170. return $this;
  171. }
  172. /**
  173. * Check if the given object is in the reference table, write the reference if it exists,
  174. * otherwise add the object to the reference table
  175. *
  176. * @param mixed $object object to check for reference
  177. * @param $markerType AMF type of the object to write
  178. * @return Boolean true, if the reference was written, false otherwise
  179. */
  180. protected function writeObjectReference($object, $markerType){
  181. if( $markerType == Zend_Amf_Constants::AMF0_OBJECT ||
  182. $markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY ||
  183. $markerType == Zend_Amf_Constants::AMF0_ARRAY ||
  184. $markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT ) {
  185. $ref = array_search($object, $this->_referenceObjects,true);
  186. //handle object reference
  187. if($ref !== false){
  188. $this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE);
  189. return true;
  190. }
  191. $this->_referenceObjects[] = $object;
  192. }
  193. return false;
  194. }
  195. /**
  196. * Write a php array with string or mixed keys.
  197. *
  198. * @param object $data
  199. * @return Zend_Amf_Parse_Amf0_Serializer
  200. */
  201. public function writeObject($object)
  202. {
  203. // Loop each element and write the name of the property.
  204. foreach ($object as $key => $value) {
  205. // skip variables starting with an _ provate transient
  206. if( $key[0] == "_") continue;
  207. $this->_stream->writeUTF($key);
  208. $this->writeTypeMarker($value);
  209. }
  210. // Write the end object flag
  211. $this->_stream->writeInt(0);
  212. $this->_stream->writeByte(Zend_Amf_Constants::AMF0_OBJECTTERM);
  213. return $this;
  214. }
  215. /**
  216. * Write a standard numeric array to the output stream. If a mixed array
  217. * is encountered call writeTypeMarker with mixed array.
  218. *
  219. * @param array $array
  220. * @return Zend_Amf_Parse_Amf0_Serializer
  221. */
  222. public function writeArray($array)
  223. {
  224. $length = count($array);
  225. if (!$length < 0) {
  226. // write the length of the array
  227. $this->_stream->writeLong(0);
  228. } else {
  229. // Write the length of the numberic array
  230. $this->_stream->writeLong($length);
  231. for ($i=0; $i<$length; $i++) {
  232. $value = isset($array[$i]) ? $array[$i] : null;
  233. $this->writeTypeMarker($value);
  234. }
  235. }
  236. return $this;
  237. }
  238. /**
  239. * Convert the DateTime into an AMF Date
  240. *
  241. * @param DateTime|Zend_Date $data
  242. * @return Zend_Amf_Parse_Amf0_Serializer
  243. */
  244. public function writeDate($data)
  245. {
  246. if ($data instanceof DateTime) {
  247. $dateString = $data->format('U');
  248. } elseif ($data instanceof Zend_Date) {
  249. $dateString = $data->toString('U');
  250. } else {
  251. require_once 'Zend/Amf/Exception.php';
  252. throw new Zend_Amf_Exception('Invalid date specified; must be a DateTime or Zend_Date object');
  253. }
  254. $dateString *= 1000;
  255. // Make the conversion and remove milliseconds.
  256. $this->_stream->writeDouble($dateString);
  257. // Flash does not respect timezone but requires it.
  258. $this->_stream->writeInt(0);
  259. return $this;
  260. }
  261. /**
  262. * Write a class mapped object to the output stream.
  263. *
  264. * @param object $data
  265. * @return Zend_Amf_Parse_Amf0_Serializer
  266. */
  267. public function writeTypedObject($data)
  268. {
  269. $this->_stream->writeUTF($this->_className);
  270. $this->writeObject($data);
  271. return $this;
  272. }
  273. /**
  274. * Encountered and AMF3 Type Marker use AMF3 serializer. Once AMF3 is
  275. * enountered it will not return to AMf0.
  276. *
  277. * @param string $data
  278. * @return Zend_Amf_Parse_Amf0_Serializer
  279. */
  280. public function writeAmf3TypeMarker($data)
  281. {
  282. require_once 'Zend/Amf/Parse/Amf3/Serializer.php';
  283. $serializer = new Zend_Amf_Parse_Amf3_Serializer($this->_stream);
  284. $serializer->writeTypeMarker($data);
  285. return $this;
  286. }
  287. /**
  288. * Find if the class name is a class mapped name and return the
  289. * respective classname if it is.
  290. *
  291. * @param object $object
  292. * @return false|string $className
  293. */
  294. protected function getClassName($object)
  295. {
  296. require_once 'Zend/Amf/Parse/TypeLoader.php';
  297. //Check to see if the object is a typed object and we need to change
  298. $className = '';
  299. switch (true) {
  300. // the return class mapped name back to actionscript class name.
  301. case Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)):
  302. $className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object));
  303. break;
  304. // Check to see if the user has defined an explicit Action Script type.
  305. case isset($object->_explicitType):
  306. $className = $object->_explicitType;
  307. break;
  308. // Check if user has defined a method for accessing the Action Script type
  309. case method_exists($object, 'getASClassName'):
  310. $className = $object->getASClassName();
  311. break;
  312. // No return class name is set make it a generic object
  313. case ($object instanceof stdClass):
  314. $className = '';
  315. break;
  316. // By default, use object's class name
  317. default:
  318. $className = get_class($object);
  319. break;
  320. }
  321. if(!$className == '') {
  322. return $className;
  323. } else {
  324. return false;
  325. }
  326. }
  327. }