Skip to content

Commit

Permalink
✨ Add strategy support.
Browse files Browse the repository at this point in the history
  • Loading branch information
overtrue committed Apr 29, 2017
1 parent 295927f commit ec8326d
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 61 deletions.
17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,22 @@ $ composer require "overtrue/easy-sms"
use Overtrue\EasySms\EasySms;

$config = [
'default' => 'error-log',
'shuffle_gateways' => true,
'enabled_gateways' => ['yunpian', 'alidayu'],
'timeout' => 5.0,
'default' => [
'strategy' => \Overtrue\EasySms\Strategies\RandomStrategy::class,
'gateways' => [
'yunpian', 'alidayu',
],
],
'gateways' => [
'error-log' => [
'errorlog' => [
'file' => '/tmp/easy-sms.log',
],
'yunpian' => [
'api_key' => '824f0ff2f71cab52936a13ede3xxxxx',
'api_key' => '824f0ff2f71cab52936axxxxxxxxxx',
],
alidayu => [
//...
],
],
];
Expand Down
25 changes: 25 additions & 0 deletions src/Contracts/StrategyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

/*
* This file is part of the overtrue/easy-sms.
* (c) overtrue <[email protected]>
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Overtrue\EasySms\Contracts;

/**
* Interface StrategyInterface.
*/
interface StrategyInterface
{
/**
* Apply the strategy and return result.
*
* @param array $gateways
*
* @return array
*/
public function apply(array $gateways);
}
93 changes: 46 additions & 47 deletions src/EasySms.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
namespace Overtrue\EasySms;

use Closure;
use InvalidArgumentException;
use Overtrue\EasySms\Contracts\GatewayInterface;
use Overtrue\EasySms\Contracts\MessageInterface;
use Overtrue\EasySms\Contracts\StrategyInterface;
use Overtrue\EasySms\Exceptions\InvalidArgumentException;
use Overtrue\EasySms\Support\Config;
use RuntimeException;

Expand Down Expand Up @@ -46,6 +46,11 @@ class EasySms
*/
protected $messenger;

/**
* @var array
*/
protected $strategies = [];

/**
* Constructor.
*
Expand All @@ -65,14 +70,15 @@ public function __construct(array $config)
*
* @param string|array $to
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
* @param array $gateways
*
* @return array
*/
public function send($to, $message)
public function send($to, $message, array $gateways = [])
{
$messenger = $this->getMessenger();

return $messenger->send($to, $message, $this->getMessageGateways($message));
return $messenger->send($to, $message, $gateways);
}

/**
Expand All @@ -93,6 +99,34 @@ public function gateway($name = null)
return $this->gateways[$name];
}

/**
* Get a strategy instance.
*
* @param string|null $strategy
*
* @return StrategyInterface
*/
public function strategy($strategy = null)
{
if (is_null($strategy)) {
$strategy = $this->config->get('default.strategy');
}

if (!class_exists($strategy)) {
$strategy = __NAMESPACE__.'\Strategies\\'.ucfirst($strategy);
}

if (!class_exists($strategy)) {
throw new InvalidArgumentException("Unsupported strategy \"{$strategy}\"");
}

if (!($this->strategies[$strategy] instanceof StrategyInterface)) {
$this->strategies[$strategy] = new $strategy($this);
}

return $this->strategies[$strategy];
}

/**
* Register a custom driver creator Closure.
*
Expand All @@ -108,6 +142,14 @@ public function extend($name, Closure $callback)
return $this;
}

/**
* @return \Overtrue\EasySms\Support\Config
*/
public function getConfig()
{
return $this->config;
}

/**
* Get default gateway name.
*
Expand Down Expand Up @@ -146,36 +188,6 @@ public function getMessenger()
return $this->messenger ?: $this->messenger = new Messenger($this);
}

/**
* @param \Overtrue\EasySms\Contracts\MessageInterface $message
*
* @return array
*/
protected function getMessageGateways(MessageInterface $message)
{
$gateways = [];

foreach ($message->getGateways() as $gateway => $setting) {
if (is_integer($gateway) && is_string($setting)) {
$gateway = $setting;
$setting = [];
}
$globalSetting = $this->config->get("gateways.{$gateway}", []);

if (is_string($gateway) && !empty($globalSetting)) {
$gateways[$gateway] = array_merge($globalSetting, (array) $setting);
}
}

if ($this->config->get('shuffle_gateways')) {
uasort($gateways, function () {
return mt_rand() - mt_rand();
});
}

return $gateways;
}

/**
* Create a new driver instance.
*
Expand Down Expand Up @@ -247,17 +259,4 @@ protected function callCustomCreator($gateway)
{
return call_user_func($this->customCreators[$gateway], $this->config->get($gateway, []));
}

/**
* Dynamically call the default gateway instance.
*
* @param string $method
* @param array $parameters
*
* @return mixed
*/
public function __call($method, $parameters)
{
return call_user_func_array([$this->gateway(), $method], $parameters);
}
}
17 changes: 17 additions & 0 deletions src/Exceptions/InvalidArgumentException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

/*
* This file is part of the overtrue/easy-sms.
* (c) overtrue <[email protected]>
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Overtrue\EasySms\Exceptions;

/**
* Class InvalidArgumentException.
*/
class InvalidArgumentException extends \InvalidArgumentException
{
}
73 changes: 66 additions & 7 deletions src/Messenger.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,30 @@
namespace Overtrue\EasySms;

use Overtrue\EasySms\Contracts\MessageInterface;
use Overtrue\EasySms\Support\Config;

/**
* Class Messenger.
*/
class Messenger
{
const STATUS_SUCCESS = 'success';
const STATUS_ERRED = 'erred';

/**
* @var \Overtrue\EasySms\EasySms
*/
protected $easySms;

/**
* Messenger constructor.
*
* @param \Overtrue\EasySms\EasySms $easySms
*/
public function __construct(EasySms $easySms)
{
$this->easySms = $easySms;
}

/**
* Send a message.
*
Expand All @@ -29,20 +46,62 @@ class Messenger
public function send($to, MessageInterface $message, array $gateways = [])
{
if (!($message instanceof MessageInterface)) {
$message = new Message(['content' => $message, 'template' => $message]);
$message = new Message([
'content' => $message,
'template' => $message,
]);
}

$result = [];
$results = [];

foreach ($gateways as $gateway => $config) {
if (empty($gateways)) {
$gateways = $message->getGateways();
}

$gateways = $this->formatGateways($gateways);
$strategyAppliedGateways = $this->easySms->strategy()->apply($gateways);

foreach ($strategyAppliedGateways as $gateway) {
try {
$result[$gateway] = $this->gateway($gateway)->send($to, $message, new Config($config));
$result[$gateway] = [
'status' => self::STATUS_SUCCESS,
'result' => $this->easySms->gateway($gateway)->send($to, $message, new Config($gateways[$gateway])),
];
} catch (GatewayErrorException $e) {
$result[$gateway] = $e;
$result[$gateway] = [
'status' => self::STATUS_ERRED,
'exception' => $e,
];
continue;
}
}

return false;
return $results;
}

/**
* @param array $gateways
*
* @return array
*/
protected function formatGateways(array $gateways)
{
$formatted = [];
$config = $this->easySms->getConfig();

foreach ($gateways as $gateway => $setting) {
if (is_integer($gateway) && is_string($setting)) {
$gateway = $setting;
$setting = [];
}

$globalSetting = $config->get("gateways.{$gateway}", []);

if (is_string($gateway) && !empty($globalSetting) && is_array($setting)) {
$formatted[$gateway] = array_merge($globalSetting, $setting);
}
}

return $formatted;
}
}
32 changes: 32 additions & 0 deletions src/Strategies/RadomStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

/*
* This file is part of the overtrue/easy-sms.
* (c) overtrue <[email protected]>
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace Overtrue\EasySms\Strategies;

use Overtrue\EasySms\Contracts\StrategyInterface;

/**
* Class RandomStrategy.
*/
class RandomStrategy implements StrategyInterface
{
/**
* @param array $gateways
*
* @return array
*/
public function apply(array $gateways)
{
uasort($gateways, function () {
return mt_rand() - mt_rand();
});

return $gateways;
}
}
10 changes: 8 additions & 2 deletions tests/EasySmsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,20 @@ public function testExtend()
public function testSend()
{
$message = new Message(['content' => 'hello']);
$config = new Config();

$easySms = \Mockery::mock(EasySms::class.'[getMessenger]', [['default' => DummyGatewayForTest::class]]);
$messenger = \Mockery::mock(Messenger::class);
$messenger->shouldReceive('send')->with('mock-number', $message, [])->andReturn('send-result');
$easySms->shouldReceive('getMessenger')->andReturn($messenger);

$this->assertSame('send-result', $easySms->send('mock-number', $message, $config));
$this->assertSame('send-result', $easySms->send('mock-number', $message, []));
}

public function testGetMessenger()
{
$easySms = new EasySms([]);

$this->assertInstanceOf(Messenger::class, $easySms->getMessenger());
}
}

Expand Down

0 comments on commit ec8326d

Please sign in to comment.