Source of file Message.php

Size: 9,251 Bytes - Last Modified: 2015-02-02T11:34:19+02:00

/Users/mcfedr/dev/awspushbundle/src/Mcfedr/AwsPushBundle/Message/Message.php

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
<?php

namespace Mcfedr\AwsPushBundle\Message;

use Mcfedr\AwsPushBundle\Exception\MessageTooLongException;

class Message implements \JsonSerializable
{
    const GCM_NO_COLLAPSE = 'do_not_collapse';
    const APNS_MAX_LENGTH = 2048;
    const GCM_MAX_LENGTH = 4096;

    /**
     * The text is automatically trimmed when sending to APNS
     * The text will only be sent to GCM and ADM if no platform specific data is set
     *
     * @var string
     */
    private $text;

    /**
     * APNS only
     *
     * @var int
     */
    private $badge;

    /**
     * APNS only
     * Provide this key with a value of 1 to indicate that new content is available. Including this key and value means that when your app is launched in the background or resumed
     *
     * @var bool
     */
    private $contentAvailable;

    /**
     * APNS only
     *
     * @var string
     */
    private $sound;

    /**
     * This is the data to send to all services, it will be deep merged with the other data
     *
     * @var array
     */
    private $custom = [];

    /**
     * If set, will be sent to GCM, otherwise ['message' => $text] will be sent as part of the data
     *
     * @var array
     */
    private $gcmData;

    /**
     * If set, will be sent to ADM, otherwise ['message' => $text] will be sent as part of the data
     *
     * @var array
     */
    private $admData;

    /**
     * If set, will be sent to APNS
     *
     * @var array
     */
    private $apnsData;

    /**
     * GCM and ADM only
     *
     * @var string
     */
    private $collapseKey = self::GCM_NO_COLLAPSE;

    /**
     * GCM only
     *
     * @var int
     */
    private $ttl;

    /**
     * GCM only
     *
     * @var boolean
     */
    private $delayWhileIdle = false;

    /**
     * @param string $text
     */
    public function __construct($text = null)
    {
        $this->text = $text;
    }

    /**
     * @param int $badge
     */
    public function setBadge($badge)
    {
        $this->badge = $badge;
    }

    /**
     * @return int
     */
    public function getBadge()
    {
        return $this->badge;
    }

    /**
     * @return boolean
     */
    public function isContentAvailable()
    {
        return $this->contentAvailable;
    }

    /**
     * @param boolean $contentAvailable
     */
    public function setContentAvailable($contentAvailable)
    {
        $this->contentAvailable = $contentAvailable;
    }

    /**
     * @param array $custom
     */
    public function setCustom($custom)
    {
        $this->custom = $custom;
    }

    /**
     * @return array
     */
    public function getCustom()
    {
        return $this->custom;
    }

    /**
     * @param string $sound
     */
    public function setSound($sound)
    {
        $this->sound = $sound;
    }

    /**
     * @return string
     */
    public function getSound()
    {
        return $this->sound;
    }

    /**
     * @param string $text
     */
    public function setText($text)
    {
        $this->text = $text;
    }

    /**
     * @return string
     */
    public function getText()
    {
        return $this->text;
    }

    /**
     * @param string $collapseKey
     */
    public function setCollapseKey($collapseKey)
    {
        $this->collapseKey = $collapseKey;
    }

    /**
     * @return string
     */
    public function getCollapseKey()
    {
        return $this->collapseKey;
    }

    /**
     * @param boolean $delayWhileIdle
     */
    public function setDelayWhileIdle($delayWhileIdle)
    {
        $this->delayWhileIdle = $delayWhileIdle;
    }

    /**
     * @return boolean
     */
    public function getDelayWhileIdle()
    {
        return $this->delayWhileIdle;
    }

    /**
     * @param int $ttl
     */
    public function setTtl($ttl)
    {
        $this->ttl = $ttl;
    }

    /**
     * @return int
     */
    public function getTtl()
    {
        return $this->ttl;
    }

    /**
     * @param array $gcmData
     */
    public function setGcmData($gcmData)
    {
        $this->gcmData = $gcmData;
    }

    /**
     * @return array
     */
    public function getGcmData()
    {
        return $this->gcmData;
    }

    /**
     * @param array $admData
     * @return Message
     */
    public function setAdmData($admData)
    {
        $this->admData = $admData;
        return $this;
    }

    /**
     * @return array
     */
    public function getAdmData()
    {
        return $this->admData;
    }

    /**
     * @param array $apnsData
     * @return Message
     */
    public function setApnsData($apnsData)
    {
        $this->apnsData = $apnsData;
        return $this;
    }

    /**
     * @return array
     */
    public function getApnsData()
    {
        return $this->apnsData;
    }

    public function jsonSerialize()
    {
        $apnsData = $this->getApnsJson($this->text);
        if (($apnsDataLength = strlen($apnsData)) > static::APNS_MAX_LENGTH) {
            $cut = $apnsDataLength - static::APNS_MAX_LENGTH;
            //Note that strlen returns the byte length of the string
            $textLength = strlen($this->text);
            if ($textLength > $cut) {
                $apnsData = $this->getApnsJson(mb_strcut($this->text, 0, $textLength - $cut - 3, 'utf8') . '...');
            } else {
                throw new MessageTooLongException("You message for APNS is too long $apnsData");
            }
        }

        $gcmData = $this->getGcmJson($this->text);
        if (($gcmDataLength = strlen($gcmData)) > static::GCM_MAX_LENGTH) {
            $cut = $gcmDataLength - static::GCM_MAX_LENGTH;
            //Note that strlen returns the byte length of the string
            $textLength = strlen($this->text);
            if ($textLength > $cut) {
                $gcmData = $this->getGcmJson(mb_strcut($this->text, 0, $textLength - $cut - 3, 'utf8') . '...');
            } else {
                throw new MessageTooLongException("You message for GCM is too long $gcmData");
            }
        }

        return [
            'default' => $this->text,
            'APNS' => $apnsData,
            'APNS_SANDBOX' => $apnsData,
            'ADM' => $this->getAdmJson(),
            'GCM' => $gcmData
        ];
    }

    public function __toString()
    {
        return json_encode($this);
    }

    /**
     * Get the correct apple push notification server json
     *
     * @param string $text
     * @return string
     */
    private function getApnsJson($text)
    {
        $apns = [
            'aps' => []
        ];

        if (!is_null($text)) {
            $apns['aps']['alert'] = $text;
        }

        if ($this->isContentAvailable()) {
            $apns['aps']['content-available'] = 1;
        }

        if (!is_null($this->badge)) {
            $apns['aps']['badge'] = $this->badge;
        }

        if (!is_null($this->sound)) {
            $apns['aps']['sound'] = $this->sound;
        }

        return json_encode(
            $this->arrayMergeDeep($apns, $this->custom, $this->apnsData ? $this->apnsData : []),
            JSON_UNESCAPED_UNICODE
        );
    }

    /**
     * Get the json to send via Amazon Device Messaging
     *
     * @return string
     */
    private function getAdmJson()
    {
        $adm = [
            'data' => $this->arrayMergeDeep($this->admData ? $this->admData : ['message' => $this->text], $this->custom)
        ];

        if ($this->collapseKey != static::GCM_NO_COLLAPSE) {
            $adm['consolidationKey'] = $this->collapseKey;
        }

        return json_encode($adm, JSON_UNESCAPED_UNICODE);
    }

    /**
     * Get the json to send via Google Cloud Messaging
     *
     * @param string $text
     * @return string
     */
    private function getGcmJson($text)
    {
        return json_encode(
            [
                'collapse_key' => $this->collapseKey,
                'time_to_live' => $this->ttl,
                'delay_while_idle' => $this->delayWhileIdle,
                'data' => $this->arrayMergeDeep($this->gcmData ? $this->gcmData : ['message' => $text], $this->custom)
            ],
            JSON_UNESCAPED_UNICODE
        );
    }

    /**
     * Merge arrays, deeply
     *
     * @param array $array1
     * @param array $array2
     * @return array
     */
    private function arrayMergeDeep($array1, $array2)
    {
        $result = [];
        foreach (func_get_args() as $array) {
            foreach ($array as $key => $value) {
                // Renumber integer keys as array_merge_recursive() does. Note that PHP
                // automatically converts array keys that are integer strings (e.g., '1')
                // to integers.
                if (is_integer($key)) {
                    $result[] = $value;
                } elseif (isset($result[$key]) && is_array($result[$key]) && is_array($value)) {
                    // Recurse when both values are arrays.
                    $result[$key] = $this->arrayMergeDeep($result[$key], $value);
                } else {
                    // Otherwise, use the latter value, overriding any previous value.
                    $result[$key] = $value;
                }
            }
        }
        return $result;
    }
}