Back to index

d-push  2.0
Public Member Functions | Public Attributes | Protected Attributes | Private Member Functions
Streamer Class Reference
Inheritance diagram for Streamer:
Inheritance graph
[legend]

List of all members.

Public Member Functions

 Streamer ($mapping)
 Constructor.
 Decode (&$decoder)
 Decodes the WBXML from a WBXMLdecoder until we reach the same depth level of WBXML.
 Encode (&$encoder)
 Encodes this object and any subobjects - output is ordered according to mapping.
 StripData ()
 Removes not necessary data from the object.
 serialize ()
 Method to serialize a Streamer and respective SyncObject.
 unserialize ($data)
 Method to unserialize a Streamer and respective SyncObject.
 parseDate ($ts)
 Transforms an AS timestamp into a unix timestamp.

Public Attributes

const STREAMER_VAR = 1
const STREAMER_ARRAY = 2
const STREAMER_TYPE = 3
const STREAMER_PROP = 4
const STREAMER_TYPE_DATE = 1
const STREAMER_TYPE_HEX = 2
const STREAMER_TYPE_DATE_DASHES = 3
const STREAMER_TYPE_STREAM = 4
const STREAMER_TYPE_IGNORE = 5
const STREAMER_TYPE_SEND_EMPTY = 6
const STREAMER_TYPE_NO_CONTAINER = 7
const STREAMER_TYPE_COMMA_SEPARATED = 8
const STREAMER_TYPE_SEMICOLON_SEPARATED = 9
 $flags
 $content

Protected Attributes

 $mapping

Private Member Functions

 formatDate ($ts, $type)
 
Private methods for conversion

Detailed Description

Definition at line 50 of file streamer.php.


Member Function Documentation

Streamer::Decode ( &$  decoder)

Decodes the WBXML from a WBXMLdecoder until we reach the same depth level of WBXML.

This means that if there are multiple objects at this level, then only the first is decoded SubOjects are auto-instantiated and decoded using the same functionality

Parameters:
WBXMLDecoder$decoderpublic

Definition at line 89 of file streamer.php.

                                      {
        while(1) {
            $entity = $decoder->getElement();

            if($entity[EN_TYPE] == EN_TYPE_STARTTAG) {
                if(! ($entity[EN_FLAGS] & EN_FLAGS_CONTENT)) {
                    $map = $this->mapping[$entity[EN_TAG]];
                    if (isset($map[self::STREAMER_ARRAY])) {
                        $this->$map[self::STREAMER_VAR] = array();
                    } else if(!isset($map[self::STREAMER_TYPE])) {
                        $this->$map[self::STREAMER_VAR] = "";
                    }
                    else if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE_DASHES ) {
                        $this->$map[self::STREAMER_VAR] = "";
                    }
                    else if ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEND_EMPTY)
                        $this->$map[self::STREAMER_VAR] = "";
                    else if (isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_SEND_EMPTY)
                        $this->$map[self::STREAMER_VAR] = "";
                    continue;
                }
                // Found a start tag
                if(!isset($this->mapping[$entity[EN_TAG]])) {
                    // This tag shouldn't be here, abort
                    ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("Tag '%s' unexpected in type XML type '%s'", $entity[EN_TAG], get_class($this)));
                    return false;
                }
                else {
                    $map = $this->mapping[$entity[EN_TAG]];

                    // Handle an array
                    if(isset($map[self::STREAMER_ARRAY])) {
                        while(1) {
                            //do not get start tag for an array without a container
                            if (!(isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER)) {
                                if(!$decoder->getElementStartTag($map[self::STREAMER_ARRAY]))
                                    break;
                            }
                            if(isset($map[self::STREAMER_TYPE])) {
                                $decoded = new $map[self::STREAMER_TYPE];

                                $decoded->Decode($decoder);
                            }
                            else {
                                $decoded = $decoder->getElementContent();
                            }

                            if(!isset($this->$map[self::STREAMER_VAR]))
                                $this->$map[self::STREAMER_VAR] = array($decoded);
                            else
                                array_push($this->$map[self::STREAMER_VAR], $decoded);

                            if(!$decoder->getElementEndTag()) //end tag of a container element
                                return false;

                            if (isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER) {
                                $e = $decoder->peek();
                                //go back to the initial while if another block of no container elements is found
                                if ($e[EN_TYPE] == EN_TYPE_STARTTAG) {
                                    continue 2;
                                }
                                //break on end tag because no container elements block end is reached
                                if ($e[EN_TYPE] == EN_TYPE_ENDTAG)
                                    break;
                                if (empty($e))
                                    break;
                            }
                        }
                        //do not get end tag for an array without a container
                        if (!(isset($map[self::STREAMER_PROP]) && $map[self::STREAMER_PROP] == self::STREAMER_TYPE_NO_CONTAINER)) {
                            if(!$decoder->getElementEndTag()) //end tag of container
                                return false;
                        }
                    }
                    else { // Handle single value
                        if(isset($map[self::STREAMER_TYPE])) {
                            // Complex type, decode recursively
                            if($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE_DASHES) {
                                $decoded = $this->parseDate($decoder->getElementContent());
                                if(!$decoder->getElementEndTag())
                                    return false;
                            }
                            else if($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_HEX) {
                                $decoded = hex2bin($decoder->getElementContent());
                                if(!$decoder->getElementEndTag())
                                    return false;
                            }
                            else if($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEND_EMPTY) {
                                $decoded = $decoder->getElementContent();
                                if(!$decoder->getElementEndTag())
                                    return false;
                            }
                            else {
                                $subdecoder = new $map[self::STREAMER_TYPE]();
                                if($subdecoder->Decode($decoder) === false)
                                    return false;

                                $decoded = $subdecoder;

                                if(!$decoder->getElementEndTag()) {
                                    ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("No end tag for '%s'", $entity[EN_TAG]));
                                    return false;
                                }
                            }
                        }
                        else {
                            // Simple type, just get content
                            $decoded = $decoder->getElementContent();

                            if($decoded === false) {
                                // the tag is declared to have content, but no content is available.
                                // set an empty content
                                $decoded = "";
                            }

                            if(!$decoder->getElementEndTag()) {
                                ZLog::Write(LOGLEVEL_WBXMLSTACK, sprintf("Unable to get end tag for '%s'", $entity[EN_TAG]));
                                return false;
                            }
                        }
                        // $decoded now contains data object (or string)
                        $this->$map[self::STREAMER_VAR] = $decoded;
                    }
                }
            }
            else if($entity[EN_TYPE] == EN_TYPE_ENDTAG) {
                $decoder->ungetElement($entity);
                break;
            }
            else {
                ZLog::Write(LOGLEVEL_WBXMLSTACK, "Unexpected content in type");
                break;
            }
        }
    }

Here is the call graph for this function:

Streamer::Encode ( &$  encoder)

Encodes this object and any subobjects - output is ordered according to mapping.

Parameters:
WBXMLEncoder$encoderpublic

Definition at line 232 of file streamer.php.

                                      {
        foreach($this->mapping as $tag => $map) {
            if(isset($this->$map[self::STREAMER_VAR])) {
                // Variable is available
                if(is_object($this->$map[self::STREAMER_VAR])) {
                    // Subobjects can do their own encoding
                    if ($this->$map[self::STREAMER_VAR] instanceof Streamer) {
                        $encoder->startTag($tag);
                        $this->$map[self::STREAMER_VAR]->Encode($encoder);
                        $encoder->endTag();
                    }
                    else
                        ZLog::Write(LOGLEVEL_ERROR, sprintf("Streamer->Encode(): parameter '%s' of object %s is not of type Streamer", $map[self::STREAMER_VAR], get_class($this)));
                }
                // Array of objects
                else if(isset($map[self::STREAMER_ARRAY])) {
                    if ((empty($this->$map[self::STREAMER_VAR]) && isset($map[self::STREAMER_TYPE]) && $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEND_EMPTY)
                    || (isset($map[self::STREAMER_PROP]) &&  isset($map[self::STREAMER_PROP]) == self::STREAMER_TYPE_SEND_EMPTY)) {
                        $encoder->startTag($tag, false, true);
                    }
                    else {
                        // Outputs array container (eg Attachments)
                        // Do not output start and end tag when type is STREAMER_TYPE_NO_CONTAINER
                        if (!isset($map[self::STREAMER_PROP]) || $map[self::STREAMER_PROP] != self::STREAMER_TYPE_NO_CONTAINER)
                            $encoder->startTag($tag);

                        foreach ($this->$map[self::STREAMER_VAR] as $element) {
                            if(is_object($element)) {
                                $encoder->startTag($map[self::STREAMER_ARRAY]); // Outputs object container (eg Attachment)
                                $element->Encode($encoder);
                                $encoder->endTag();
                            }
                            else {
                                if(strlen($element) == 0)
                                      // Do not output empty items. Not sure if we should output an empty tag with $encoder->startTag($map[self::STREAMER_ARRAY], false, true);
                                      ;
                                else {
                                    $encoder->startTag($map[self::STREAMER_ARRAY]);
                                    $encoder->content($element);
                                    $encoder->endTag();
                                }
                            }
                        }

                        if  (!isset($map[self::STREAMER_PROP]) || $map[self::STREAMER_PROP] != self::STREAMER_TYPE_NO_CONTAINER)
                            $encoder->endTag();
                    }
                }
                else {
                    if(isset($map[self::STREAMER_TYPE]) && $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_IGNORE) {
                        continue;
                    }

                    // Simple type
                    if(!isset($map[self::STREAMER_TYPE]) && strlen($this->$map[self::STREAMER_VAR]) == 0) {
                        if ((isset($map[self::STREAMER_TYPE]) && $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEND_EMPTY)
                        || (isset($map[self::STREAMER_PROP]) &&  isset($map[self::STREAMER_PROP]) == self::STREAMER_TYPE_SEND_EMPTY)) {
                            $encoder->startTag($tag, false, true);
                        }
                          // Do not output empty items. See above: $encoder->startTag($tag, false, true);
                        continue;
                    } else
                        $encoder->startTag($tag);

                    if(isset($map[self::STREAMER_TYPE]) && ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_DATE_DASHES)) {
                        if($this->$map[self::STREAMER_VAR] != 0) // don't output 1-1-1970
                            $encoder->content($this->formatDate($this->$map[self::STREAMER_VAR], $map[self::STREAMER_TYPE]));
                    }
                    else if(isset($map[self::STREAMER_TYPE]) && $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_HEX) {
                        $encoder->content(strtoupper(bin2hex($this->$map[self::STREAMER_VAR])));
                    }
                    else if(isset($map[self::STREAMER_TYPE]) && $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_STREAM) {
                        //encode stream with base64
                        //TODO stream chunked without loading the complete attachment into memory
                        $stream = $this->$map[self::STREAMER_VAR];
                        $base64filter = stream_filter_append($stream, 'convert.base64-encode');
                        $d = "";
                        while (!feof($stream)) {
                            $d .= fgets($stream, 4096);
                        }
                        $encoder->content($d);
                        stream_filter_remove($base64filter);
                    }
                    // implode comma or semicolon arrays into a string
                    else if(isset($map[self::STREAMER_TYPE]) && is_array($this->$map[self::STREAMER_VAR]) &&
                        ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_COMMA_SEPARATED || $map[self::STREAMER_TYPE] == self::STREAMER_TYPE_SEMICOLON_SEPARATED)) {
                        $glue = ($map[self::STREAMER_TYPE] == self::STREAMER_TYPE_COMMA_SEPARATED)?", ":"; ";
                        $encoder->content(implode($glue, $this->$map[self::STREAMER_VAR]));
                    }
                    else {
                        $encoder->content($this->$map[self::STREAMER_VAR]);
                    }
                    $encoder->endTag();
                }
            }
        }
        // Output our own content
        if(isset($this->content))
            $encoder->content($this->content);
    }

Here is the call graph for this function:

Streamer::formatDate ( ts,
type 
) [private]


Private methods for conversion

Formats a timestamp Oh yeah, this is beautiful. Exchange outputs date fields differently in calendar items and emails. We could just always send one or the other, but unfortunately nokia's 'Mail for exchange' depends on this quirk. So we have to send a different date type depending on where it's used. Sigh.

Parameters:
long$ts
int$typeprivate
Returns:
string

Definition at line 408 of file streamer.php.

                                            {
        if($type == self::STREAMER_TYPE_DATE)
            return gmstrftime("%Y%m%dT%H%M%SZ", $ts);
        else if($type == self::STREAMER_TYPE_DATE_DASHES)
            return gmstrftime("%Y-%m-%dT%H:%M:%S.000Z", $ts);
    }

Here is the caller graph for this function:

Transforms an AS timestamp into a unix timestamp.

Parameters:
string$tsprivate
Returns:
long

Definition at line 423 of file streamer.php.

                            {
        if(preg_match("/(\d{4})[^0-9]*(\d{2})[^0-9]*(\d{2})(T(\d{2})[^0-9]*(\d{2})[^0-9]*(\d{2})(.\d+)?Z){0,1}$/", $ts, $matches)) {
            if ($matches[1] >= 2038){
                $matches[1] = 2038;
                $matches[2] = 1;
                $matches[3] = 18;
                $matches[5] = $matches[6] = $matches[7] = 0;
            }

            if (!isset($matches[5])) $matches[5] = 0;
            if (!isset($matches[6])) $matches[6] = 0;
            if (!isset($matches[7])) $matches[7] = 0;

            return gmmktime($matches[5], $matches[6], $matches[7], $matches[2], $matches[3], $matches[1]);
        }
        return 0;
    }

Here is the caller graph for this function:

Method to serialize a Streamer and respective SyncObject.

public

Returns:
array

Definition at line 365 of file streamer.php.

                                {
        $values = array();
        foreach ($this->mapping as $k=>$v) {
            if (isset($this->$v[self::STREAMER_VAR]))
                $values[$v[self::STREAMER_VAR]] = serialize($this->$v[self::STREAMER_VAR]);
        }

        return serialize($values);
    }
Streamer::Streamer ( mapping)

Constructor.

Parameters:
array$mappinginternal mapping of variables public

Definition at line 75 of file streamer.php.

                                {
        $this->mapping = $mapping;
        $this->flags = false;
    }

Here is the caller graph for this function:

Removes not necessary data from the object.

public

Returns:
boolean

Definition at line 339 of file streamer.php.

                                {
        foreach ($this->mapping as $k=>$v) {
            if (isset($this->$v[self::STREAMER_VAR])) {
                if (is_object($this->$v[self::STREAMER_VAR]) && method_exists($this->$v[self::STREAMER_VAR], "StripData") ) {
                    $this->$v[self::STREAMER_VAR]->StripData();
                }
                else if (isset($v[self::STREAMER_ARRAY]) && !empty($this->$v[self::STREAMER_VAR])) {
                    foreach ($this->$v[self::STREAMER_VAR] as $element) {
                        if (is_object($element) && method_exists($element, "StripData") ) {
                            $element->StripData();
                        }
                    }
                }
            }
        }
        unset($this->mapping);

        return true;
    }
Streamer::unserialize ( data)

Method to unserialize a Streamer and respective SyncObject.

public

Returns:
array

Definition at line 381 of file streamer.php.

                                       {
        $class = get_class($this);
        $this->$class();
        $values = unserialize($data);
        foreach ($values as $k=>$v)
            $this->$k = unserialize($v);

        return true;
    }

Member Data Documentation

Definition at line 67 of file streamer.php.

Definition at line 66 of file streamer.php.

Streamer::$mapping [protected]

Definition at line 65 of file streamer.php.

Definition at line 52 of file streamer.php.

Definition at line 54 of file streamer.php.

Definition at line 53 of file streamer.php.

Definition at line 62 of file streamer.php.

Definition at line 55 of file streamer.php.

Definition at line 57 of file streamer.php.

Definition at line 56 of file streamer.php.

Definition at line 59 of file streamer.php.

Definition at line 61 of file streamer.php.

Definition at line 63 of file streamer.php.

Definition at line 60 of file streamer.php.

Definition at line 58 of file streamer.php.

Definition at line 51 of file streamer.php.


The documentation for this class was generated from the following file: