update v1.0.7.9 R.C.

This is a Release Candidate. We are still testing.
This commit is contained in:
Sujit Prasad
2016-08-03 20:04:36 +05:30
parent 8b6b924d09
commit ffa56a43cb
3830 changed files with 181529 additions and 495353 deletions

View File

@@ -0,0 +1,54 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Adapter;
use Sly\NotificationPusher\Model\PushInterface;
/**
* AdapterInterface.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
interface AdapterInterface
{
/**
* Push.
*
* @param \Sly\NotificationPusher\Model\PushInterface $push Push
*
* @return \Sly\NotificationPusher\Collection\DeviceCollection
*/
public function push(PushInterface $push);
/**
* Supports.
*
* @param string $token Token
*
* @return boolean
*/
public function supports($token);
/**
* Get default parameters.
*
* @return array
*/
public function getDefaultParameters();
/**
* Get required parameters.
*
* @return array
*/
public function getRequiredParameters();
}

View File

@@ -0,0 +1,196 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Adapter;
use Sly\NotificationPusher\Model\PushInterface;
use Sly\NotificationPusher\Model\MessageInterface;
use Sly\NotificationPusher\Model\DeviceInterface;
use Sly\NotificationPusher\Exception\AdapterException;
use Sly\NotificationPusher\Exception\PushException;
use Sly\NotificationPusher\Collection\DeviceCollection;
use ZendService\Apple\Apns\Client\AbstractClient as ServiceAbstractClient;
use ZendService\Apple\Apns\Client\Message as ServiceClient;
use ZendService\Apple\Apns\Message as ServiceMessage;
use ZendService\Apple\Apns\Message\Alert as ServiceAlert;
use ZendService\Apple\Apns\Response\Message as ServiceResponse;
use ZendService\Apple\Apns\Exception\RuntimeException as ServiceRuntimeException;
use ZendService\Apple\Apns\Client\Feedback as ServiceFeedbackClient;
/**
* APNS adapter.
*
* @uses \Sly\NotificationPusher\Adapter\BaseAdapter
* @uses \Sly\NotificationPusher\Adapter\AdapterInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class Apns extends BaseAdapter implements AdapterInterface
{
/**
* {@inheritdoc}
*
* @throws \Sly\NotificationPusher\Exception\AdapterException
*/
public function __construct(array $parameters = array())
{
parent::__construct($parameters);
$cert = $this->getParameter('certificate');
if (false === file_exists($cert)) {
throw new AdapterException(sprintf('Certificate %s does not exist', $cert));
}
}
/**
* {@inheritdoc}
*
* @throws \Sly\NotificationPusher\Exception\PushException
*/
public function push(PushInterface $push)
{
$client = $this->getOpenedClient(new ServiceClient());
$pushedDevices = new DeviceCollection();
foreach ($push->getDevices() as $device) {
$message = $this->getServiceMessageFromOrigin($device, $push->getMessage());
try {
$this->response = $client->send($message);
} catch (ServiceRuntimeException $e) {
throw new PushException($e->getMessage());
}
if (ServiceResponse::RESULT_OK === $this->response->getCode()) {
$pushedDevices->add($device);
}
}
$client->close();
return $pushedDevices;
}
/**
* Feedback.
*
* @return array
*/
public function getFeedback()
{
$client = $this->getOpenedClient(new ServiceFeedbackClient());
$responses = array();
$serviceResponses = $client->feedback();
$client->close();
foreach ($serviceResponses as $response) {
$responses[$response->getToken()] = new \DateTime(date("c", $response->getTime()));
}
return $responses;
}
/**
* Get opened client.
*
* @param \ZendService\Apple\Apns\Client\AbstractClient $client Client
*
* @return \ZendService\Apple\Apns\Client\AbstractClient
*/
public function getOpenedClient(ServiceAbstractClient $client)
{
$client->open(
$this->isProductionEnvironment() ? ServiceClient::PRODUCTION_URI : ServiceClient::SANDBOX_URI,
$this->getParameter('certificate'),
$this->getParameter('passPhrase')
);
return $client;
}
/**
* Get service message from origin.
*
* @param \Sly\NotificationPusher\Model\DeviceInterface $device Device
* @param \Sly\NotificationPusher\Model\MessageInterface $message Message
*
* @return \ZendService\Apple\Apns\Message
*/
public function getServiceMessageFromOrigin(DeviceInterface $device, MessageInterface $message)
{
$badge = ($message->hasOption('badge'))
? (int) ($message->getOption('badge') + $device->getParameter('badge', 0))
: 0
;
$sound = $message->getOption('sound', 'bingbong.aiff');
$alert = new ServiceAlert(
$message->getText(),
$message->getOption('actionLocKey'),
$message->getOption('locKey'),
$message->getOption('locArgs'),
$message->getOption('launchImage')
);
if ($actionLocKey = $message->getOption('actionLocKey')) {
$alert->setActionLocKey($actionLocKey);
}
if ($locKey = $message->getOption('locKey')) {
$alert->setLocKey($locKey);
}
if ($locArgs = $message->getOption('locArgs')) {
$alert->setLocArgs($locArgs);
}
if ($launchImage = $message->getOption('launchImage')) {
$alert->setLaunchImage($launchImage);
}
$serviceMessage = new ServiceMessage();
$serviceMessage->setId(sha1($device->getToken().$message->getText()));
$serviceMessage->setAlert($alert);
$serviceMessage->setToken($device->getToken());
$serviceMessage->setBadge($badge);
$serviceMessage->setCustom($message->getOption('custom', array()));
if (null !== $sound) {
$serviceMessage->setSound($sound);
}
return $serviceMessage;
}
/**
* {@inheritdoc}
*/
public function supports($token)
{
return (ctype_xdigit($token) && 64 == strlen($token));
}
/**
* {@inheritdoc}
*/
public function getDefaultParameters()
{
return array('passPhrase' => null);
}
/**
* {@inheritdoc}
*/
public function getRequiredParameters()
{
return array('certificate');
}
}

View File

@@ -0,0 +1,130 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Adapter;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Sly\NotificationPusher\Model\BaseParameteredModel;
use Sly\NotificationPusher\PushManager;
/**
* BaseAdapter.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
abstract class BaseAdapter extends BaseParameteredModel
{
/**
* @var string
*/
protected $adapterKey;
/**
* @var string
*/
protected $environment;
/**
* @var mixed
*/
protected $response;
/**
* Constructor.
*
* @param array $parameters Adapter specific parameters
*/
public function __construct(array $parameters = array())
{
$resolver = new OptionsResolver();
$resolver->setDefaults($this->getDefaultParameters());
$resolver->setRequired($this->getRequiredParameters());
$reflectedClass = new \ReflectionClass($this);
$this->adapterKey = lcfirst($reflectedClass->getShortName());
$this->parameters = $resolver->resolve($parameters);
}
/**
* __toString.
*
* @return string
*/
public function __toString()
{
return ucfirst($this->getAdapterKey());
}
/**
* Return the original response.
*
* @return mixed
*/
public function getResponse()
{
return $this->response;
}
/**
* Get AdapterKey.
*
* @return string
*/
public function getAdapterKey()
{
return $this->adapterKey;
}
/**
* Get Environment.
*
* @return string
*/
public function getEnvironment()
{
return $this->environment;
}
/**
* Set Environment.
*
* @param string $environment Environment value to set
*
* @return \Sly\NotificationPusher\Adapter\AdapterInterface
*/
public function setEnvironment($environment)
{
$this->environment = $environment;
return $this;
}
/**
* isDevelopmentEnvironment.
*
* @return boolean
*/
public function isDevelopmentEnvironment()
{
return (PushManager::ENVIRONMENT_DEV === $this->getEnvironment());
}
/**
* isProductionEnvironment.
*
* @return boolean
*/
public function isProductionEnvironment()
{
return (PushManager::ENVIRONMENT_PROD === $this->getEnvironment());
}
}

View File

@@ -0,0 +1,181 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Adapter;
use Sly\NotificationPusher\Model\PushInterface;
use Sly\NotificationPusher\Model\MessageInterface;
use Sly\NotificationPusher\Collection\DeviceCollection;
use Sly\NotificationPusher\Exception\PushException;
use Zend\Http\Client as HttpClient;
use Zend\Http\Client\Adapter\Socket as HttpSocketAdapter;
use ZendService\Google\Gcm\Client as ServiceClient;
use ZendService\Google\Gcm\Message as ServiceMessage;
use ZendService\Google\Exception\RuntimeException as ServiceRuntimeException;
use InvalidArgumentException;
/**
* GCM adapter.
*
* @uses \Sly\NotificationPusher\Adapter\BaseAdapter
* @uses \Sly\NotificationPusher\Adapter\AdapterInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class Gcm extends BaseAdapter implements AdapterInterface
{
/**
* @var \Zend\Http\Client
*/
private $httpClient;
/**
* {@inheritdoc}
*/
public function supports($token)
{
return (bool) preg_match('/[0-9a-zA-Z\-\_]/i', $token);
}
/**
* {@inheritdoc}
*
* @throws \Sly\NotificationPusher\Exception\PushException
*/
public function push(PushInterface $push)
{
$client = $this->getOpenedClient(new ServiceClient());
$pushedDevices = new DeviceCollection();
$tokens = array_chunk($push->getDevices()->getTokens(), 100);
foreach ($tokens as $tokensRange) {
$message = $this->getServiceMessageFromOrigin($tokensRange, $push->getMessage());
try {
$this->response = $client->send($message);
} catch (ServiceRuntimeException $e) {
throw new PushException($e->getMessage());
}
if ((bool) $this->response->getSuccessCount()) {
foreach ($tokensRange as $token) {
$pushedDevices->add($push->getDevices()->get($token));
}
}
}
return $pushedDevices;
}
/**
* Get opened client.
*
* @param \ZendService\Google\Gcm\Client $client Client
*
* @return \ZendService\Google\Gcm\Client
*/
public function getOpenedClient(ServiceClient $client)
{
$client->setApiKey($this->getParameter('apiKey'));
if ($this->httpClient !== null) {
$client->setHttpClient($this->httpClient);
}
return $client;
}
/**
* Get service message from origin.
*
* @param array $tokens Tokens
* @param \Sly\NotificationPusher\Model\MessageInterface $message Message
*
* @return \ZendService\Google\Gcm\Message
*/
public function getServiceMessageFromOrigin(array $tokens, MessageInterface $message)
{
$data = $message->getOptions();
$data['message'] = $message->getText();
$serviceMessage = new ServiceMessage();
$serviceMessage->setRegistrationIds($tokens);
$serviceMessage->setData($data);
$serviceMessage->setCollapseKey($this->getParameter('collapseKey'));
$serviceMessage->setRestrictedPackageName($this->getParameter('restrictedPackageName'));
$serviceMessage->setDelayWhileIdle($this->getParameter('delayWhileIdle', false));
$serviceMessage->setTimeToLive($this->getParameter('ttl', 600));
$serviceMessage->setDryRun($this->getParameter('dryRun', false));
return $serviceMessage;
}
/**
* {@inheritdoc}
*/
public function getDefaultParameters()
{
return array();
}
/**
* {@inheritdoc}
*/
public function getRequiredParameters()
{
return array('apiKey');
}
/**
* Get the current Zend Http Client instance.
*
* @return HttpClient
*/
public function getHttpClient()
{
return $this->httpClient;
}
/**
* Overrides the default Http Client.
*
* @param HttpClient $client
*/
public function setHttpClient(HttpClient $client)
{
$this->httpClient = $client;
}
/**
* Send custom parameters to the Http Adapter without overriding the Http Client.
*
* @param array $config
*
* @throws \InvalidArgumentException
*/
public function setAdapterParameters(array $config = array())
{
if (!is_array($config) || empty($config)) {
throw new InvalidArgumentException('$config must be an associative array with at least 1 item.');
}
if ($this->httpClient === null) {
$this->httpClient = new HttpClient();
$this->httpClient->setAdapter(new HttpSocketAdapter());
}
$this->httpClient->getAdapter()->setOptions($config);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Collection;
/**
* AbstractCollection.
*
* @uses \IteratorAggregate
* @author Cédric Dugat <cedric@dugat.me>
*/
abstract class AbstractCollection
{
/**
* @var \ArrayIterator
*/
protected $coll;
/**
* Get.
*
* @param string $key Key
*
* @return \Sly\NotificationPusher\Model\MessageInterface|false
*/
public function get($key)
{
return isset($this->coll[$key]) ? $this->coll[$key] : false;
}
/**
* Count.
*
* @return integer
*/
public function count()
{
return count($this->getIterator());
}
/**
* isEmpty.
*
* @return boolean
*/
public function isEmpty()
{
return (bool) $this->count();
}
/**
* Clear categories.
*/
public function clear()
{
$this->coll = new \ArrayIterator();
}
}

View File

@@ -0,0 +1,70 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Collection;
use Sly\NotificationPusher\Model\DeviceInterface;
/**
* DeviceCollection.
*
* @uses \Sly\NotificationPusher\Collection\AbstractCollection
* @uses \IteratorAggregate
* @author Cédric Dugat <cedric@dugat.me>
*/
class DeviceCollection extends AbstractCollection implements \IteratorAggregate
{
/**
* Constructor.
*
* @param array $devices Devices
*/
public function __construct(array $devices = array())
{
$this->coll = new \ArrayIterator();
foreach ($devices as $device) {
$this->add($device);
}
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return $this->coll;
}
/**
* @param \Sly\NotificationPusher\Model\DeviceInterface $device Device
*/
public function add(DeviceInterface $device)
{
$this->coll[$device->getToken()] = $device;
}
/**
* Get tokens.
*
* @return array
*/
public function getTokens()
{
$tokens = array();
foreach ($this as $token => $device) {
$tokens[] = $token;
}
return array_unique(array_filter($tokens));
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Collection;
use Sly\NotificationPusher\Model\MessageInterface;
/**
* MessageCollection.
*
* @uses \Sly\NotificationPusher\Collection\AbstractCollection
* @uses \IteratorAggregate
* @author Cédric Dugat <cedric@dugat.me>
*/
class MessageCollection extends AbstractCollection implements \IteratorAggregate
{
/**
* Constructor.
*/
public function __construct()
{
$this->coll = new \ArrayIterator();
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return $this->coll;
}
/**
* @param \Sly\NotificationPusher\Model\MessageInterface $message Message
*/
public function add(MessageInterface $message)
{
$this->coll[] = $message;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Collection;
use Sly\NotificationPusher\Model\PushInterface;
/**
* PushCollection.
*
* @uses \Sly\NotificationPusher\Collection\AbstractCollection
* @uses \IteratorAggregate
* @author Cédric Dugat <cedric@dugat.me>
*/
class PushCollection extends AbstractCollection implements \IteratorAggregate
{
/**
* Constructor.
*/
public function __construct()
{
$this->coll = new \ArrayIterator();
}
/**
* @return \ArrayIterator
*/
public function getIterator()
{
return $this->coll;
}
/**
* @param \Sly\NotificationPusher\Model\PushInterface $push Push
*/
public function add(PushInterface $push)
{
$this->coll[] = $push;
}
}

View File

@@ -0,0 +1,37 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Console;
use Symfony\Component\Console\Application as BaseApplication;
use Sly\NotificationPusher\NotificationPusher;
use Sly\NotificationPusher\Console\Command\PushCommand;
/**
* Application.
*
* @uses \Symfony\Component\Console\Application
* @author Cédric Dugat <cedric@dugat.me>
*/
class Application extends BaseApplication
{
/**
* Constructor.
*/
public function __construct()
{
error_reporting(-1);
parent::__construct('NotificationPusher version', NotificationPusher::VERSION);
$this->add(new PushCommand());
}
}

View File

@@ -0,0 +1,160 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Console\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Sly\NotificationPusher\PushManager;
use Sly\NotificationPusher\Model\Device;
use Sly\NotificationPusher\Model\Message;
use Sly\NotificationPusher\Model\Push;
use Sly\NotificationPusher\Exception\AdapterException;
use Doctrine\Common\Util\Inflector;
/**
* PushCommand.
*
* @uses \Symfony\Component\Console\Command\Command
* @author Cédric Dugat <cedric@dugat.me>
*/
class PushCommand extends Command
{
/**
* @see Command
*/
protected function configure()
{
parent::configure();
$this
->setName('push')
->setDescription('Manual notification push')
->addArgument(
'adapter',
InputArgument::REQUIRED,
'Adapter (apns, gcm, specific class name, ...)'
)
->addArgument(
'token',
InputArgument::REQUIRED,
'Device Token or Registration ID'
)
->addArgument(
'message',
InputArgument::REQUIRED,
'Message'
)
->addOption(
'certificate',
null,
InputOption::VALUE_OPTIONAL,
'Certificate path (for APNS adapter)'
)
->addOption(
'api-key',
null,
InputOption::VALUE_OPTIONAL,
'API key (for GCM adapter)'
)
->addOption(
'env',
PushManager::ENVIRONMENT_DEV,
InputOption::VALUE_OPTIONAL,
sprintf(
'Environment (%s, %s)',
PushManager::ENVIRONMENT_DEV,
PushManager::ENVIRONMENT_PROD
)
);
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$adapter = $this->getReadyAdapter($input, $output);
$pushManager = new PushManager($input->getOption('env'));
$message = new Message('This is an example.');
$push = new Push($adapter, new Device($input->getArgument('token')), $message);
$pushManager->add($push);
$pushManager->push();
}
/**
* Get adapter class from argument.
*
* @param string $argument Given argument
*
* @return string
*
* @throws AdapterException When given adapter class doesn't exist
*/
private function getAdapterClassFromArgument($argument)
{
if (!class_exists($adapterClass = $argument) &&
!class_exists($adapterClass = '\\Sly\\NotificationPusher\\Adapter\\'.ucfirst($argument))) {
throw new AdapterException(
sprintf(
'Adapter class %s does not exist',
$adapterClass
)
);
}
return $adapterClass;
}
/**
* {@inheritdoc}
*
* @return \Sly\NotificationPusher\Adapter\AdapterInterface
*/
private function getReadyAdapter(InputInterface $input, OutputInterface $output)
{
$adapterClass = $this->getAdapterClassFromArgument($input->getArgument('adapter'));
try {
$adapter = new $adapterClass();
} catch (\Exception $e) {
$adapterData = array();
preg_match_all('/"(.*)"/i', $e->getMessage(), $matches);
foreach ($matches[1] as $match) {
$optionKey = str_replace('_', '-', Inflector::tableize($match));
$option = $input->getOption($optionKey);
if (!$option) {
throw new AdapterException(
sprintf(
'The option "%s" is needed by %s adapter',
$optionKey,
$adapterClass
)
);
}
$adapterData[$match] = $option;
}
$adapter = new $adapterClass($adapterData);
}
return $adapter;
}
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Exception;
use Sly\NotificationPusher\Exception\ExceptionInterface;
/**
* AdapterException.
*
* @uses \RuntimeException
* @uses \Sly\NotificationPusher\Exception\ExceptionInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class AdapterException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,21 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Exception;
/**
* ExceptionInterface.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
interface ExceptionInterface
{
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Exception;
use Sly\NotificationPusher\Exception\ExceptionInterface;
/**
* InvalidException.
*
* @uses \RuntimeException
* @uses \Sly\NotificationPusher\Exception\ExceptionInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class InvalidException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Exception;
use Sly\NotificationPusher\Exception\ExceptionInterface;
/**
* PushException.
*
* @uses \RuntimeException
* @uses \Sly\NotificationPusher\Exception\ExceptionInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class PushException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,26 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Exception;
use Sly\NotificationPusher\Exception\ExceptionInterface;
/**
* RuntimeException.
*
* @uses \RuntimeException
* @uses \Sly\NotificationPusher\Exception\ExceptionInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* BaseOptionedModel.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
abstract class BaseOptionedModel
{
/**
* @var array
*/
protected $options = array();
/**
* Get options.
*
* @return array
*/
public function getOptions()
{
return $this->options;
}
/**
* Has option.
*
* @param string $key Key
*
* @return boolean
*/
public function hasOption($key)
{
return array_key_exists($key, $this->options);
}
/**
* Get option.
*
* @param string $key Key
* @param mixed $default Default
*
* @return mixed
*/
public function getOption($key, $default = null)
{
return $this->hasOption($key) ? $this->options[$key] : $default;
}
/**
* Set options.
*
* @param array $options Options
*
* @return \Sly\NotificationPusher\Model\BaseOptionedModel
*/
public function setOptions($options)
{
$this->options = $options;
return $this;
}
/**
* Set option.
*
* @param string $key Key
* @param mixed $value Value
*
* @return mixed
*/
public function setOption($key, $value)
{
$this->options[$key] = $value;
return $value;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* BaseParameteredModel.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
abstract class BaseParameteredModel
{
/**
* @var array
*/
protected $parameters = array();
/**
* Get parameters.
*
* @return array
*/
public function getParameters()
{
return $this->parameters;
}
/**
* Has parameter.
*
* @param string $key Key
*
* @return boolean
*/
public function hasParameter($key)
{
return array_key_exists($key, $this->parameters);
}
/**
* Get parameter.
*
* @param string $key Key
* @param mixed $default Default
*
* @return mixed
*/
public function getParameter($key, $default = null)
{
return $this->hasParameter($key) ? $this->parameters[$key] : $default;
}
/**
* Set parameters.
*
* @param array $parameters Parameters
*
* @return \Sly\NotificationPusher\Model\BaseParameteredModel
*/
public function setParameters($parameters)
{
$this->parameters = $parameters;
return $this;
}
/**
* Set parameter.
*
* @param string $key Key
* @param mixed $value Value
*
* @return mixed
*/
public function setParameter($key, $value)
{
$this->parameters[$key] = $value;
return $value;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* Device.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class Device extends BaseParameteredModel implements DeviceInterface
{
/**
* @var string
*/
private $token;
/**
* Constructor.
*
* @param string $token Token
* @param array $parameters Parameters
*/
public function __construct($token, array $parameters = array())
{
$this->token = $token;
$this->parameters = $parameters;
}
/**
* Get token.
*
* @return string
*/
public function getToken()
{
return $this->token;
}
/**
* Set token.
*
* @param string $token Token
*
* @return \Sly\NotificationPusher\Model\DeviceInterface
*/
public function setToken($token)
{
$this->token = $token;
return $this;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* DeviceInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
interface DeviceInterface
{
/**
* Get token.
*
* @return string
*/
public function getToken();
/**
* Set token.
*
* @param string $token Token
*
* @return \Sly\NotificationPusher\Model\DeviceInterface
*/
public function setToken($token);
}

View File

@@ -0,0 +1,61 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* Message.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class Message extends BaseOptionedModel implements MessageInterface
{
/**
* @var string
*/
private $text;
/**
* Constructor.
*
* @param string $text Text
* @param array $options Options
*/
public function __construct($text, array $options = array())
{
$this->text = $text;
$this->options = $options;
}
/**
* Get Text.
*
* @return string
*/
public function getText()
{
return $this->text;
}
/**
* Set Text.
*
* @param string $text Text
*
* @return \Sly\NotificationPusher\Model\MessageInterface
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
}

View File

@@ -0,0 +1,36 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
/**
* MessageInterface
*
* @author Cédric Dugat <cedric@dugat.me>
*/
interface MessageInterface
{
/**
* Get Text.
*
* @return string
*/
public function getText();
/**
* Set Text.
*
* @param string $text Text
*
* @return \Sly\NotificationPusher\Model\MessageInterface
*/
public function setText($text);
}

View File

@@ -0,0 +1,246 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
use Sly\NotificationPusher\Collection\DeviceCollection;
use Sly\NotificationPusher\Adapter\AdapterInterface;
use Sly\NotificationPusher\Model\DeviceInterface;
use Sly\NotificationPusher\Model\MessageInterface;
use Sly\NotificationPusher\Exception\AdapterException;
/**
* Push.
*
* @author Cédric Dugat <cedric@dugat.me>
*/
class Push extends BaseOptionedModel implements PushInterface
{
/**
* @var string
*/
private $status;
/**
* @var \Sly\NotificationPusher\Adapter\AdapterInterface
*/
private $adapter;
/**
* @var \Sly\NotificationPusher\Model\MessageInterface
*/
private $message;
/**
* @var \Sly\NotificationPusher\Collection\DeviceCollection
*/
private $devices;
/**
* @var \DateTime
*/
private $pushedAt;
/**
* Constructor.
*
* @param \Sly\NotificationPusher\Adapter\AdapterInterface $adapter Adapter
* @param DeviceInterface|DeviceCollection $devices Device(s)
* @param \Sly\NotificationPusher\Model\MessageInterface $message Message
* @param array $options Options
*
* Options are adapters specific ones, like Apns "badge" or "sound" option for example.
* Of course, they can be more general.
*
* @throws \Sly\NotificationPusher\Exception\AdapterException
*/
public function __construct(AdapterInterface $adapter, $devices, MessageInterface $message, array $options = array())
{
if ($devices instanceof DeviceInterface) {
$devices = new DeviceCollection(array($devices));
}
$this->adapter = $adapter;
$this->devices = $devices;
$this->message = $message;
$this->options = $options;
$this->status = self::STATUS_PENDING;
$this->checkDevicesTokens();
}
/**
* Check devices tokens.
*/
private function checkDevicesTokens()
{
$devices = $this->getDevices();
$adapter = $this->getAdapter();
foreach ($devices as $device) {
if (false === $adapter->supports($device->getToken())) {
throw new AdapterException(
sprintf(
'Adapter %s does not supports %s token\'s device',
(string) $adapter,
$device->getToken()
)
);
}
}
}
/**
* Get Status.
*
* @return string
*/
public function getStatus()
{
return $this->status;
}
/**
* Set Status.
*
* @param string $status Status
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function setStatus($status)
{
$this->status = $status;
return $this;
}
/**
* isPushed.
*
* @return boolean
*/
public function isPushed()
{
return (bool) (self::STATUS_PUSHED === $this->status);
}
/**
* Declare as pushed.
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function pushed()
{
$this->status = self::STATUS_PUSHED;
$this->pushedAt = new \DateTime();
return $this;
}
/**
* Get Adapter.
*
* @return \Sly\NotificationPusher\Adapter\AdapterInterface
*/
public function getAdapter()
{
return $this->adapter;
}
/**
* Set Adapter.
*
* @param \Sly\NotificationPusher\Adapter\AdapterInterface $adapter Adapter
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function setAdapter(AdapterInterface $adapter)
{
$this->adapter = $adapter;
return $this;
}
/**
* Get Message.
*
* @return \Sly\NotificationPusher\Model\MessageInterface
*/
public function getMessage()
{
return $this->message;
}
/**
* Set Message.
*
* @param \Sly\NotificationPusher\Model\MessageInterface $message Message
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function setMessage(MessageInterface $message)
{
$this->message = $message;
return $this;
}
/**
* Get Devices.
*
* @return \Sly\NotificationPusher\Collection\DeviceCollection
*/
public function getDevices()
{
return $this->devices;
}
/**
* Set Devices.
*
* @param \Sly\NotificationPusher\Collection\DeviceCollection $devices Devices
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function setDevices(DeviceCollection $devices)
{
$this->devices = $devices;
$this->checkDevicesTokens();
return $this;
}
/**
* Get PushedAt.
*
* @return \DateTime
*/
public function getPushedAt()
{
return $this->pushedAt;
}
/**
* Set PushedAt.
*
* @param \DateTime $pushedAt PushedAt
*
* @return \Sly\NotificationPusher\Model\PushInterface
*/
public function setPushedAt(\DateTime $pushedAt)
{
$this->pushedAt = $pushedAt;
return $this;
}
}

View File

@@ -0,0 +1,122 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher\Model;
use DateTime;
use Sly\NotificationPusher\Adapter\AdapterInterface;
use Sly\NotificationPusher\Collection\DeviceCollection;
/**
* PushInterface
*/
interface PushInterface
{
/**
* Constants define available statuses
*/
const STATUS_PENDING = 'pending';
const STATUS_PUSHED = 'sent';
/**
* Get Status.
*
* @return string
*/
public function getStatus();
/**
* Set Status.
*
* @param string $status Status
*
* @return PushInterface
*/
public function setStatus($status);
/**
* isPushed.
*
* @return boolean
*/
public function isPushed();
/**
* Declare as pushed.
*
* @return PushInterface
*/
public function pushed();
/**
* Get Adapter.
*
* @return AdapterInterface
*/
public function getAdapter();
/**
* Set Adapter.
*
* @param AdapterInterface $adapter Adapter
*
* @return PushInterface
*/
public function setAdapter(AdapterInterface $adapter);
/**
* Get Message.
*
* @return MessageInterface
*/
public function getMessage();
/**
* Set Message.
*
* @param MessageInterface $message Message
*
* @return PushInterface
*/
public function setMessage(MessageInterface $message);
/**
* Get Devices.
*
* @return DeviceCollection
*/
public function getDevices();
/**
* Set Devices.
*
* @param DeviceCollection $devices Devices
*
* @return PushInterface
*/
public function setDevices(DeviceCollection $devices);
/**
* Get PushedAt.
*
* @return DateTime
*/
public function getPushedAt();
/**
* Set PushedAt.
*
* @param DateTime $pushedAt PushedAt
*
* @return PushInterface
*/
public function setPushedAt(DateTime $pushedAt);
}

View File

@@ -0,0 +1,20 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher;
/**
* NotificationPusher.
*/
class NotificationPusher
{
const VERSION = '2.0';
}

View File

@@ -0,0 +1,97 @@
<?php
/*
* This file is part of NotificationPusher.
*
* (c) 2013 Cédric Dugat <cedric@dugat.me>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sly\NotificationPusher;
use Sly\NotificationPusher\Collection\PushCollection;
use Sly\NotificationPusher\Adapter\AdapterInterface;
use Sly\NotificationPusher\Exception\AdapterException;
/**
* PushManager.
*
* @uses \Sly\NotificationPusher\Collection\PushCollection
* @author Cédric Dugat <cedric@dugat.me>
*/
class PushManager extends PushCollection
{
const ENVIRONMENT_DEV = 'dev';
const ENVIRONMENT_PROD = 'prod';
/**
* @var string
*/
private $environment;
/**
* Constructor.
*
* @param string $environment Environment
*/
public function __construct($environment = self::ENVIRONMENT_DEV)
{
parent::__construct();
$this->environment = $environment;
}
/**
* Get environment.
*
* @return string
*/
public function getEnvironment()
{
return $this->environment;
}
/**
* Push.
*
* @return \Sly\NotificationPusher\Collection\PushCollection
*/
public function push()
{
foreach ($this as $push) {
$adapter = $push->getAdapter();
$adapter->setEnvironment($this->getEnvironment());
if ($adapter->push($push)) {
$push->pushed();
}
}
return $this;
}
/**
* Get feedback.
*
* @param \Sly\NotificationPusher\Adapter\AdapterInterface $adapter Adapter
*
* @return array
*
* @throws AdapterException When the adapter has no dedicated `getFeedback` method
*/
public function getFeedback(AdapterInterface $adapter)
{
if (false === method_exists($adapter, 'getFeedback')) {
throw new AdapterException(
sprintf(
'%s adapter has no dedicated "getFeedback" method',
(string) $adapter
)
);
}
return $adapter->getFeedback();
}
}