Completed
Pull Request — master (#85)
by
unknown
01:26
created

AbstractClient::close()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
c 0
b 0
f 0
nc 1
1
<?php
2
3
namespace AfriCC\EPP;
4
5
use AfriCC\EPP\Frame\Command\Login as LoginCommand;
6
use AfriCC\EPP\Frame\Response as ResponseFrame;
7
use AfriCC\EPP\Frame\ResponseFactory;
8
use Exception;
9
use Psr\Log\LoggerAwareInterface;
10
use Psr\Log\LoggerAwareTrait;
11
12
/**
13
 * An abstract client client for the Extensible Provisioning Protocol (EPP)
14
 *
15
 * Extend this class in your custom EPP Client
16
 *
17
 * @see http://tools.ietf.org/html/rfc5734
18
 * @see ClientInterface
19
 *
20
 * As this class is abstract and relies on subclass implementation details it's untestable
21
 * @codeCoverageIgnore
22
 */
23
abstract class AbstractClient implements ClientInterface, LoggerAwareInterface
24
{
25
    use LoggerAwareTrait;
26
27
    protected $host;
28
    protected $port;
29
    protected $username;
30
    protected $password;
31
    protected $services;
32
    protected $serviceExtensions;
33
    protected $ssl;
34
    protected $local_cert;
35
    protected $ca_cert;
36
    protected $pk_cert;
37
    protected $passphrase;
38
    protected $debug;
39
    protected $connect_timeout;
40
    protected $timeout;
41
    protected $objectSpec;
42
43
    /**
44
     * {@inheritdoc}
45
     *
46
     * @see \AfriCC\EPP\ClientInterface::connect()
47
     */
48
    abstract public function connect($newPassword = false);
49
50
    abstract public function close();
51
52
    /**
53
     * Prints out debugging data (eg raw frame bytes)
54
     *
55
     * @param string $message
56
     */
57
    abstract protected function debugLog($message);
58
59
    protected function logCommand(FrameInterface $frame)
60
    {
61
        if (isset($this->logger)) {
62
            $command = \get_class($frame);
63
            $frame_xml = (string) $frame;
64
            $this->logger->info("Sending EPP Command '$command'. Full frame: $frame_xml");
65
        }
66
    }
67
68
    /**
69
     * @param ResponseFrame|string $frame
70
     */
71
    protected function logResponse($frame)
72
    {
73
        if (isset($this->logger)) {
74
            $type = $frame instanceof ResponseFrame ? \get_class($frame) : 'INCORRECT';
75
            $frame_xml = (string) $frame;
76
            $this->logger->info("Received EPP '$type' Response. Full frame: $frame_xml");
77
        }
78
    }
79
80
    /**
81
     * Send frame to EPP server
82
     *
83
     * @param FrameInterface $frame Frame to send
84
     *
85
     * @throws Exception on send error
86
     */
87
    abstract public function sendFrame(FrameInterface $frame);
88
89
    /**
90
     * Get response frame from EPP server (use after sendFrame)
91
     *
92
     * @throws Exception on frame receive error
93
     *
94
     * @return string raw XML of EPP Frame
95
     */
96
    abstract public function getFrame();
97
98
    public function request(FrameInterface $frame)
99
    {
100
        if ($frame instanceof TransactionAwareInterface) {
101
            $frame->setClientTransactionId(
102
                $this->generateClientTransactionId()
103
                );
104
        }
105
106
        $this->logCommand($frame);
107
        $this->sendFrame($frame);
108
109
        $return = $this->getFrame();
110
        $response = ResponseFactory::build($return, $this->objectSpec);
111
        $this->logResponse($response);
112
113
        return $response;
114
    }
115
116
    public function __construct(array $config, ObjectSpec $objectSpec = null)
117
    {
118
        if (!empty($config['debug']) && is_bool($config['debug'])) {
119
            $this->debug = $config['debug'];
120
        } else {
121
            $this->debug = false;
122
        }
123
124
        if (is_null($objectSpec)) {
125
            $objectSpec = new ObjectSpec();
126
        }
127
128
        $this->objectSpec = $objectSpec;
129
130
        $this->prepareConnectionOptions($config);
131
        $this->prepareCredentials($config);
132
        $this->prepareSSLOptions($config);
133
        $this->prepareEPPServices($config);
134
    }
135
136
    /**
137
     * Get client's ObjectSpec
138
     *
139
     * @return ObjectSpec
140
     */
141
    public function getObjectSpec()
142
    {
143
        return $this->objectSpec;
144
    }
145
146
    /**
147
     * Set client's ObjectSpec
148
     *
149
     * @param ObjectSpec $newObjectSpec
150
     */
151
    public function setObjectSpec(ObjectSpec $newObjectSpec)
152
    {
153
        $this->objectSpec = $newObjectSpec;
154
    }
155
156
    protected function prepareConnectionOptions(array $config)
157
    {
158
        if (!empty($config['host'])) {
159
            $this->host = (string) $config['host'];
160
        }
161
162
        if (!empty($config['port'])) {
163
            $this->port = (int) $config['port'];
164
        } else {
165
            $this->port = false;
166
        }
167
168
        if (!empty($config['connect_timeout'])) {
169
            $this->connect_timeout = (int) $config['connect_timeout'];
170
        } else {
171
            $this->connect_timeout = 16;
172
        }
173
174
        if (!empty($config['timeout'])) {
175
            $this->timeout = (int) $config['timeout'];
176
        } else {
177
            $this->timeout = 32;
178
        }
179
    }
180
181
    protected function prepareCredentials(array $config)
182
    {
183
        if (!empty($config['username'])) {
184
            $this->username = (string) $config['username'];
185
        }
186
187
        if (!empty($config['password'])) {
188
            $this->password = (string) $config['password'];
189
        }
190
    }
191
192
    protected function prepareSSLOptions(array $config)
193
    {
194
        if ((!empty($config['ssl']) && is_bool($config['ssl']))) {
195
            $this->ssl = $config['ssl'];
196
        } else {
197
            $this->ssl = false;
198
        }
199
200
        if (!empty($config['local_cert'])) {
201
            $this->local_cert = (string) $config['local_cert'];
202
203
            if (!is_readable($this->local_cert)) {
204
                throw new \Exception(sprintf('unable to read local_cert: %s', $this->local_cert));
205
            }
206
        }
207
208
        if (!empty($config['ca_cert'])) {
209
            $this->ca_cert = (string) $config['ca_cert'];
210
211
            if (!is_readable($this->ca_cert)) {
212
                throw new \Exception(sprintf('unable to read ca_cert: %s', $this->ca_cert));
213
            }
214
        }
215
216
        if (!empty($config['pk_cert'])) {
217
            $this->pk_cert = (string) $config['pk_cert'];
218
219
            if (!is_readable($this->pk_cert)) {
220
                throw new \Exception(sprintf('unable to read pk_cert: %s', $this->pk_cert));
221
            }
222
        }
223
224
        if (!empty($config['passphrase'])) {
225
            $this->passphrase = (string) $config['passphrase'];
226
        }
227
    }
228
229
    protected function prepareEPPServices(array $config)
230
    {
231
        if (!empty($config['services']) && is_array($config['services'])) {
232
            $this->services = $config['services'];
233
234
            if (!empty($config['serviceExtensions']) && is_array($config['serviceExtensions'])) {
235
                $this->serviceExtensions = $config['serviceExtensions'];
236
            }
237
        }
238
    }
239
240
    protected function generateClientTransactionId()
241
    {
242
        return Random::id(64, $this->username);
243
    }
244
245
    /**
246
     * Generate and send login frame
247
     *
248
     * @param bool|string $newPassword New password to set on login, false if not changing password
249
     *
250
     * @throws \Exception On unsuccessful login
251
     *
252
     * @return \AfriCC\EPP\Frame\Response Login response
253
     */
254
    protected function login($newPassword = false)
255
    {
256
        // send login command
257
        $login = new LoginCommand($this->objectSpec);
258
        $login->setClientId($this->username);
259
        $login->setPassword($this->password);
260
        if ($newPassword) {
261
            $login->setNewPassword($newPassword);
262
        }
263
        $login->setVersion('1.0');
264
        $login->setLanguage('en');
265
266
        if (!empty($this->services) && is_array($this->services)) {
267
            foreach ($this->services as $urn) {
268
                $login->addService($urn);
269
            }
270
271
            if (!empty($this->serviceExtensions) && is_array($this->serviceExtensions)) {
272
                foreach ($this->serviceExtensions as $extension) {
273
                    $login->addServiceExtension($extension);
274
                }
275
            }
276
        }
277
278
        $response = $this->request($login);
279
        unset($login);
280
281
        // check if login was successful
282
        if (!($response instanceof ResponseFrame)) {
283
            throw new \Exception('there was a problem logging onto the EPP server');
284
        } elseif ($response->code() !== 1000) {
285
            throw new \Exception($response->message(), $response->code());
286
        }
287
288
        return $response;
289
    }
290
}
291