<?php
require_once 'Zend/Amf/Parse/Serializer.php';
class Zend_Amf_Parse_Amf0_Serializer extends Zend_Amf_Parse_Serializer
{
protected $_className = '';
protected $_referenceObjects = array();
public function writeTypeMarker($data, $markerType = null)
{
if (null !== $markerType) {
if( !$this->writeObjectReference($data, $markerType) ) {
$this->_stream->writeByte($markerType);
switch($markerType) {
case Zend_Amf_Constants::AMF0_NUMBER:
$this->_stream->writeDouble($data);
break;
case Zend_Amf_Constants::AMF0_BOOLEAN:
$this->_stream->writeByte($data);
break;
case Zend_Amf_Constants::AMF0_STRING:
$this->_stream->writeUTF($data);
break;
case Zend_Amf_Constants::AMF0_OBJECT:
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_NULL:
break;
case Zend_Amf_Constants::AMF0_REFERENCE:
$this->_stream->writeInt($data);
break;
case Zend_Amf_Constants::AMF0_MIXEDARRAY:
$this->_stream->writeLong(0);
$this->writeObject($data);
break;
case Zend_Amf_Constants::AMF0_ARRAY:
$this->writeArray($data);
break;
case Zend_Amf_Constants::AMF0_DATE:
$this->writeDate($data);
break;
case Zend_Amf_Constants::AMF0_LONGSTRING:
$this->_stream->writeLongUTF($data);
break;
case Zend_Amf_Constants::AMF0_TYPEDOBJECT:
$this->writeTypedObject($data);
break;
case Zend_Amf_Constants::AMF0_AMF3:
$this->writeAmf3TypeMarker($data);
break;
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception("Unknown Type Marker: " . $markerType);
}
}
} else {
if(is_resource($data)) {
$data = Zend_Amf_Parse_TypeLoader::handleResource($data);
}
switch (true) {
case (is_int($data) || is_float($data)):
$markerType = Zend_Amf_Constants::AMF0_NUMBER;
break;
case (is_bool($data)):
$markerType = Zend_Amf_Constants::AMF0_BOOLEAN;
break;
case (is_string($data) && (strlen($data) > 65536)):
$markerType = Zend_Amf_Constants::AMF0_LONGSTRING;
break;
case (is_string($data)):
$markerType = Zend_Amf_Constants::AMF0_STRING;
break;
case (is_object($data)):
if (($data instanceof DateTime) || ($data instanceof Zend_Date)) {
$markerType = Zend_Amf_Constants::AMF0_DATE;
} else {
if($className = $this->getClassName($data)){
$markerType = Zend_Amf_Constants::AMF0_TYPEDOBJECT;
$this->_className = $className;
} else {
$markerType = Zend_Amf_Constants::AMF0_OBJECT;
}
break;
}
break;
case (null === $data):
$markerType = Zend_Amf_Constants::AMF0_NULL;
break;
case (is_array($data)):
$i = 0;
foreach (array_keys($data) as $key) {
if (!is_numeric($key) || intval($key) != $key) {
$markerType = Zend_Amf_Constants::AMF0_OBJECT;
break;
} else if ($key != $i) {
$markerType = Zend_Amf_Constants::AMF0_MIXEDARRAY;
break;
}
$i++;
}
if(!$markerType){
$markerType = Zend_Amf_Constants::AMF0_ARRAY;
break;
}
break;
default:
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Unsupported data type: ' . gettype($data));
}
$this->writeTypeMarker($data, $markerType);
}
return $this;
}
protected function writeObjectReference($object, $markerType){
if( $markerType == Zend_Amf_Constants::AMF0_OBJECT ||
$markerType == Zend_Amf_Constants::AMF0_MIXEDARRAY ||
$markerType == Zend_Amf_Constants::AMF0_ARRAY ||
$markerType == Zend_Amf_Constants::AMF0_TYPEDOBJECT ) {
$ref = array_search($object, $this->_referenceObjects,true);
if($ref !== false){
$this->writeTypeMarker($ref,Zend_Amf_Constants::AMF0_REFERENCE);
return true;
}
$this->_referenceObjects[] = $object;
}
return false;
}
public function writeObject($object)
{
foreach ($object as $key => $value) {
if( $key[0] == "_") continue;
$this->_stream->writeUTF($key);
$this->writeTypeMarker($value);
}
$this->_stream->writeInt(0);
$this->_stream->writeByte(Zend_Amf_Constants::AMF0_OBJECTTERM);
return $this;
}
public function writeArray($array)
{
$length = count($array);
if (!$length < 0) {
$this->_stream->writeLong(0);
} else {
$this->_stream->writeLong($length);
for ($i=0; $i<$length; $i++) {
$value = isset($array[$i]) ? $array[$i] : null;
$this->writeTypeMarker($value);
}
}
return $this;
}
public function writeDate($data)
{
if ($data instanceof DateTime) {
$dateString = $data->format('U');
} elseif ($data instanceof Zend_Date) {
$dateString = $data->toString('U');
} else {
require_once 'Zend/Amf/Exception.php';
throw new Zend_Amf_Exception('Invalid date specified; must be a DateTime or Zend_Date object');
}
$dateString *= 1000;
$this->_stream->writeDouble($dateString);
$this->_stream->writeInt(0);
return $this;
}
public function writeTypedObject($data)
{
$this->_stream->writeUTF($this->_className);
$this->writeObject($data);
return $this;
}
public function writeAmf3TypeMarker($data)
{
require_once 'Zend/Amf/Parse/Amf3/Serializer.php';
$serializer = new Zend_Amf_Parse_Amf3_Serializer($this->_stream);
$serializer->writeTypeMarker($data);
return $this;
}
protected function getClassName($object)
{
require_once 'Zend/Amf/Parse/TypeLoader.php';
$className = '';
switch (true) {
case Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object)):
$className = Zend_Amf_Parse_TypeLoader::getMappedClassName(get_class($object));
break;
case isset($object->_explicitType):
$className = $object->_explicitType;
break;
case method_exists($object, 'getASClassName'):
$className = $object->getASClassName();
break;
case ($object instanceof stdClass):
$className = '';
break;
default:
$className = get_class($object);
break;
}
if(!$className == '') {
return $className;
} else {
return false;
}
}
}