Completed
Push — master ( 9b0d18...fb03b4 )
by smiley
02:39
created

TinyCurlEndpoint::sendSimple()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 3
rs 10
cc 1
eloc 1
nc 1
nop 2
1
<?php
2
/**
3
 * Class TinyCurlEndpoint
4
 *
5
 * @filesource   TinyCurlEndpoint.php
6
 * @created      02.04.2016
7
 * @package      chillerlan\Threema\Endpoint
8
 * @author       Smiley <[email protected]>
9
 * @copyright    2016 Smiley
10
 * @license      MIT
11
 */
12
13
namespace chillerlan\Threema\Endpoint;
14
15
use chillerlan\Threema\{
16
	GatewayException, GatewayOptions
17
};
18
use chillerlan\TinyCurl\{
19
	Request, Response\ResponseInterface, URL
20
};
21
use Dotenv\Dotenv;
22
23
/**
24
 *
25
 */
26
class TinyCurlEndpoint implements EndpointInterface{
27
28
	/**
29
	 * @var \chillerlan\Threema\GatewayOptions
30
	 */
31
	protected $gatewayOptions;
32
33
	/**
34
	 * @var \chillerlan\TinyCurl\Request
35
	 */
36
	protected $request;
37
38
	/**
39
	 * TinyCurlEndpoint constructor.
40
	 *
41
	 * @param \chillerlan\Threema\GatewayOptions $gatewayOptions
42
	 * @param \chillerlan\TinyCurl\Request       $request
43
	 *
44
	 * @codeCoverageIgnore
45
	 */
46
	public function __construct(GatewayOptions $gatewayOptions, Request $request){
47
		$this->gatewayOptions = $gatewayOptions;
48
		$this->request        = $request;
49
50
		(new Dotenv($gatewayOptions->configPath, $gatewayOptions->configFilename))->load();
51
	}
52
53
	/**
54
	 * @param string $endpoint
55
	 * @param array  $params
56
	 * @param array  $body
57
	 *
58
	 * @return \chillerlan\TinyCurl\Response\ResponseInterface
59
	 * @throws \chillerlan\Threema\GatewayException
60
	 * @throws \chillerlan\TinyCurl\RequestException
61
	 */
62
	protected function getResponse(string $endpoint, array $params = [], array $body = []):ResponseInterface{
63
		$endpoint = self::API_BASE.$endpoint;
64
		$params   = array_merge($params, [
65
			'from'   => getenv('THREEMA_GATEWAY_ID'),
66
			'secret' => getenv('THREEMA_GATEWAY_SECRET')
67
		]);
68
69
		$url = !empty($body)
70
			? new URL($endpoint, $params, 'POST', $body)
71
			: new URL($endpoint, $params);
72
73
		$response = $this->request->fetch($url);
74
75
		if($response->info->http_code === 200){
76
			return $response;
77
		}
78
		// @codeCoverageIgnoreStart
79
		elseif(array_key_exists($response->info->http_code, self::API_ERRORS)){
80
			throw new GatewayException('gateway error: '.self::API_ERRORS[$response->info->http_code]);
81
		}
82
83
		throw new GatewayException('unknown error: "compiles on my machine."');
84
		// @codeCoverageIgnoreEnd
85
	}
86
87
	/**
88
	 * @inheritdoc
89
	 */
90
	public function checkCredits():int{
91
		return intval($this->getResponse('/credits')->body->content);
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
92
	}
93
94
	/**
95
	 * @inheritdoc
96
	 */
97
	public function checkCapabilities(string $threemaID):array{
98
		$response = $this->getResponse('/capabilities/'.$this->checkThreemaID($threemaID))->body->content;
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
99
		$response = !empty($response) ? explode(',', $response) : [];
100
101
		sort($response);
102
103
		return $response;
104
	}
105
106
	/**
107
	 * @inheritdoc
108
	 */
109
	public function getIdByPhone(string $phoneno):string{
110
		return $this->getResponse('/lookup/phone/'.$this->checkPhoneNo($phoneno))->body->content;
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
111
	}
112
113
	/**
114
	 * @inheritdoc
115
	 */
116
	public function getIdByPhoneHash(string $phonenoHash):string{
117
		return $this->getResponse('/lookup/phone_hash/'.$this->checkHash($phonenoHash))->body->content;
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
118
	}
119
120
	/**
121
	 * @inheritdoc
122
	 */
123
	public function getIdByEmail(string $email):string{
124
		return $this->getResponse('/lookup/email/'.$this->checkEmail($email))->body->content;
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
125
	}
126
127
	/**
128
	 * @inheritdoc
129
	 */
130
	public function getIdByEmailHash(string $emailHash):string{
131
		return $this->getResponse('/lookup/email_hash/'.$this->checkHash($emailHash))->body->content;
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
132
	}
133
134
	/**
135
	 * @inheritdoc
136
	 */
137
	public function getPublicKey(string $threemaID):string{
138
		return $this->checkHash($this->getResponse('/pubkeys/'.$this->checkThreemaID($threemaID))->body->content);
1 ignored issue
show
Bug introduced by
Accessing body on the interface chillerlan\TinyCurl\Response\ResponseInterface 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...
139
	}
140
141
	/**
142
	 * @inheritdoc
143
	 */
144
	public function sendSimple(string $to, string $message):string{
145
		// TODO: Implement sendSimple() method.
146
	}
147
148
	/**
149
	 * @inheritdoc
150
	 */
151
	public function sendE2E(string $threemaID, string $box, string $nonce):string{
152
		// TODO: Implement sendE2E() method.
153
	}
154
155
	/**
156
	 * @inheritdoc
157
	 */
158
	public function upload(string $blob):string{
159
		// TODO: Implement upload() method.
160
	}
161
162
	/**
163
	 * @inheritdoc
164
	 */
165
	public function download(string $blobID){
166
		// TODO: Implement download() method.
167
	}
168
169
	/**
170
	 * @param string $threemaID
171
	 *
172
	 * @return string
173
	 * @throws \chillerlan\Threema\GatewayException
174
	 */
175
	protected function checkThreemaID(string $threemaID):string{
176
177
		if(preg_match('/^[a-z\d\*]{8}$/i', $threemaID)){
178
			return strtoupper($threemaID);
179
		}
180
181
		throw new GatewayException('invalid threema id');
182
	}
183
184
	/**
185
	 * @param string $phoneNo
186
	 *
187
	 * @return string
188
	 * @throws \chillerlan\Threema\GatewayException
189
	 */
190
	protected function checkPhoneNo(string $phoneNo):string{
191
		$phoneNo = preg_replace('/[^\d]/', '', $phoneNo);
192
193
		if(empty($phoneNo)){
194
			throw new GatewayException('invalid phone number');
195
		}
196
197
		return (string)$phoneNo;
198
	}
199
200
	/**
201
	 * @param $email
202
	 *
203
	 * @return string
204
	 * @throws \chillerlan\Threema\GatewayException
205
	 */
206
	protected function checkEmail($email):string{
207
		$email = filter_var(trim($email), FILTER_VALIDATE_EMAIL);
208
209
		if(empty($email)){
210
			throw new GatewayException('invalid email');
211
		}
212
213
		return strtolower($email);
214
	}
215
216
	/**
217
	 * @param string $hash
218
	 *
219
	 * @return string
220
	 * @throws \chillerlan\Threema\GatewayException
221
	 */
222
	protected function checkHash(string $hash):string{
223
224
		if(preg_match('/^[a-f\d]{64}$/i', $hash)){
225
			return $hash;
226
		}
227
228
		throw new GatewayException('invalid hash');
229
	}
230
231
}
232