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

AbstractClient::getObjectSpec()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
nc 1
cc 1
nop 0
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
    protected function logResponse(ResponseFrame $frame)
69
    {
70
        if (isset($this->logger)) {
71
            $type = \get_class($frame);
72
            $frame_xml = (string) $frame;
73
            $this->logger->info("Received EPP Response '$type'. Full frame: $frame_xml");
74
        }
75
    }
76
77
    /**
78
     * Send frame to EPP server
79
     *
80
     * @param FrameInterface $frame Frame to send
81
     *
82
     * @throws Exception on send error
83
     */
84
    abstract public function sendFrame(FrameInterface $frame);
85
86
    /**
87
     * Get response frame from EPP server (use after sendFrame)
88
     *
89
     * @throws Exception on frame receive error
90
     *
91
     * @return string raw XML of EPP Frame
92
     */
93
    abstract public function getFrame();
94
95
    public function request(FrameInterface $frame)
96
    {
97
        if ($frame instanceof TransactionAwareInterface) {
98
            $frame->setClientTransactionId(
99
                $this->generateClientTransactionId()
100
                );
101
        }
102
103
        $this->logCommand($frame);
104
        $this->sendFrame($frame);
105
106
        $return = $this->getFrame();
107
        $response = ResponseFactory::build($return, $this->objectSpec);
108
        $this->logResponse($response);
0 ignored issues
show
Bug introduced by
It seems like $response defined by \AfriCC\EPP\Frame\Respon...urn, $this->objectSpec) on line 107 can also be of type string; however, AfriCC\EPP\AbstractClient::logResponse() does only seem to accept object<AfriCC\EPP\Frame\Response>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
109
110
        return $response;
111
    }
112
113
    public function __construct(array $config, ObjectSpec $objectSpec = null)
114
    {
115
        if (!empty($config['debug']) && is_bool($config['debug'])) {
116
            $this->debug = $config['debug'];
117
        } else {
118
            $this->debug = false;
119
        }
120
121
        if (is_null($objectSpec)) {
122
            $objectSpec = new ObjectSpec();
123
        }
124
125
        $this->objectSpec = $objectSpec;
126
127
        $this->prepareConnectionOptions($config);
128
        $this->prepareCredentials($config);
129
        $this->prepareSSLOptions($config);
130
        $this->prepareEPPServices($config);
131
    }
132
133
    /**
134
     * Get client's ObjectSpec
135
     *
136
     * @return ObjectSpec
137
     */
138
    public function getObjectSpec()
139
    {
140
        return $this->objectSpec;
141
    }
142
143
    /**
144
     * Set client's ObjectSpec
145
     *
146
     * @param ObjectSpec $newObjectSpec
147
     */
148
    public function setObjectSpec(ObjectSpec $newObjectSpec)
149
    {
150
        $this->objectSpec = $newObjectSpec;
151
    }
152
153
    protected function prepareConnectionOptions(array $config)
154
    {
155
        if (!empty($config['host'])) {
156
            $this->host = (string) $config['host'];
157
        }
158
159
        if (!empty($config['port'])) {
160
            $this->port = (int) $config['port'];
161
        } else {
162
            $this->port = false;
163
        }
164
165
        if (!empty($config['connect_timeout'])) {
166
            $this->connect_timeout = (int) $config['connect_timeout'];
167
        } else {
168
            $this->connect_timeout = 16;
169
        }
170
171
        if (!empty($config['timeout'])) {
172
            $this->timeout = (int) $config['timeout'];
173
        } else {
174
            $this->timeout = 32;
175
        }
176
    }
177
178
    protected function prepareCredentials(array $config)
179
    {
180
        if (!empty($config['username'])) {
181
            $this->username = (string) $config['username'];
182
        }
183
184
        if (!empty($config['password'])) {
185
            $this->password = (string) $config['password'];
186
        }
187
    }
188
189
    protected function prepareSSLOptions(array $config)
190
    {
191
        if ((!empty($config['ssl']) && is_bool($config['ssl']))) {
192
            $this->ssl = $config['ssl'];
193
        } else {
194
            $this->ssl = false;
195
        }
196
197
        if (!empty($config['local_cert'])) {
198
            $this->local_cert = (string) $config['local_cert'];
199
200
            if (!is_readable($this->local_cert)) {
201
                throw new \Exception(sprintf('unable to read local_cert: %s', $this->local_cert));
202
            }
203
        }
204
205
        if (!empty($config['ca_cert'])) {
206
            $this->ca_cert = (string) $config['ca_cert'];
207
208
            if (!is_readable($this->ca_cert)) {
209
                throw new \Exception(sprintf('unable to read ca_cert: %s', $this->ca_cert));
210
            }
211
        }
212
213
        if (!empty($config['pk_cert'])) {
214
            $this->pk_cert = (string) $config['pk_cert'];
215
216
            if (!is_readable($this->pk_cert)) {
217
                throw new \Exception(sprintf('unable to read pk_cert: %s', $this->pk_cert));
218
            }
219
        }
220
221
        if (!empty($config['passphrase'])) {
222
            $this->passphrase = (string) $config['passphrase'];
223
        }
224
    }
225
226
    protected function prepareEPPServices(array $config)
227
    {
228
        if (!empty($config['services']) && is_array($config['services'])) {
229
            $this->services = $config['services'];
230
231
            if (!empty($config['serviceExtensions']) && is_array($config['serviceExtensions'])) {
232
                $this->serviceExtensions = $config['serviceExtensions'];
233
            }
234
        }
235
    }
236
237
    protected function generateClientTransactionId()
238
    {
239
        return Random::id(64, $this->username);
240
    }
241
242
    /**
243
     * Generate and send login frame
244
     *
245
     * @param bool|string $newPassword New password to set on login, false if not changing password
246
     *
247
     * @throws \Exception On unsuccessful login
248
     *
249
     * @return \AfriCC\EPP\Frame\Response Login response
250
     */
251
    protected function login($newPassword = false)
252
    {
253
        // send login command
254
        $login = new LoginCommand($this->objectSpec);
255
        $login->setClientId($this->username);
256
        $login->setPassword($this->password);
257
        if ($newPassword) {
258
            $login->setNewPassword($newPassword);
259
        }
260
        $login->setVersion('1.0');
261
        $login->setLanguage('en');
262
263
        if (!empty($this->services) && is_array($this->services)) {
264
            foreach ($this->services as $urn) {
265
                $login->addService($urn);
266
            }
267
268
            if (!empty($this->serviceExtensions) && is_array($this->serviceExtensions)) {
269
                foreach ($this->serviceExtensions as $extension) {
270
                    $login->addServiceExtension($extension);
271
                }
272
            }
273
        }
274
275
        $response = $this->request($login);
276
        unset($login);
277
278
        // check if login was successful
279
        if (!($response instanceof ResponseFrame)) {
280
            throw new \Exception('there was a problem logging onto the EPP server');
281
        } elseif ($response->code() !== 1000) {
282
            throw new \Exception($response->message(), $response->code());
283
        }
284
285
        return $response;
286
    }
287
}
288