Skip to content

Commit 5eaa09d

Browse files
feat(registrar support): added Internet.bs (IBS) and Moniker (MONIKER) as supported registrars
BREAKING CHANGE: We added support for two new Domain Registrar Systems: Internet.bs (IBS) and Moniker (MONIKER)
1 parent 5c28442 commit 5eaa09d

26 files changed

+1559
-84
lines changed

Diff for: README.md

+37-18
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ This module is a connector library for the insanely fast CNIC Backend APIs (HEXO
1111

1212
## Resources
1313

14-
* Documentation:
15-
* [HEXONET](https://www.hexonet.support/hc/en-gb/articles/13651711901213-Self-Development-Kit-for-PHP)
16-
* [CentralNic Reseller](https://support.centralnicreseller.com/hc/en-gb/articles/13513253776285-Self-Development-Kit-for-PHP)
14+
* Documentation Links (PHP-SKD internal registrar id available in round brackets):
15+
* [HEXONET (HEXONET)](https://www.hexonet.support/hc/en-gb/articles/13651711901213-Self-Development-Kit-for-PHP)
16+
* [CentralNic Reseller (CNR)](https://support.centralnicreseller.com/hc/en-gb/articles/13513253776285-Self-Development-Kit-for-PHP)
17+
* [Internet.bs (IBS)](https://www.hexonet.support/hc/en-gb/articles/13651711901213-Self-Development-Kit-for-PHP)
18+
* [Moniker (MONIKER)](https://support.centralnicreseller.com/hc/en-gb/articles/13513253776285-Self-Development-Kit-for-PHP)
1719
* [Release Notes](https://github.com/centralnicgroup-opensource/rtldev-middleware-php-sdk/releases)
1820

1921
## Usage
2022

2123
```composer require centralnic-reseller/php-sdk```
2224

2325
## Dev Container
24-
* Add an entry in your hosts file: ```127.0.0.1 devsdk.hexonet.net```
26+
* Add an entry in your hosts file: ```127.0.0.1 devsdk.hexonet.net```
2527

2628
PHP SDK Data can be accessed via apache server at this url: ```http://devsdk.hexonet.net```
2729

@@ -34,30 +36,47 @@ To run the demo application, follow these steps:
3436
- Directly replace the credentials within the application file.
3537
- Alternatively, set the environment variables required for the CNR test app:
3638
```sh
39+
# CentralNic Reseller
3740
export RTLDEV_MW_CI_USER_CNR=<your-username>
3841
export RTLDEV_MW_CI_USERPASSWORD_CNR=<your-password>
42+
# HEXONET
43+
export RTLDEV_MW_CI_USER_HEXONET=<your-username>
44+
export RTLDEV_MW_CI_USERPASSWORD_HEXONET=<your-password>
45+
# internet.bs
46+
export RTLDEV_MW_CI_USER_IBS=<your-username>
47+
export RTLDEV_MW_CI_USERPASSWORD_IBS=<your-password>
48+
# moniker
49+
export RTLDEV_MW_CI_USER_MONIKER=<your-username>
50+
export RTLDEV_MW_CI_USERPASSWORD_MONIKER=<your-password>
3951
```
4052

4153
2. **Execute the Demo**: Once the credentials are configured, run the appropriate demo command:
42-
- For CNR:
43-
```sh
44-
npm run test-demo-cnr
45-
```
46-
- For Hexonet:
47-
```sh
48-
npm run test-demo-hexonet
49-
```
54+
55+
Run the below npm scripts (or execute the related commands covered in package.json):
56+
57+
```sh
58+
# CentralNic Reseller
59+
npm run test-demo-cnr
60+
# HEXONET
61+
npm run test-demo-hexonet
62+
# internet.bs
63+
npm run test-demo-ibs
64+
# Moniker
65+
npm run test-demo-moniker
66+
```
5067

5168
3. **Update Demo Contents**:
52-
If you need to modify the demo contents, the relevant file is located at:
53-
- For CNR:
54-
```plaintext
55-
tests/CNR/app.php
56-
```
69+
If you need to modify the demo contents, the relevant files are located at:
5770

58-
- For Hexonet:
5971
```plaintext
72+
# CentralNic Reseller
73+
tests/CNR/app.php
74+
# HEXONET
6075
tests/HEXONET/app.php
76+
# internet.bs
77+
tests/IBS/app.php
78+
# Moniker
79+
tests/MONIKER/app.php
6180
```
6281

6382
## Authors

Diff for: package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
],
2323
"scripts": {
2424
"test-demo-cnr": "php -f tests/CNR/app.php",
25-
"test-demo-hexonet": "php -f tests/HEXONET/app.php"
25+
"test-demo-hexonet": "php -f tests/HEXONET/app.php",
26+
"test-demo-ibs": "php -f tests/IBS/app.php",
27+
"test-demo-moniker": "php -f tests/MONIKER/app.php"
2628
},
2729
"keywords": [
2830
"hexonet",

Diff for: src/CNR/Client.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ class Client extends \CNIC\HEXONET\Client
3535
public function __construct($path = "")
3636
{
3737
$contents = file_get_contents($path) ?: "";
38-
/** @var array<mixed> $settings */
3938
$settings = json_decode($contents, true);
39+
if (is_null($settings) || $settings === false || $settings === true) {
40+
$settings = [];
41+
}
4042
$this->settings = $settings;
4143
$this->socketURL = "";
4244
$this->debugMode = false;

Diff for: src/CNR/SessionClient.php

+7-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,13 @@ class SessionClient extends \CNIC\CNR\Client
1919
{
2020
public function __construct()
2121
{
22-
parent::__construct(implode(DIRECTORY_SEPARATOR, [__DIR__, "config.json"]));
22+
$reflection = new \ReflectionClass(get_called_class());
23+
$fname = $reflection->getFileName();
24+
if ($fname === false) {
25+
throw new \Exception("Reflection failed");
26+
}
27+
$cfgpath = implode(DIRECTORY_SEPARATOR, [dirname($fname), "config.json"]);
28+
parent::__construct($cfgpath);
2329
}
2430
/**
2531
* Perform API login to start session-based communication

Diff for: src/CNR/SocketConfig.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SocketConfig extends \CNIC\HEXONET\SocketConfig
2525

2626
/**
2727
* Create POST data string out of connection data
28-
* @param array<mixed> $command API Command to request
28+
* @param array<int|string,mixed> $command API Command to request
2929
* @param bool $secured if password has to be returned "hidden"
3030
* @return string POST data string
3131
*/

Diff for: src/ClientFactory.php

+8-2
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,21 @@ class ClientFactory
88
* Returns Client Instance by configuration
99
* @param array<mixed> $params configuration settings
1010
* @param \CNIC\HEXONET\Logger|\CNIC\CNR\Logger $logger Logger Instance (optional)
11-
* @return \CNIC\HEXONET\SessionClient|\CNIC\CNR\SessionClient
11+
* @return \CNIC\HEXONET\SessionClient|\CNIC\CNR\SessionClient|\CNIC\IBS\SessionClient
1212
* @throws \Exception
1313
*/
1414
public static function getClient($params, $logger = null)
1515
{
16-
if (!(bool)preg_match("/^HEXONET|ISPAPI|KeySystems|RRPproxy|CNR|CNIC$/i", $params["registrar"])) {
16+
if (!(bool)preg_match("/^HEXONET|ISPAPI|CNR|CNIC|IBS|MONIKER$/i", $params["registrar"])) {
1717
throw new \Exception("Registrar `" . $params["registrar"] . "` not supported.");
1818
}
1919
// if we dynamically instantiate via string, phpStan start complaining ...
2020
if ((bool)preg_match("/^HEXONET|ISPAPI$/i", $params["registrar"])) {
2121
$cl = new \CNIC\HEXONET\SessionClient();
22+
} elseif ((bool)preg_match("/^IBS$/i", $params["registrar"])) {
23+
$cl = new \CNIC\IBS\SessionClient();
24+
} elseif ((bool)preg_match("/^MONIKER$/i", $params["registrar"])) {
25+
$cl = new \CNIC\MONIKER\SessionClient();
2226
} else {
2327
$cl = new \CNIC\CNR\SessionClient();
2428
}
@@ -55,6 +59,8 @@ public static function getClient($params, $logger = null)
5559
// if we dynamically instantiate via string, phpStan start complaining ...
5660
if ((bool)preg_match("/^HEXONET|ISPAPI$/i", $params["registrar"])) {
5761
$logger = new \CNIC\HEXONET\Logger();
62+
} else if ((bool)preg_match("/^IBS|MONIKER$/i", $params["registrar"])) {
63+
$logger = new \CNIC\IBS\Logger();
5864
} else {
5965
$logger = new \CNIC\CNR\Logger();
6066
}

Diff for: src/CommandFormatter.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ public static function getSortedCommand(array $command): array
2828
/**
2929
* Flatten API command's nested arrays for easier handling
3030
* @param array<mixed> $cmd API Command
31+
* @param bool $toupper flag to convert keys to uppercase or leave as is
3132
* @return array<mixed>
3233
*/
33-
public static function flattenCommand($cmd)
34+
public static function flattenCommand($cmd, $toupper = true)
3435
{
3536
$newcmd = [];
3637
foreach ($cmd as $key => $val) {
3738
if (isset($val)) {
3839
$val = preg_replace("/\r|\n/", "", $val);
39-
$newKey = \strtoupper($key);
40+
$newKey = $toupper ? \strtoupper($key) : $key;
4041
if (is_array($val)) {
4142
foreach ($cmd[$key] as $idx => $v) {
4243
$newcmd[$newKey . $idx] = $v;

Diff for: src/HEXONET/Client.php

+21-44
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ class Client
6565
public $isOTE = false;
6666
/**
6767
* curl handle cache
68-
* @var array<string,\CurlHandle>
68+
* @var \CurlHandle|null
6969
*/
70-
protected $curlcache = [];
70+
protected $chandle = null;
7171

7272
/**
7373
* Constructor
@@ -77,9 +77,11 @@ class Client
7777
public function __construct($path = "")
7878
{
7979
$contents = file_get_contents($path) ?: "";
80-
/** @var array<string,mixed>|false|null $json */
81-
$json = json_decode($contents, true);
82-
$this->settings = ($json) ? $json : [];
80+
$settings = json_decode($contents, true);
81+
if (is_null($settings) || $settings === false || $settings === true) {
82+
$settings = [];
83+
}
84+
$this->settings = $settings;
8385
$this->socketURL = "";
8486
$this->debugMode = false;
8587
$this->ua = "";
@@ -412,70 +414,45 @@ public function request($cmd)
412414
"CONNECTION_URL" => $this->socketURL
413415
];
414416
$data = $this->getPOSTData($mycmd);
415-
if (isset($this->curlcache[$cfg["CONNECTION_URL"]])) {
416-
$curl = $this->curlcache[$cfg["CONNECTION_URL"]];
417-
} else {
418-
$curl = curl_init($cfg["CONNECTION_URL"]);
419-
// PHP 7.3 return false vs. 7.4 throws an Exception
420-
// when setting the URL to "\0"
421-
// @codeCoverageIgnoreStart
422-
if ($curl === false) {
417+
418+
if (!$this->chandle) {
419+
$tmp = curl_init();
420+
if ($tmp === false) {
423421
$r = new Response("nocurl", $mycmd, $cfg);
424422
if ($this->debugMode) {
425423
$secured = $this->getPOSTData($mycmd, true);
426424
$this->logger->log($secured, $r, "CURL for PHP missing.");
427425
}
428426
return $r;
429427
}
430-
431-
// @codeCoverageIgnoreEnd
432-
curl_setopt_array($curl, [
433-
// CURLOPT_VERBOSE => $this->debugMode,
434-
CURLOPT_CONNECTTIMEOUT => 5, // 5s
435-
CURLOPT_TIMEOUT => $this->settings["socketTimeout"],
436-
CURLOPT_POST => 1,
437-
CURLOPT_HEADER => 0,
438-
CURLOPT_RETURNTRANSFER => 1,
439-
]);
440-
441-
$this->curlcache[$cfg["CONNECTION_URL"]] = $curl;
428+
$this->chandle = $tmp;
442429
}
443430

444-
curl_setopt_array($curl, [
445-
CURLOPT_POSTFIELDS => $data,
446-
CURLOPT_USERAGENT => $this->getUserAgent(),
447-
CURLOPT_HTTPHEADER => [
448-
"Expect:",
449-
"Content-Type: application/x-www-form-urlencoded", //UTF-8 implied
450-
"Content-Length: " . strlen($data),
451-
"Connection: keep-alive"
452-
]
453-
] + $this->curlopts);
454-
455431

456-
// @codeCoverageIgnoreEnd
457-
curl_setopt_array($curl, [
432+
curl_setopt_array($this->chandle, [
458433
// CURLOPT_VERBOSE => $this->debugMode,
434+
CURLOPT_URL => $cfg["CONNECTION_URL"],
459435
CURLOPT_CONNECTTIMEOUT => 5, // 5s
460436
CURLOPT_TIMEOUT => $this->settings["socketTimeout"],
461437
CURLOPT_POST => 1,
462-
CURLOPT_POSTFIELDS => $data,
463438
CURLOPT_HEADER => 0,
464439
CURLOPT_RETURNTRANSFER => 1,
440+
CURLOPT_POSTFIELDS => $data,
465441
CURLOPT_USERAGENT => $this->getUserAgent(),
466442
CURLOPT_HTTPHEADER => [
467443
"Expect:",
468444
"Content-Type: application/x-www-form-urlencoded", //UTF-8 implied
469-
"Content-Length: " . strlen($data)
445+
"Content-Length: " . strlen($data),
446+
"Connection: keep-alive"
470447
]
471448
] + $this->curlopts);
472449

473450
// which is by default tested for by phpStan
474451
/** @var string|false $r */
475-
$r = curl_exec($curl);
452+
$r = curl_exec($this->chandle);
476453
$error = null;
477454
if ($r === false) {
478-
$error = curl_error($curl);
455+
$error = curl_error($this->chandle);
479456
$r = "httperror|" . $error;
480457
}
481458
$response = new Response($r, $mycmd, $cfg);
@@ -540,8 +517,8 @@ public function requestAllResponsePages($cmd)
540517
*/
541518
public function close()
542519
{
543-
foreach ($this->curlcache as $curl) {
544-
curl_close($curl);
520+
if (!is_null($this->chandle)) {
521+
curl_close($this->chandle);
545522
}
546523
}
547524

Diff for: src/HEXONET/Response.php

+8-8
Original file line numberDiff line numberDiff line change
@@ -24,46 +24,46 @@ class Response // implements \CNIC\ResponseInterface
2424
* The API Command used within this request
2525
* @var array<string>
2626
*/
27-
private $command;
27+
protected $command;
2828

2929
/**
3030
* plain API response
3131
* @var string
3232
*/
33-
private $raw;
33+
protected $raw;
3434

3535
/**
3636
* hash representation of plain API response
3737
* @var array<string,mixed>
3838
*/
39-
private $hash;
39+
protected $hash;
4040

4141
/**
4242
* Regex for pagination related column keys
4343
* @var string
4444
*/
45-
private $paginationkeys = "/^TOTAL|COUNT|LIMIT|FIRST|LAST$/";
45+
protected $paginationkeys = "/^TOTAL|COUNT|LIMIT|FIRST|LAST$/";
4646

4747
/**
4848
* Column names available in this responsse
4949
* @var string[]
5050
*/
51-
private $columnkeys;
51+
protected $columnkeys;
5252
/**
5353
* Container of Column Instances
5454
* @var Column[]
5555
*/
56-
private $columns;
56+
protected $columns;
5757
/**
5858
* Record Index we currently point to in record list
5959
* @var int
6060
*/
61-
private $recordIndex;
61+
protected $recordIndex;
6262
/**
6363
* Record List (List of rows)
6464
* @var Record[]
6565
*/
66-
private $records;
66+
protected $records;
6767

6868
/**
6969
* Constructor

Diff for: src/HEXONET/SessionClient.php

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717

1818
class SessionClient extends Client
1919
{
20-
public function __construct(string $cfgfile = "")
20+
public function __construct()
2121
{
22-
if (empty($cfgfile)) {
23-
parent::__construct(implode(DIRECTORY_SEPARATOR, [__DIR__, "config.json"]));
24-
} else {
25-
parent::__construct($cfgfile);
22+
$reflection = new \ReflectionClass(get_called_class());
23+
$fname = $reflection->getFileName();
24+
if ($fname === false) {
25+
throw new \Exception("Reflection failed");
2626
}
27+
$cfgpath = implode(DIRECTORY_SEPARATOR, [dirname($fname), "config.json"]);
28+
parent::__construct($cfgpath);
2729
}
2830

2931
/**

Diff for: src/HEXONET/SocketConfig.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ protected function getPOSTDataParams($command, $secured)
121121

122122
/**
123123
* Create POST data string out of connection data
124-
* @param array<mixed> $command API Command to request
124+
* @param array<int|string,mixed> $command API Command to request
125125
* @param bool $secured if password has to be returned "hidden"
126126
* @return string POST data string
127127
*/

0 commit comments

Comments
 (0)