Sms   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 176
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 23
c 3
b 0
f 0
lcom 1
cbo 2
dl 0
loc 176
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A send() 0 5 1
A __construct() 0 10 2
A balance() 0 4 1
A randomizeProvider() 0 15 3
A generateMessageId() 0 4 1
C response() 0 60 10
A prepareNumber() 0 11 4
A getSmsProviderName() 0 4 1
1
<?php
2
namespace ridvanbaluyos\sms;
3
4
use ridvanbaluyos\sms\SmsProviderServicesInterface as SmsProviderServicesInterface;
5
use ridvanbaluyos\sms\providers\PromoTexter;
6
use ridvanbaluyos\sms\providers\RisingTide;
7
use ridvanbaluyos\sms\providers\Semaphore;
8
use ridvanbaluyos\sms\providers\Chikka;
9
use Noodlehaus\Config as Config;
10
11
/**
12
 * Class Sms
13
 * @package ridvanbaluyos\sms
14
 */
15
class Sms implements SmsProviderServicesInterface
16
{
17
    /**
18
     * @var SmsProviderServicesInterface
19
     */
20
    private $smsProvider;
21
22
    /**
23
     * Sms constructor.
24
     * @param SmsProviderServicesInterface|null $smsProvider
25
     */
26
    public function __construct(SmsProviderServicesInterface $smsProvider = null)
27
    {
28
        // If no provider is specified, randomize by distribution percentage.
29
        if ($smsProvider instanceof SmsProviderServicesInterface) {
30
            $this->smsProvider = $smsProvider;
31
        } else {
32
            $provider = 'ridvanbaluyos\\sms\\providers\\' . $this->randomizeProvider();
33
            $this->smsProvider = new $provider();
34
        }
35
    }
36
37
    /**
38
     * This function sends the SMS.
39
     *
40
     * @param $phoneNumber - the mobile number
41
     * @param $message - the message
42
     */
43
    public function send($phoneNumber, $message)
44
    {
45
        $phoneNumber = $this->prepareNumber($phoneNumber);
46
        return $this->smsProvider->send($phoneNumber, $message . ' via ' . $this->smsProvider->className);
0 ignored issues
show
Bug introduced by
Accessing className on the interface ridvanbaluyos\sms\SmsProviderServicesInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
47
    }
48
49
    /**
50
     * This function gets the remaining balance of an account
51
     *
52
     */
53
    public function balance()
54
    {
55
        return $this->smsProvider->balance();
56
    }
57
58
    /**
59
     * This function randomizes the SMS providers. Make sure that the total
60
     * of the SMS providers in distribution.json is equal to 1. Otherwise, there's
61
     * no guarantee that the randomizer will work as expected.
62
     *
63
     * @return string $result - the lucky SMS provider
64
     */
65
    private function randomizeProvider()
66
    {
67
        $providers = Config::load(__DIR__ . '/config/distribution.json');
68
        $result = 'PromoTexter';
69
        $rand = (float)rand() / (float)getrandmax();
70
        foreach ($providers as $provider => $weight) {
71
            if ($rand < $weight) {
72
                $result = $provider;
73
                break;
74
            }
75
            $rand -= $weight;
76
        }
77
78
        return $result;
79
    }
80
81
    /**
82
     * This function generates a random string with a specific length.
83
     *
84
     * @param int $length - the length of the message id
85
     * @return string - returns a random n length string
86
     */
87
    protected function generateMessageId($length = 32)
88
    {
89
        return str_pad(uniqid(uniqid()), $length, uniqid(), STR_PAD_LEFT);
90
    }
91
92
    /**
93
     * This function acts a pseudo-envelope for the responses of each SMS providers. It basically
94
     * standardizes the responses of each.
95
     *
96
     * @param $code - the response code
97
     * @param null $message - an optional message aside from the default ones
98
     * @param null $provider - the SMS provider used. Should only be enabled during debug mode.
99
     *
100
     * @return string $response - the JSON formatted response.
101
     */
102
    protected function response($code, $metadata = null, $message = null, $provider)
103
    {
104
        switch ($code) {
105
            // Error Codes
106
            case 400:
107
                $envelope = 'error';
108
                $description = 'Bad Request';
109
                break;
110
            case 401:
111
                $envelope = 'error';
112
                $description = 'Unauthorized';
113
                break;
114
            case 403:
115
                $envelope = 'error';
116
                $description = 'Forbidden';
117
                break;
118
            case 404:
119
                $envelope = 'error';
120
                $description = 'Not Found';
121
                break;
122
            case 500:
123
                $envelope = 'error';
124
                $description = 'Something went wrong';
125
                break;
126
            // Success Codes
127
            case 200:
128
                $envelope = 'data';
129
                $description = 'OK';
130
                break;
131
            case 201:
132
                $envelope = 'data';
133
                $description = 'Created';
134
                break;
135
            case 202:
136
                $envelope = 'data';
137
                $description = 'Accepted';
138
                break;
139
            default:
140
                $envelope = 'data';
141
                $description = '';
142
                break;
143
        }
144
145
        if (is_null($message)) {
146
            $message = $description;
147
        }
148
        // HTTP Response
149
        $response = [
150
            $envelope => [
151
                'code' => $code,
152
                'message' => $message,
153
                'provider' => $provider,
154
                'metadata' => $metadata
155
            ],
156
        ];
157
158
        $response = json_encode($response, JSON_PRETTY_PRINT);
159
160
        return $response;
161
    }
162
163
    /**
164
     * This function reformats the mobile number being sent to the Philippine mobile number standard.
165
     *
166
     * @param $number - the mobile number
167
     * @return string - the formatted mobile number
168
     */
169
    protected function prepareNumber($number)
170
    {
171
        $numbersOnly = preg_replace('/[^0-9]/', '', $number);
172
        if (strpos($numbersOnly, '09') === 0) {
173
            $number = '63' . mb_substr($numbersOnly, 1);
174
        } elseif (strlen($numbersOnly) == 10 && strpos($numbersOnly, '9') === 0) {
175
            $number = '63' . $numbersOnly;
176
        }
177
178
        return $number;
179
    }
180
181
    /**
182
     * This function returns the SMS Provider name in plain text.
183
     *
184
     * @return string $className - the sms provider name.
185
     */
186
    public function getSmsProviderName()
187
    {
188
        return $this->smsProvider->className;
0 ignored issues
show
Bug introduced by
Accessing className on the interface ridvanbaluyos\sms\SmsProviderServicesInterface suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
189
    }
190
}
191